aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/java
diff options
context:
space:
mode:
authorGravatar Adam Michael <ajmichael@google.com>2017-09-21 15:00:07 -0400
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2017-10-05 00:18:35 +0200
commitb4ebfd724d33223ac78190be88c6f8704c249651 (patch)
tree7dcf4db51a9d5fad13ad17c69074b64e02228418 /third_party/java
parent74776b409214846aa3fe3a41a3447c6412dc046c (diff)
Add proguard 5.3.3 to third_party.
See https://github.com/bazelbuild/bazel/issues/3777 The Android SDK provides a very old proguard and will be removing it soon, so we need to bundle our own. Change-Id: I054c54130bef1befc8591598768184fe23f76161 RELNOTES: None
Diffstat (limited to 'third_party/java')
-rw-r--r--third_party/java/proguard/BUILD17
-rw-r--r--third_party/java/proguard/BUILD.tools11
-rw-r--r--third_party/java/proguard/proguard5.3.3/README33
-rw-r--r--third_party/java/proguard/proguard5.3.3/bin/proguard.bat14
-rwxr-xr-xthird_party/java/proguard/proguard5.3.3/bin/proguard.sh24
-rw-r--r--third_party/java/proguard/proguard5.3.3/bin/proguardgui.bat14
-rwxr-xr-xthird_party/java/proguard/proguard5.3.3/bin/proguardgui.sh27
-rw-r--r--third_party/java/proguard/proguard5.3.3/bin/retrace.bat14
-rwxr-xr-xthird_party/java/proguard/proguard5.3.3/bin/retrace.sh24
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/README42
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/build.gradle111
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/build.properties4
-rwxr-xr-xthird_party/java/proguard/proguard5.3.3/buildscripts/build.sh112
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/build.xml210
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/makefile109
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/maven/ant/pom.xml78
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/maven/base/pom.xml72
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/maven/gradle/pom.xml97
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/maven/gui/pom.xml78
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/maven/pom.xml165
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/maven/retrace/pom.xml61
-rw-r--r--third_party/java/proguard/proguard5.3.3/buildscripts/maven/wtk/pom.xml79
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/FAQ.html304
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/GPL.html406
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/GPL_exception.html54
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/acknowledgements.html89
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/alternatives.html790
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/android_shades.pngbin0 -> 2726 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/checkmark.gifbin0 -> 63 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/dexguard.pngbin0 -> 5331 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/downloads.html803
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/drop1.gifbin0 -> 803 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/drop2.gifbin0 -> 620 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/drop3.gifbin0 -> 175 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/favicon.icobin0 -> 7406 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/feedback.html104
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.eotbin0 -> 21190 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.svg146
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.ttfbin0 -> 21012 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.woffbin0 -> 14036 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.eotbin0 -> 23866 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.svg146
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.ttfbin0 -> 23680 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.woffbin0 -> 15836 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.eotbin0 -> 20878 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.svg146
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.ttfbin0 -> 20688 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.woffbin0 -> 13988 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/guardsquare.pngbin0 -> 2946 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/index.html96
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/license.html58
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/main.html108
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/android_small.pngbin0 -> 1106 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/ant.html661
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/attention.gifbin0 -> 896 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/attributes.html217
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/examples.html1693
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/gradle.html561
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/gui.html483
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/index.html41
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/introduction.html173
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/limitations.html63
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/optimizations.html202
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/refcard.html493
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/retrace/examples.html182
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/retrace/index.html26
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/retrace/introduction.html80
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/retrace/usage.html143
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/sections.html54
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/style.css184
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/troubleshooting.html933
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/usage.html1271
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/manual/wtk.html71
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/proguard.appdata.xml32
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/quality.html57
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/results.html170
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshot_console.gifbin0 -> 18930 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshot_console_small.gifbin0 -> 19730 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshot_gui1.gifbin0 -> 42755 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshot_gui2.gifbin0 -> 36887 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshot_gui3.gifbin0 -> 37080 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshot_gui4.gifbin0 -> 40769 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshot_gui5.gifbin0 -> 35909 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshot_gui6.gifbin0 -> 37123 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshot_gui7.gifbin0 -> 41922 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshot_gui8.gifbin0 -> 31454 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshots.html68
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/screenshots_gui_small.gifbin0 -> 161022 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/sections.html49
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/sflogo.pngbin0 -> 469 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/steel.gifbin0 -> 2759 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/style.css278
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/testimonials.html132
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/title.gifbin0 -> 2613 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/docs/title.html17
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/android.pro174
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/examples.pro60
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Applet.java23
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Application.java21
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Bean.java57
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/examples/NativeCallBack.java52
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/lib/annotations.jarbin0 -> 6123 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/lib/annotations.pro118
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/Keep.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepApplication.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepClassMemberNames.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepClassMembers.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepGettersSetters.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepImplementations.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepName.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicClassMemberNames.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicClassMembers.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicGettersSetters.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicImplementations.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicProtectedClassMemberNames.java18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicProtectedClassMembers.java19
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/ant/applets.xml88
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/ant/applications1.xml15
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/ant/applications2.xml74
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/ant/applications3.xml98
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/ant/library.xml102
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/ant/midlets.xml52
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/ant/proguard.xml89
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/ant/servlets.xml88
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/applets.pro69
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/applications.pro75
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/dictionaries/compact.txt18
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/dictionaries/keywords.txt58
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/dictionaries/shakespeare.txt23
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/dictionaries/windows.txt209
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/gradle/android.gradle195
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/gradle/applets.gradle90
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/gradle/applications.gradle96
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/gradle/library.gradle99
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/gradle/midlets.gradle88
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/gradle/proguard.gradle92
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/gradle/proguardall.gradle94
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/gradle/proguardgui.gradle72
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/gradle/retrace.gradle64
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/gradle/scala.gradle153
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/gradle/servlets.gradle91
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/library.pro79
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/midlets.pro67
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/proguard.pro70
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/proguardall.pro72
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/proguardgui.pro51
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/retrace.pro43
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/scala.pro132
-rw-r--r--third_party/java/proguard/proguard5.3.3/examples/servlets.pro70
-rw-r--r--third_party/java/proguard/proguard5.3.3/lib/proguard.jarbin0 -> 870966 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/lib/proguardgui.jarbin0 -> 140183 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/lib/retrace.jarbin0 -> 10482 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ArgumentWordReader.java111
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/AssumeNoSideEffectsChecker.java98
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ClassMemberChecker.java158
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ClassPath.java94
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ClassPathEntry.java384
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecification.java259
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecificationVisitorFactory.java529
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/Configuration.java331
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationChecker.java224
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationConstants.java126
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationParser.java1364
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationWriter.java661
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/DataEntryReaderFactory.java159
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/DataEntryWriterFactory.java162
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/DescriptorKeepChecker.java168
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/DuplicateClassPrinter.java63
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/FileWordReader.java55
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/FullyQualifiedClassNameChecker.java200
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/GPL.java196
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/GetAnnotationChecker.java80
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/GetEnclosingClassChecker.java76
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/GetEnclosingMethodChecker.java76
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/GetSignatureChecker.java78
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/Initializer.java576
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/InputReader.java191
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/KeepClassMemberChecker.java86
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/KeepClassSpecification.java151
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/LibraryKeepChecker.java115
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/LineWordReader.java74
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/MANIFEST.MF2
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/MemberSpecification.java114
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/OutputWriter.java219
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ParseException.java51
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java558
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/SeedPrinter.java91
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/SubclassedClassFilter.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/Targeter.java88
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/UpToDateChecker.java232
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/WordReader.java387
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ant/ClassPathElement.java207
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ant/ClassSpecificationElement.java259
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ant/ConfigurationElement.java123
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ant/ConfigurationTask.java450
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ant/FilterElement.java85
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ant/KeepSpecificationElement.java95
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ant/MemberSpecificationElement.java218
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ant/ProGuardTask.java357
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ant/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ant/task.properties2
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ClassConstants.java345
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ClassPool.java160
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Clazz.java266
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Field.java32
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/JavaConstants.java89
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryClass.java553
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryField.java77
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryMember.java104
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryMethod.java85
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Member.java57
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Method.java32
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramClass.java584
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramField.java93
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramMember.java140
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramMethod.java101
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/VisitorAccepter.java47
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/Attribute.java143
-rwxr-xr-xthird_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/BootstrapMethodInfo.java89
-rwxr-xr-xthird_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java93
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/CodeAttribute.java202
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ConstantValueAttribute.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/DeprecatedAttribute.java66
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/EnclosingMethodAttribute.java132
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExceptionInfo.java100
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExceptionsAttribute.java80
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExtendedLineNumberInfo.java63
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/InnerClassesAttribute.java80
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/InnerClassesInfo.java119
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LineNumberInfo.java61
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LineNumberTableAttribute.java174
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableInfo.java135
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTableAttribute.java79
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTypeInfo.java143
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java79
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/MethodParametersAttribute.java80
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ParameterInfo.java81
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SignatureAttribute.java111
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SourceDirAttribute.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SourceFileAttribute.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SyntheticAttribute.java66
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/UnknownAttribute.java84
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/Annotation.java143
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java73
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java76
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java114
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ArrayElementValue.java82
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ClassElementValue.java104
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ConstantElementValue.java71
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ElementValue.java126
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java138
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java83
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java70
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleTypeAnnotationsAttribute.java77
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java70
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleTypeAnnotationsAttribute.java77
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypeAnnotation.java162
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypeAnnotationsAttribute.java98
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypePathInfo.java50
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/package.html4
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/CatchTargetInfo.java82
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/EmptyTargetInfo.java72
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/FormalParameterTargetInfo.java81
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetElement.java53
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetInfo.java99
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/OffsetTargetInfo.java82
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/SuperTypeTargetInfo.java72
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TargetInfo.java97
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/ThrowsTargetInfo.java81
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeArgumentTargetInfo.java85
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeParameterBoundTargetInfo.java87
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeParameterTargetInfo.java79
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/visitor/LocalVariableTargetElementVisitor.java37
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/visitor/TargetInfoVisitor.java50
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java161
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java206
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java110
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java42
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java51
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/TypeAnnotationVisitor.java41
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/TypePathInfoVisitor.java41
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/DoubleType.java66
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/FloatType.java66
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/FullFrame.java202
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/IntegerType.java66
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/LessZeroFrame.java103
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/LongType.java66
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java161
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/NullType.java66
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/ObjectType.java107
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/SameOneFrame.java115
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/SameZeroFrame.java74
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapAttribute.java91
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapFrame.java117
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java93
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/TopType.java66
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/UninitializedThisType.java66
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/UninitializedType.java106
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/VerificationType.java103
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java112
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java40
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java65
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java117
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java55
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java55
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java55
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllLineNumberInfoVisitor.java55
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java467
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AttributeVisitor.java101
-rwxr-xr-xthird_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java38
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java37
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java38
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java38
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LineNumberRangeFinder.java89
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java38
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java38
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java446
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java373
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/ParameterInfoVisitor.java37
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java443
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/StackSizeComputer.java389
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/ClassConstant.java105
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/Constant.java68
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/DoubleConstant.java82
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/FieldrefConstant.java71
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/FloatConstant.java82
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/IntegerConstant.java82
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/InterfaceMethodrefConstant.java71
-rwxr-xr-xthird_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/InvokeDynamicConstant.java148
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/LongConstant.java82
-rwxr-xr-xthird_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodHandleConstant.java132
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodTypeConstant.java125
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodrefConstant.java71
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/NameAndTypeConstant.java119
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/RefConstant.java130
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/StringConstant.java135
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/Utf8Constant.java285
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/AllConstantVisitor.java53
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/BootstrapMethodArgumentVisitor.java56
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java96
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ConstantTagFilter.java86
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ConstantVisitor.java49
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java64
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/MethodrefTraveler.java59
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/SuperClassConstantVisitor.java69
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AccessFixer.java262
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AnnotationAdder.java153
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AnnotationsAttributeEditor.java67
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributeAdder.java500
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributeSorter.java89
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributesEditor.java314
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodInfoAdder.java86
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodRemapper.java88
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodsAttributeAdder.java91
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodsAttributeEditor.java60
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BridgeMethodFixer.java117
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassEditor.java255
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassElementSorter.java52
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassMemberSorter.java69
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassReferenceFixer.java591
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeComposer.java1069
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeEditor.java1267
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeEditorResetter.java60
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ComparableConstant.java276
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantAdder.java256
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolEditor.java784
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolRemapper.java688
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolShrinker.java604
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolSorter.java123
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ElementValueAdder.java217
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ElementValuesEditor.java238
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionAdder.java65
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionInfoAdder.java67
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionsAttributeEditor.java68
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InnerClassesAccessFixer.java83
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InstructionAdder.java76
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InstructionWriter.java320
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceAdder.java59
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceDeleter.java209
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceSorter.java246
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfacesEditor.java109
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberInfoAdder.java91
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java67
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberTableAttributeTrimmer.java78
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableInfoAdder.java67
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java57
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java68
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java58
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MemberAdder.java294
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MemberReferenceFixer.java447
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MethodInvocationFixer.java242
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/NameAndTypeShrinker.java195
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/NamedAttributeDeleter.java82
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java56
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ParameterInfoAdder.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/StackSizeUpdater.java54
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/SubclassAdder.java59
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/SubclassToAdder.java60
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/Utf8Shrinker.java483
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableCleaner.java271
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableEditor.java130
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableRemapper.java218
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableSizeUpdater.java105
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/BranchInstruction.java180
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/ConstantInstruction.java309
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/Instruction.java1137
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionConstants.java449
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionFactory.java300
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionUtil.java67
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/LookUpSwitchInstruction.java135
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/SimpleInstruction.java255
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/SwitchInstruction.java83
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/TableSwitchInstruction.java139
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/VariableInstruction.java372
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/package.html9
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java56
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java63
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionCounter.java59
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionVisitor.java42
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java131
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/LibraryClassReader.java383
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/ProgramClassReader.java1118
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/ProgramClassWriter.java873
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/RuntimeDataInput.java223
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/RuntimeDataOutput.java261
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/package.html15
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/AccessUtil.java105
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/AllParameterVisitor.java239
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassReferenceInitializer.java587
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassSubHierarchyInitializer.java77
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java163
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassUtil.java1311
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DescriptorClassEnumeration.java252
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DynamicClassReferenceInitializer.java486
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java942
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/EnumFieldReferenceInitializer.java149
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ExternalTypeEnumeration.java106
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/InstructionSequenceMatcher.java754
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/InternalTypeEnumeration.java254
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/MemberFinder.java197
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/MethodLinker.java159
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/SimplifiedVisitor.java1114
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/StringReferenceInitializer.java90
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/StringSharer.java172
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/WarningPrinter.java136
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllClassVisitor.java47
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllFieldVisitor.java55
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllMemberVisitor.java57
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllMethodVisitor.java55
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/BottomClassFilter.java69
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassAccessFilter.java88
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCleaner.java364
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCollector.java58
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCounter.java56
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassHierarchyTraveler.java91
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassNameFilter.java112
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolFiller.java55
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolRemover.java54
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolVisitor.java37
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPresenceFilter.java93
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPrinter.java1183
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVersionFilter.java85
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVersionSetter.java83
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVisitor.java36
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java100
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/DotClassClassVisitor.java89
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/DynamicReturnedClassVisitor.java68
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptClassFilter.java69
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptClassesFilter.java90
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionCounter.java52
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java64
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionHandlerFilter.java70
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionOffsetFilter.java64
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionRangeFilter.java68
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java69
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementedClassFilter.java71
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java70
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/InitializerMethodFilter.java108
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/LibraryClassFilter.java60
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/LibraryMemberFilter.java73
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberAccessFilter.java122
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberClassAccessFilter.java106
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberCollector.java59
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberCounter.java72
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberDescriptorFilter.java113
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberDescriptorReferencedClassVisitor.java65
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberNameFilter.java114
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberToClassVisitor.java90
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberVisitor.java40
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MethodImplementationFilter.java70
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MethodImplementationTraveler.java128
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiClassPoolVisitor.java88
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiClassVisitor.java97
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiMemberVisitor.java113
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedClassVisitor.java49
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedFieldVisitor.java61
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedMethodVisitor.java61
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ParameterVisitor.java56
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ProgramClassFilter.java60
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ProgramMemberFilter.java73
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ReferencedClassVisitor.java269
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ReferencedMemberVisitor.java73
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SimilarMemberVisitor.java125
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SimpleClassPrinter.java167
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SubclassFilter.java91
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SubclassTraveler.java60
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/VariableClassVisitor.java78
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/VariableMemberVisitor.java96
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/package.html40
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BasicBranchUnit.java126
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BasicInvocationUnit.java426
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BranchTargetFinder.java763
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BranchUnit.java63
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/ClassConstantValueFactory.java51
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/ConstantValueFactory.java113
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/InvocationUnit.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Processor.java927
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Stack.java560
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/TracedStack.java374
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/TracedVariables.java199
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Variables.java347
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ArrayReferenceValue.java165
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Category1Value.java41
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Category2Value.java41
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ComparisonValue.java69
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeDoubleValue.java81
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeFloatValue.java81
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeIntegerValue.java87
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeLongValue.java87
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedByteValue.java64
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedCharacterValue.java64
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedDoubleValue.java64
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedFloatValue.java64
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedIntegerValue.java64
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedLongValue.java64
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedShortValue.java64
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DetailedArrayReferenceValue.java301
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DetailedValueFactory.java48
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DoubleValue.java359
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/FloatValue.java359
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedArrayReferenceValue.java159
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedDoubleValue.java67
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedFloatValue.java67
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedIntegerValue.java67
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedLongValue.java67
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedReferenceValue.java159
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedValueFactory.java92
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/InitialValueFactory.java79
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/InstructionOffsetValue.java320
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IntegerValue.java1002
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/LongValue.java554
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedDoubleValue.java71
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedFloatValue.java71
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedIntegerValue.java71
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedLongValue.java71
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularDoubleValue.java221
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularFloatValue.java221
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularIntegerValue.java383
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularLongValue.java271
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularValueFactory.java111
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ReferenceValue.java305
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificDoubleValue.java186
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificFloatValue.java186
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificIntegerValue.java354
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificLongValue.java259
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/TopValue.java79
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/TypedReferenceValue.java620
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownDoubleValue.java125
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownFloatValue.java125
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownIntegerValue.java216
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownLongValue.java160
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Value.java169
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ValueFactory.java176
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gradle/ProGuardTask.java1625
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassPathPanel.java447
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassSpecificationDialog.java562
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassSpecificationsPanel.java231
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/ExtensionFileFilter.java78
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/FilterBuilder.java208
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/FilterDialog.java373
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/GUIResources.java56
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/GUIResources.properties659
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/KeepSpecificationsPanel.java85
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/ListPanel.java340
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/MANIFEST.MF3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/MemberSpecificationDialog.java509
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/MemberSpecificationsPanel.java304
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/MessageDialogRunnable.java89
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/OptimizationsDialog.java251
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/ProGuardGUI.java1778
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/ProGuardRunnable.java154
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/ReTraceRunnable.java125
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/SwingUtil.java82
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/TabbedPane.java229
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/TextAreaOutputStream.java80
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/TextAreaWriter.java80
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/arrow.gifbin0 -> 112 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/boilerplate.pro384
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/default.pro292
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/BufferedSprite.java145
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/CircleSprite.java74
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ClipSprite.java85
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ColorSprite.java65
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/CompositeSprite.java56
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantColor.java51
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantDouble.java49
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantFont.java46
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantInt.java49
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantString.java49
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantTiming.java57
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/FontSprite.java65
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ImageSprite.java76
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearColor.java72
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearDouble.java55
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearInt.java55
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearTiming.java55
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/OverrideGraphics2D.java598
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/RectangleSprite.java114
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SawToothTiming.java53
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ShadowedSprite.java109
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SineTiming.java53
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SmoothTiming.java66
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SplashPanel.java235
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/Sprite.java41
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TextSprite.java89
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TimeSwitchSprite.java75
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/Timing.java34
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TypeWriterString.java71
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableColor.java36
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableDouble.java34
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableFont.java36
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableInt.java34
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableSizeFont.java65
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableString.java34
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/package.html4
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/gui/vtitle.pngbin0 -> 23313 bytes
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/CascadingDataEntryWriter.java94
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassFilter.java57
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassReader.java115
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassRewriter.java80
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntry.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryClassWriter.java85
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryCopier.java360
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryDirectoryFilter.java38
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryFilter.java38
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryNameFilter.java54
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryObfuscator.java150
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryParentFilter.java51
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryPump.java43
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryReader.java38
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryRenamer.java104
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryRewriter.java148
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryWriter.java73
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryFilter.java52
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryPump.java86
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryWriter.java165
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/FileDataEntry.java96
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/FilteredDataEntryReader.java90
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/FilteredDataEntryWriter.java125
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/Finisher.java37
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/JarReader.java75
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/JarWriter.java234
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/ManifestRewriter.java211
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/NameFilter.java83
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/ParentDataEntryWriter.java75
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/RenamedDataEntry.java83
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/ZipDataEntry.java105
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/io/package.html4
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/AttributeShrinker.java120
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/AttributeUsageMarker.java71
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ClassObfuscator.java569
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ClassRenamer.java109
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/DictionaryNameFactory.java189
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MapCleaner.java57
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingKeeper.java180
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingPrinter.java365
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingProcessor.java86
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingReader.java238
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameCleaner.java60
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameCollector.java105
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameConflictFixer.java158
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameFilter.java120
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberObfuscator.java229
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberSpecialNameFilter.java101
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MultiMappingProcessor.java105
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameFactory.java34
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameFactoryResetter.java59
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameMarker.java164
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NumericNameFactory.java46
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/Obfuscator.java476
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ParameterNameMarker.java128
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SimpleNameFactory.java156
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SourceFileRenamer.java84
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SpecialNameFactory.java83
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/BootstrapMethodArgumentShrinker.java104
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ChangedCodePrinter.java350
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ConstantMemberFilter.java77
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ConstantParameterFilter.java78
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/DuplicateInitializerFixer.java215
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/DuplicateInitializerInvocationFixer.java165
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeepMarker.java103
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeptClassFilter.java69
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeptMemberFilter.java87
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MemberDescriptorSpecializer.java138
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MethodDescriptorShrinker.java352
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MethodStaticizer.java87
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/OptimizationInfoClassFilter.java72
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/OptimizationInfoMemberFilter.java93
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/Optimizer.java1126
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ParameterShrinker.java150
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/TailRecursionSimplifier.java355
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/WriteOnlyFieldFilter.java65
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/EvaluationShrinker.java2370
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/EvaluationSimplifier.java1392
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/LivenessAnalyzer.java526
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/LoadingInvocationUnit.java164
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/PartialEvaluator.java1308
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumArrayPropagator.java94
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumClassChecker.java75
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumClassSimplifier.java164
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumDescriptorSimplifier.java799
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumUseChecker.java766
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java818
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/StoringInvocationUnit.java207
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/TracedBranchUnit.java59
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/VariableOptimizer.java357
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/package.html4
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/AccessMethodMarker.java201
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/BackwardBranchMarker.java90
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CatchExceptionMarker.java69
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CaughtClassFilter.java63
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CaughtClassMarker.java63
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ClassOptimizationInfo.java177
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ClassOptimizationInfoSetter.java47
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DotClassFilter.java63
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DotClassMarker.java96
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DynamicInvocationMarker.java79
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ExceptionInstructionChecker.java260
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/FieldOptimizationInfo.java188
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstanceofClassFilter.java63
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstanceofClassMarker.java93
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstantiationClassFilter.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstantiationClassMarker.java93
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MemberOptimizationInfoSetter.java59
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MethodInvocationMarker.java107
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MethodOptimizationInfo.java336
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NoSideEffectMethodMarker.java91
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NonEmptyStackReturnMarker.java115
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NonPrivateMemberMarker.java171
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java85
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java129
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ParameterUsageMarker.java285
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ReadWriteFieldMarker.java163
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectInstructionChecker.java375
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectMethodFilter.java73
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectMethodMarker.java181
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SimpleEnumFilter.java96
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SimpleEnumMarker.java75
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java65
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SuperInvocationMarker.java93
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/VariableUsageMarker.java96
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/package.html4
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/package.html4
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ClassFinalizer.java84
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ClassMerger.java742
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java264
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoGotoReplacer.java115
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoReturnReplacer.java115
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/HorizontalClassMerger.java89
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequenceConstants.java5128
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequenceReplacer.java422
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequencesReplacer.java139
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/LineNumberLinearizer.java250
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MemberPrivatizer.java103
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MethodFinalizer.java93
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MethodInliner.java712
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/NopRemover.java89
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/PeepholeOptimizer.java104
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ReachableCodeMarker.java262
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/RetargetedClassFilter.java96
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java170
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/TargetClassChanger.java508
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/UnreachableCodeRemover.java143
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/UnreachableExceptionRemover.java156
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/VariableShrinker.java133
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/VerticalClassMerger.java88
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/package.html5
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/preverify/CodePreverifier.java623
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/preverify/CodeSubroutineInliner.java402
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/preverify/Preverifier.java68
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/preverify/SubroutineInliner.java73
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FrameInfo.java108
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FramePattern.java303
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FrameRemapper.java435
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/retrace/MANIFEST.MF3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/retrace/ReTrace.java305
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/retrace/package.html4
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/AnnotationUsageMarker.java327
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ClassShrinker.java567
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/InnerUsageMarker.java174
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/InterfaceUsageMarker.java152
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/LocalVariableTypeUsageMarker.java177
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsageMark.java183
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsageMarker.java277
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsagePrinter.java220
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/Shrinker.java192
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsageMarker.java1125
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsagePrinter.java184
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsedClassFilter.java74
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsedMemberFilter.java93
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/shrink/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/AndMatcher.java49
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/ArrayUtil.java1015
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/ClassNameParser.java215
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/ConstantMatcher.java48
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/EmptyStringMatcher.java36
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/ExtensionMatcher.java62
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/FileNameParser.java121
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/FixedStringMatcher.java60
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/ListMatcher.java69
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/ListParser.java137
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/ListUtil.java180
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/NameParser.java106
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/NotMatcher.java46
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/ObjectUtil.java67
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/OrMatcher.java49
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/SettableMatcher.java46
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/StringMatcher.java51
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/StringParser.java35
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/VariableStringMatcher.java126
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/util/package.html3
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/wtk/ProGuardObfuscator.java142
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/wtk/default.pro114
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/wtk/package.html3
852 files changed, 144778 insertions, 0 deletions
diff --git a/third_party/java/proguard/BUILD b/third_party/java/proguard/BUILD
new file mode 100644
index 0000000000..345346e175
--- /dev/null
+++ b/third_party/java/proguard/BUILD
@@ -0,0 +1,17 @@
+licenses(["restricted"]) # GNU GPL v2
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+ visibility = ["//third_party:__pkg__"],
+)
+
+filegroup(
+ name = "embedded_tools",
+ srcs = [
+ "BUILD.tools",
+ "proguard5.3.3/docs/GPL.html",
+ "proguard5.3.3/lib/proguard.jar",
+ ],
+ visibility = ["//src:__pkg__"],
+)
diff --git a/third_party/java/proguard/BUILD.tools b/third_party/java/proguard/BUILD.tools
new file mode 100644
index 0000000000..ae54c33140
--- /dev/null
+++ b/third_party/java/proguard/BUILD.tools
@@ -0,0 +1,11 @@
+java_import(
+ name = "proguard_import",
+ jars = ["proguard5.3.3/lib/proguard.jar"],
+)
+
+java_binary(
+ name = "proguard",
+ main_class = "proguard.ProGuard",
+ runtime_deps = [":proguard_import"],
+ visibility = ["//visibility:public"],
+)
diff --git a/third_party/java/proguard/proguard5.3.3/README b/third_party/java/proguard/proguard5.3.3/README
new file mode 100644
index 0000000000..1b3a54f8c5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/README
@@ -0,0 +1,33 @@
+ProGuard, Java class file shrinker, optimizer, obfuscator, and preverifier
+==========================================================================
+
+This distribution contains the following directories:
+
+- bin : simple wrapper scripts to run ProGuard, its GUI, and ReTrace
+- lib : the main jars, compiled and ready to use with "java -jar ...."
+- docs : the complete documentation, licenses, etc. in html format
+- examples : some example configuration files
+- src : the source code
+- buildscripts : various alternative build scripts
+
+
+The best place to start is docs/index.html
+
+
+Example
+-------
+
+If you want to give ProGuard a spin right away, try processing the ProGuard
+jar itself:
+
+ cd examples
+ java -jar ../lib/proguard.jar @proguard.pro
+
+The resulting proguard_out.jar contains the same application, but it's a lot
+smaller.
+
+Enjoy!
+
+http://proguard.sourceforge.net/
+
+Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
diff --git a/third_party/java/proguard/proguard5.3.3/bin/proguard.bat b/third_party/java/proguard/proguard5.3.3/bin/proguard.bat
new file mode 100644
index 0000000000..daf2c1a3ed
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/bin/proguard.bat
@@ -0,0 +1,14 @@
+@ECHO OFF
+
+REM Start-up script for ProGuard -- free class file shrinker, optimizer,
+REM obfuscator, and preverifier for Java bytecode.
+REM
+REM Note: when passing file names containing spaces to this script,
+REM you'll have to add escaped quotes around them, e.g.
+REM "\"C:/My Directory/My File.txt\""
+
+IF EXIST "%PROGUARD_HOME%" GOTO home
+SET PROGUARD_HOME=%~dp0\..
+:home
+
+java -jar "%PROGUARD_HOME%\lib\proguard.jar" %*
diff --git a/third_party/java/proguard/proguard5.3.3/bin/proguard.sh b/third_party/java/proguard/proguard5.3.3/bin/proguard.sh
new file mode 100755
index 0000000000..3ee60ed76e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/bin/proguard.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Start-up script for ProGuard -- free class file shrinker, optimizer,
+# obfuscator, and preverifier for Java bytecode.
+#
+# Note: when passing file names containing spaces to this script,
+# you'll have to add escaped quotes around them, e.g.
+# "\"/My Directory/My File.txt\""
+
+# Account for possibly missing/basic readlink.
+# POSIX conformant (dash/ksh/zsh/bash).
+PROGUARD=`readlink -f "$0" 2>/dev/null`
+if test "$PROGUARD" = ''
+then
+ PROGUARD=`readlink "$0" 2>/dev/null`
+ if test "$PROGUARD" = ''
+ then
+ PROGUARD="$0"
+ fi
+fi
+
+PROGUARD_HOME=`dirname "$PROGUARD"`/..
+
+java -jar "$PROGUARD_HOME/lib/proguard.jar" "$@"
diff --git a/third_party/java/proguard/proguard5.3.3/bin/proguardgui.bat b/third_party/java/proguard/proguard5.3.3/bin/proguardgui.bat
new file mode 100644
index 0000000000..c328f5b1f5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/bin/proguardgui.bat
@@ -0,0 +1,14 @@
+@ECHO OFF
+
+REM Start-up script for the GUI of ProGuard -- free class file shrinker,
+REM optimizer, obfuscator, and preverifier for Java bytecode.
+REM
+REM Note: when passing file names containing spaces to this script,
+REM you'll have to add escaped quotes around them, e.g.
+REM "\"C:/My Directory/My File.txt\""
+
+IF EXIST "%PROGUARD_HOME%" GOTO home
+SET PROGUARD_HOME=%~dp0\..
+:home
+
+java -jar "%PROGUARD_HOME%\lib\proguardgui.jar" %*
diff --git a/third_party/java/proguard/proguard5.3.3/bin/proguardgui.sh b/third_party/java/proguard/proguard5.3.3/bin/proguardgui.sh
new file mode 100755
index 0000000000..aba7f622d4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/bin/proguardgui.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Start-up script for the GUI of ProGuard -- free class file shrinker,
+# optimizer, obfuscator, and preverifier for Java bytecode.
+#
+# Note: when passing file names containing spaces to this script,
+# you'll have to add escaped quotes around them, e.g.
+# "\"/My Directory/My File.txt\""
+
+# Account for possibly missing/basic readlink.
+# POSIX conformant (dash/ksh/zsh/bash).
+PROGUARD=`readlink -f "$0" 2>/dev/null`
+if test "$PROGUARD" = ''
+then
+ PROGUARD=`readlink "$0" 2>/dev/null`
+ if test "$PROGUARD" = ''
+ then
+ PROGUARD="$0"
+ fi
+fi
+
+PROGUARD_HOME=`dirname "$PROGUARD"`/..
+
+# On Linux, Java 1.6.0_24 and higher hang when starting the GUI:
+# http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7027598
+# We're using the -D option as a workaround.
+java -DsuppressSwingDropSupport=true -jar "$PROGUARD_HOME/lib/proguardgui.jar" "$@"
diff --git a/third_party/java/proguard/proguard5.3.3/bin/retrace.bat b/third_party/java/proguard/proguard5.3.3/bin/retrace.bat
new file mode 100644
index 0000000000..ae16ddecb8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/bin/retrace.bat
@@ -0,0 +1,14 @@
+@ECHO OFF
+
+REM Start-up script for Retrace -- companion tool for ProGuard, free class file
+REM shrinker, optimizer, obfuscator, and preverifier for Java bytecode.
+REM
+REM Note: when passing file names containing spaces to this script,
+REM you'll have to add escaped quotes around them, e.g.
+REM "\"C:/My Directory/My File.txt\""
+
+IF EXIST "%PROGUARD_HOME%" GOTO home
+SET PROGUARD_HOME=%~dp0\..
+:home
+
+java -jar "%PROGUARD_HOME%\lib\retrace.jar" %*
diff --git a/third_party/java/proguard/proguard5.3.3/bin/retrace.sh b/third_party/java/proguard/proguard5.3.3/bin/retrace.sh
new file mode 100755
index 0000000000..2f274de9af
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/bin/retrace.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Start-up script for Retrace -- companion tool for ProGuard, free class file
+# shrinker, optimizer, obfuscator, and preverifier for Java bytecode.
+#
+# Note: when passing file names containing spaces to this script,
+# you'll have to add escaped quotes around them, e.g.
+# "\"/My Directory/My File.txt\""
+
+# Account for possibly missing/basic readlink.
+# POSIX conformant (dash/ksh/zsh/bash).
+PROGUARD=`readlink -f "$0" 2>/dev/null`
+if test "$PROGUARD" = ''
+then
+ PROGUARD=`readlink "$0" 2>/dev/null`
+ if test "$PROGUARD" = ''
+ then
+ PROGUARD="$0"
+ fi
+fi
+
+PROGUARD_HOME=`dirname "$PROGUARD"`/..
+
+java -jar "$PROGUARD_HOME/lib/retrace.jar" "$@"
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/README b/third_party/java/proguard/proguard5.3.3/buildscripts/README
new file mode 100644
index 0000000000..88c2591df3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/README
@@ -0,0 +1,42 @@
+ProGuard, Java class file shrinker, optimizer, obfuscator, and preverifier
+==========================================================================
+
+This directory contains a number of alternative ways to build ProGuard:
+
+- build.sh : a shell script for GNU/Linux
+- makefile : a makefile for GNU/Linux
+- build.gradle : a Gradle build file for all platforms
+- build.xml : an Ant build file for all platforms
+- maven/pom.xml : a Maven POM for building the Maven artifacts
+
+- As a final alternative, you can also easily compile the code from the
+ command line:
+
+ mkdir classes
+ javac -sourcepath src -d classes src/proguard/ProGuard.java
+ javac -sourcepath src -d classes src/proguard/gui/ProGuardGUI.java
+ javac -sourcepath src -d classes src/proguard/retrace/ReTrace.java
+
+ For the ProGuard Gradle task:
+
+ javac -sourcepath src -d classes -classpath ..... \
+ src/proguard/gradle/ProGuardTask.java
+
+ For the ProGuard Ant task:
+
+ javac -sourcepath src -d classes -classpath lib/ant.jar \
+ src/proguard/ant/ProGuardTask.java
+
+ For the Java Micro Edition Wireless Tool Kit (JME WTK) obfuscator plug-in:
+
+ javac -sourcepath src -d classes -classpath wtklib/kenv.zip \
+ src/proguard/wtk/ProGuardObfuscator.java
+
+Depending on the scripts, you may still need to install Gradle, Ant, Maven,
+and the JME WTK yourself.
+
+Enjoy!
+
+http://proguard.sourceforge.net/
+
+Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/build.gradle b/third_party/java/proguard/proguard5.3.3/buildscripts/build.gradle
new file mode 100644
index 0000000000..229efb26aa
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/build.gradle
@@ -0,0 +1,111 @@
+apply plugin: 'java'
+
+defaultTasks 'proguardJar', 'retraceJar', 'proguardguiJar'
+
+sourceCompatibility = JavaVersion.VERSION_1_6
+targetCompatibility = JavaVersion.VERSION_1_6
+
+sourceSets {
+ proguard {
+ java {
+ srcDirs = ['../src']
+ exclude 'proguard/gui/**'
+ exclude 'proguard/retrace/**'
+ exclude 'proguard/ant/**'
+ exclude 'proguard/gradle/**'
+ exclude 'proguard/wtk/**'
+ }
+ }
+
+ retrace {
+ java {
+ srcDirs = ['../src']
+ include 'proguard/retrace/**'
+ }
+ }
+
+ anttask {
+ java {
+ srcDirs = ['../src']
+ include 'proguard/ant/**'
+ }
+ resources {
+ srcDirs = ['../src']
+ include 'proguard/ant/**.properties'
+ }
+ }
+
+ gradletask {
+ java {
+ srcDirs = ['../src']
+ include 'proguard/gradle/**'
+ }
+ }
+
+ proguardgui {
+ java {
+ srcDirs = ['../src']
+ include 'proguard/gui/**'
+ }
+ resources {
+ srcDirs = ['../src']
+ include 'proguard/gui/**.properties'
+ include 'proguard/gui/**.pro'
+ include 'proguard/gui/**.png'
+ include 'proguard/gui/**.gif'
+ }
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ retraceCompile sourceSets.proguard.output
+ anttaskCompile sourceSets.proguard.output
+ anttaskCompile 'org.apache.ant:ant:1.7.0'
+ gradletaskCompile sourceSets.proguard.output
+ gradletaskCompile gradleApi()
+ gradletaskCompile localGroovy()
+ proguardguiCompile sourceSets.proguard.output
+ proguardguiCompile sourceSets.retrace.output
+}
+
+task proguardJar(type: Jar) {
+ from sourceSets.proguard.output
+ from sourceSets.anttask.output
+ from sourceSets.gradletask.output
+ destinationDir = file('../lib')
+ baseName = 'proguard'
+
+ manifest.from '../src/proguard/MANIFEST.MF'
+
+ // Delete the original jar first, otherwise the
+ // jar task will not overwrite the file.
+ file('../lib/proguard.jar').delete()
+}
+
+task retraceJar(type: Jar) {
+ from sourceSets.retrace.output
+ destinationDir = file('../lib')
+ baseName = 'retrace'
+
+ manifest.from '../src/proguard/retrace/MANIFEST.MF'
+
+ // Delete the original jar first, otherwise the
+ // jar task will not overwrite the file.
+ file('../lib/retrace.jar').delete()
+}
+
+task proguardguiJar(type: Jar) {
+ from sourceSets.proguardgui.output
+ destinationDir = file('../lib')
+ baseName = 'proguardgui'
+
+ manifest.from '../src/proguard/gui/MANIFEST.MF'
+
+ // Delete the original jar first, otherwise the
+ // jar task will not overwrite the file.
+ file('../lib/proguardgui.jar').delete()
+}
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/build.properties b/third_party/java/proguard/proguard5.3.3/buildscripts/build.properties
new file mode 100644
index 0000000000..a6d2bbf5b0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/build.properties
@@ -0,0 +1,4 @@
+# Ant build properties for ProGuard.
+
+gradle.home = /usr/local/java/gradle
+wtk.home = /usr/local/java/wtk
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/build.sh b/third_party/java/proguard/proguard5.3.3/buildscripts/build.sh
new file mode 100755
index 0000000000..ef5cf0b290
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/build.sh
@@ -0,0 +1,112 @@
+#!/bin/bash
+#
+# GNU/Linux build script for ProGuard.
+
+#
+# Configuration.
+#
+
+ANT_HOME=${ANT_HOME:-/usr/local/java/ant}
+GRADLE_HOME=${GRADLE_HOME:-/usr/local/java/gradle}
+WTK_HOME=${WTK_HOME:-/usr/local/java/wtk}
+
+if [ -z $PROGUARD_HOME ]; then
+ PROGUARD_HOME=$(which "$0")
+ PROGUARD_HOME=$(dirname "$0")/..
+fi
+
+cd "$PROGUARD_HOME"
+
+SRC=src
+CLASSES=classes
+LIB=lib
+
+PROGUARD=proguard/ProGuard
+PROGUARD_GUI=proguard/gui/ProGuardGUI
+RETRACE=proguard/retrace/ReTrace
+ANT_TASK=proguard/ant/ProGuardTask
+GRADLE_TASK=proguard/gradle/ProGuardTask
+WTK_PLUGIN=proguard/wtk/ProGuardObfuscator
+
+ANT_JAR=$ANT_HOME/lib/ant.jar
+GRADLE_PATH=\
+$GRADLE_HOME/lib/plugins/gradle-plugins-*.jar:\
+$GRADLE_HOME/lib/gradle-logging-*.jar:\
+$GRADLE_HOME/lib/gradle-base-services-*.jar:\
+$GRADLE_HOME/lib/gradle-base-services-groovy-*.jar:\
+$GRADLE_HOME/lib/gradle-core-*.jar:\
+$GRADLE_HOME/lib/groovy-all-*.jar
+WTK_JAR=$WTK_HOME/wtklib/kenv.zip
+
+PROGUARD_JAR=$LIB/proguard.jar
+PROGUARD_GUI_JAR=$LIB/proguardgui.jar
+RETRACE_JAR=$LIB/retrace.jar
+
+#
+# Function definitions.
+#
+
+function compile {
+ # Compile java source files.
+ echo "Compiling ${1//\//.} ..."
+ javac -nowarn -Xlint:none -sourcepath "$SRC" -d "$CLASSES" \
+ "$SRC/$1.java" 2>&1 \
+ | sed -e 's|^| |'
+
+ # Copy resource files.
+ (cd "$SRC"; find $(dirname $1) -maxdepth 1 \
+ \( -name \*.properties -o -name \*.png -o -name \*.gif -o -name \*.pro \) \
+ -exec cp --parents {} "../$CLASSES" \; )
+}
+
+function createjar {
+ echo "Creating $2..."
+ jar -cfm "$2" "$SRC/$(dirname $1)/MANIFEST.MF" -C "$CLASSES" $(dirname $1)
+}
+
+function updatejar {
+ echo "Updating $PROGUARD_JAR..."
+ jar -uf "$PROGUARD_JAR" -C "$CLASSES" $(dirname $1)
+}
+
+#
+# Main script body.
+#
+
+mkdir -p "$CLASSES"
+
+compile $PROGUARD
+createjar $PROGUARD "$PROGUARD_JAR"
+
+compile $PROGUARD_GUI
+createjar $PROGUARD_GUI "$PROGUARD_GUI_JAR"
+
+compile $RETRACE
+createjar $RETRACE "$RETRACE_JAR"
+
+if [ -f "$ANT_JAR" ]; then
+ export CLASSPATH=$ANT_JAR
+ compile $ANT_TASK
+ updatejar $ANT_TASK
+else
+ echo "Please make sure the environment variable ANT_HOME is set correctly,"
+ echo "if you want to compile the optional ProGuard Ant task."
+fi
+
+if [ -f "${GRADLE_PATH%%:*}" ]; then
+ export CLASSPATH=$GRADLE_PATH
+ compile $GRADLE_TASK
+ updatejar $GRADLE_TASK
+else
+ echo "Please make sure the environment variable GRADLE_HOME is set correctly,"
+ echo "if you want to compile the optional ProGuard Gradle task."
+fi
+
+if [ -f "$WTK_JAR" ]; then
+ export CLASSPATH=$WTK_JAR
+ compile $WTK_PLUGIN
+ updatejar $WTK_PLUGIN
+else
+ echo "Please make sure the environment variable WTK_HOME is set correctly,"
+ echo "if you want to compile the optional ProGuard WTK plugin."
+fi
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/build.xml b/third_party/java/proguard/proguard5.3.3/buildscripts/build.xml
new file mode 100644
index 0000000000..370a76162d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/build.xml
@@ -0,0 +1,210 @@
+<!-- Ant build script for ProGuard. -->
+
+<project name = "proguard"
+ default = "all"
+ basedir = "..">
+
+ <property file = "buildscripts/build.properties"/>
+ <property name = "src" value = "src"/>
+ <property name = "classes" value = "classes"/>
+ <property name = "lib" value = "lib"/>
+
+ <path id="gradle.path">
+ <fileset dir="${gradle.home}/lib">
+ <include name="plugins/gradle-plugins-*.jar"/>
+ <include name="gradle-logging-*.jar"/>
+ <include name="gradle-base-services-*.jar"/>
+ <include name="gradle-base-services-groovy-*.jar"/>
+ <include name="gradle-core-*.jar"/>
+ <include name="groovy-all-*.jar"/>
+ </fileset>
+ </path>
+ <property name = "wtk.jar" value = "${wtk.home}/wtklib/kenv.zip"/>
+
+ <target name = "all" depends = "basic,options"/>
+ <target name = "basic" depends = "proguard,proguardgui,retrace"/>
+ <target name = "options" depends = "anttask,wtkplugin"/>
+
+ <target name = "proguard" depends = "classes,lib">
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "false"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/ProGuard.java">
+ <compilerarg value = "-Xlint:none"/>
+ </javac>
+
+ <copy todir = "${classes}">
+ <fileset dir = "${src}">
+ <include name = "proguard/*.properties"/>
+ <include name = "proguard/*.png"/>
+ <include name = "proguard/*.gif"/>
+ <include name = "proguard/*.pro"/>
+ </fileset>
+ </copy>
+
+ <jar jarfile = "${lib}/proguard.jar"
+ manifest = "${src}/proguard/MANIFEST.MF"
+ basedir = "${classes}"
+ includes = "proguard/**"/>
+ </target>
+
+ <target name = "proguardgui" depends = "proguard">
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "false"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/gui/ProGuardGUI.java">
+ <compilerarg value = "-Xlint:none"/>
+ </javac>
+
+ <copy todir = "${classes}">
+ <fileset dir = "${src}">
+ <include name = "proguard/gui/*.properties"/>
+ <include name = "proguard/gui/*.png"/>
+ <include name = "proguard/gui/*.gif"/>
+ <include name = "proguard/gui/*.pro"/>
+ </fileset>
+ </copy>
+
+ <jar jarfile = "${lib}/proguardgui.jar"
+ manifest = "${src}/proguard/gui/MANIFEST.MF"
+ basedir = "${classes}"
+ includes = "proguard/gui/**"/>
+ </target>
+
+ <target name = "retrace" depends = "classes,lib">
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "false"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/retrace/ReTrace.java">
+ <compilerarg value = "-Xlint:none"/>
+ </javac>
+
+ <copy todir = "${classes}">
+ <fileset dir = "${src}">
+ <include name = "proguard/retrace/*.properties"/>
+ <include name = "proguard/retrace/*.png"/>
+ <include name = "proguard/retrace/*.gif"/>
+ <include name = "proguard/retrace/*.pro"/>
+ </fileset>
+ </copy>
+
+ <jar jarfile = "${lib}/retrace.jar"
+ manifest = "${src}/proguard/retrace/MANIFEST.MF"
+ basedir = "${classes}"
+ includes = "proguard/retrace/**"/>
+ </target>
+
+ <target name = "anttask" depends = "proguard">
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "true"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/ant/ProGuardTask.java">
+ <compilerarg value = "-Xlint:none"/>
+ </javac>
+
+ <copy todir = "${classes}">
+ <fileset dir = "${src}">
+ <include name = "proguard/ant/*.properties"/>
+ <include name = "proguard/ant/*.png"/>
+ <include name = "proguard/ant/*.gif"/>
+ <include name = "proguard/ant/*.pro"/>
+ </fileset>
+ </copy>
+
+ <jar jarfile = "${lib}/proguard.jar"
+ update = "true"
+ basedir = "${classes}"
+ includes = "proguard/ant/**"/>
+ </target>
+
+ <target name = "gradletask" depends = "proguard">
+ <fail message="Please set the value of the property gradle.home in the file build.properties, if you want to build the optional ProGuard Gradle task.">
+ <condition>
+ <not>
+ <available classname="org.gradle.api.DefaultTask" classpathref="gradle.path"/>
+ </not>
+ </condition>
+ </fail>
+
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "false"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/gradle/ProGuardTask.java">
+ <compilerarg value = "-Xlint:none"/>
+ <classpath refid="gradle.path"/>
+ </javac>
+
+ <copy todir = "${classes}">
+ <fileset dir = "${src}">
+ <include name = "proguard/gradle/*.properties"/>
+ <include name = "proguard/gradle/*.png"/>
+ <include name = "proguard/gradle/*.gif"/>
+ <include name = "proguard/gradle/*.pro"/>
+ </fileset>
+ </copy>
+
+ <jar jarfile = "${lib}/proguard.jar"
+ update = "true"
+ basedir = "${classes}"
+ includes = "proguard/gradle/**"/>
+ </target>
+
+ <target name = "wtkplugin" depends = "proguard">
+ <fail message="Please set the value of the property wtk.home in the file build.properties, if you want to build the optional ProGuard WTK plugin.">
+ <condition>
+ <not>
+ <available file="${wtk.jar}"/>
+ </not>
+ </condition>
+ </fail>
+
+ <javac nowarn = "true"
+ deprecation = "false"
+ includeantruntime = "false"
+ classpath = "${wtk.jar}"
+ srcdir = "${src}"
+ destdir = "${classes}"
+ includes = "proguard/wtk/ProGuardObfuscator.java">
+ <compilerarg value = "-Xlint:none"/>
+ </javac>
+
+ <copy todir = "${classes}">
+ <fileset dir = "${src}">
+ <include name = "proguard/wtk/*.properties"/>
+ <include name = "proguard/wtk/*.png"/>
+ <include name = "proguard/wtk/*.gif"/>
+ <include name = "proguard/wtk/*.pro"/>
+ </fileset>
+ </copy>
+
+ <jar jarfile = "${lib}/proguard.jar"
+ update = "true"
+ basedir = "${classes}"
+ includes = "proguard/wtk/**"/>
+ </target>
+
+ <target name = "classes">
+ <mkdir dir = "${classes}"/>
+ </target>
+
+ <target name = "lib">
+ <mkdir dir = "${lib}"/>
+ </target>
+
+ <target name = "clean">
+ <delete>
+ <fileset dir = "${classes}"/>
+ <fileset dir = "${lib}"/>
+ </delete>
+ </target>
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/makefile b/third_party/java/proguard/proguard5.3.3/buildscripts/makefile
new file mode 100644
index 0000000000..4518a5342f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/makefile
@@ -0,0 +1,109 @@
+# GNU/Linux makefile for ProGuard.
+
+ANT_HOME = /usr/local/java/ant
+GRADLE_HOME = /usr/local/java/gradle
+WTK_HOME = /usr/local/java/wtk
+
+PROGUARD_HOME := $(subst ./..,..,$(subst /buildscripts/..,/,$(dir $(MAKEFILE_LIST))..))
+SRC = $(PROGUARD_HOME)/src
+CLASSES = $(PROGUARD_HOME)/classes
+LIB = $(PROGUARD_HOME)/lib
+
+ANT_JAR = $(ANT_HOME)/lib/ant.jar
+GRADLE_JARS = $(wildcard \
+ $(GRADLE_HOME)/lib/plugins/gradle-plugins-*.jar \
+ $(GRADLE_HOME)/lib/gradle-logging-*.jar \
+ $(GRADLE_HOME)/lib/gradle-base-services-*.jar \
+ $(GRADLE_HOME)/lib/gradle-base-services-groovy-*.jar \
+ $(GRADLE_HOME)/lib/gradle-core-*.jar \
+ $(GRADLE_HOME)/lib/groovy-all-*.jar)
+WTK_JAR = $(WTK_HOME)/wtklib/kenv.zip
+
+NOTHING:=
+SPACE:=$(NOTHING) $(NOTHING)
+CLASSPATH = $(ANT_JAR):$(subst $(SPACE),:,$(GRADLE_JARS)):$(WTK_JAR)
+
+PROGUARD = proguard/ProGuard
+PROGUARD_GUI = proguard/gui/ProGuardGUI
+RETRACE = proguard/retrace/ReTrace
+ANT_TASK = proguard/ant/ProGuardTask
+GRADLE_TASK = proguard/gradle/ProGuardTask
+WTK_PLUGIN = proguard/wtk/ProGuardObfuscator
+
+TARGETS = $(PROGUARD) $(PROGUARD_GUI) $(RETRACE) $(ANT_TASK) $(GRADLE_TASK) $(WTK_PLUGIN)
+
+JAVAC_OPTIONS = -nowarn -Xlint:none -classpath $(CLASSPATH) -sourcepath $(SRC) -d $(CLASSES)
+
+# Command sequence definitions for creating jars.
+
+define createjar
+ jar -cfm $(LIB)/$@.jar $(SRC)/$(dir $<)MANIFEST.MF \
+ -C $(CLASSES) $(dir $<)
+endef
+
+define updatejar
+ jar -uf $(LIB)/proguard.jar \
+ -C $(CLASSES) $(dir $<)
+endef
+
+# The various targets.
+
+all: basic options
+basic: proguard proguardgui retrace
+options: anttask gradletask wtkplugin
+
+proguard: $(PROGUARD)
+ $(createjar)
+
+proguardgui: proguard
+proguardgui: $(PROGUARD_GUI)
+ $(createjar)
+
+retrace: $(RETRACE)
+ $(createjar)
+
+anttask: $(ANT_JAR)
+anttask: $(PROGUARD)
+anttask: $(ANT_TASK)
+ $(updatejar)
+
+gradletask: $(GRADLE_JARS)
+gradletask: $(PROGUARD)
+gradletask: $(GRADLE_TASK)
+ $(updatejar)
+
+wtkplugin: $(WTK_JAR)
+wtkplugin: $(PROGUARD)
+wtkplugin: $(WTK_PLUGIN)
+ $(updatejar)
+
+clean:
+ -rm -fr $(CLASSES) $(LIB)
+
+
+define RESOURCES
+ $(shell find $(SRC)/$(dir $(1)) -maxdepth 1 \( -name \*.properties -o -name \*.png -o -name \*.gif -o -name \*.pro \) -printf $(CLASSES)/$(dir $(1))%P\\n)
+endef
+
+define TARGETRULE
+ $(1): $(CLASSES) $(CLASSES)/$(1).class $(call RESOURCES,$(1)) $(LIB)
+endef
+
+$(foreach TARGET,$(TARGETS),$(eval $(call TARGETRULE,$(TARGET))))
+
+$(CLASSES) $(LIB):
+ -mkdir -p $@
+
+$(CLASSES)/%.class: $(SRC)/%.java
+ javac $(JAVAC_OPTIONS) $^
+
+$(CLASSES)/%.properties $(CLASSES)/%.png $(CLASSES)/%.gif $(CLASSES)/%.pro:
+ cp $(subst $(CLASSES),$(SRC),$@) $@
+
+%.jar %.zip:
+ @echo "Please make sure the path to $@ is set"
+ @echo "correctly in this $(strip $(MAKEFILE_LIST))."
+ @echo "Alternatively, if you don't need the corresponding option,"
+ @echo "you can run `make' with the option -k."
+
+.PHONY: all basic options proguard proguardgui retrace anttask wtkplugin clean $(TARGETS) $(OPTIONAL_TARGETS)
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/maven/ant/pom.xml b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/ant/pom.xml
new file mode 100644
index 0000000000..5d7a8fdd54
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/ant/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>5.3.3</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-anttask</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/ant/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/ant/**.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <subpackages>proguard.ant</subpackages>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>../../../src</directory>
+ <includes>
+ <include>proguard/ant/**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ant</groupId>
+ <artifactId>ant</artifactId>
+ <version>1.7.0</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/maven/base/pom.xml b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/base/pom.xml
new file mode 100644
index 0000000000..c18a0edc7c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/base/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>5.3.3</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-base</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>proguard/gui/**</exclude>
+ <exclude>proguard/ant/**</exclude>
+ <exclude>proguard/gradle/**</exclude>
+ <exclude>proguard/wtk/**</exclude>
+ <exclude>proguard/retrace/**</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/**.java</include>
+ </includes>
+ <excludes>
+ <exclude>proguard/gui/**</exclude>
+ <exclude>proguard/ant/**</exclude>
+ <exclude>proguard/gradle/**</exclude>
+ <exclude>proguard/wtk/**</exclude>
+ <exclude>proguard/retrace/**</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <excludePackageNames>proguard.gui:proguard.ant:proguard.gradle:proguard.wtk:proguard.retrace</excludePackageNames>
+ <!-- sourceFileExcludes doesn't seem to work, so we're using excludePackageNames -->
+ <sourceFileExcludes>
+ <sourceFileExclude>proguard/gui/**</sourceFileExclude>
+ <sourceFileExclude>proguard/ant/**</sourceFileExclude>
+ <sourceFileExclude>proguard/gradle/**</sourceFileExclude>
+ <sourceFileExclude>proguard/wtk/**</sourceFileExclude>
+ <sourceFileExclude>proguard/retrace/**</sourceFileExclude>
+ </sourceFileExcludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>proguard.ProGuard</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/maven/gradle/pom.xml b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/gradle/pom.xml
new file mode 100644
index 0000000000..2526e89fed
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/gradle/pom.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>5.3.3</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-gradle</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/gradle/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/gradle/**.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <subpackages>proguard.gradle</subpackages>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.gradle</groupId>
+ <artifactId>gradle-logging</artifactId>
+ <version>3.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.gradle</groupId>
+ <artifactId>gradle-core</artifactId>
+ <version>3.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.gradle</groupId>
+ <artifactId>gradle-base-services</artifactId>
+ <version>3.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.gradle</groupId>
+ <artifactId>gradle-base-services-groovy</artifactId>
+ <version>3.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-all</artifactId>
+ <version>2.4.7</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <repositories>
+ <repository>
+ <id>gradle</id>
+ <url>http://repo.gradle.org/gradle/libs-releases-local/</url>
+ </repository>
+ </repositories>
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/maven/gui/pom.xml b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/gui/pom.xml
new file mode 100644
index 0000000000..4bd887ab8a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/gui/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>5.3.3</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-gui</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/gui/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/gui/**.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <subpackages>proguard.gui</subpackages>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ <mainClass>proguard.gui.ProGuardGUI</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>../../../src</directory>
+ <includes>
+ <include>proguard/gui/**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ <exclude>MANIFEST.MF</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-retrace</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/maven/pom.xml b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/pom.xml
new file mode 100644
index 0000000000..58e6a729d5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/pom.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>5.3.3</version>
+ <packaging>pom</packaging>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+ <description>ProGuard is a free Java class file shrinker, optimizer, obfuscator, and preverifier.</description>
+ <url>http://proguard.sourceforge.net/</url>
+
+ <prerequisites>
+ <maven>3</maven>
+ </prerequisites>
+
+ <developers>
+ <developer>
+ <id>lafortune</id>
+ <name>Eric Lafortune</name>
+ <url>http://www.lafortune.eu/</url>
+ <organization>GuardSquare</organization>
+ <organizationUrl>http://www.guardsquare.com/</organizationUrl>
+ <roles>
+ <role>Project Administrator</role>
+ <role>Developer</role>
+ </roles>
+ </developer>
+ </developers>
+
+ <licenses>
+ <license>
+ <name>GNU General Public License, Version 2</name>
+ <url>http://www.gnu.org/licenses/gpl-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <issueManagement>
+ <system>SourceForge.net Tracker</system>
+ <url>http://sourceforge.net/p/proguard/bugs/</url>
+ </issueManagement>
+
+ <scm>
+ <url>http://hg.code.sf.net/p/proguard/code</url>
+ <connection>scm:hg:http://hg.code.sf.net/p/proguard/code</connection>
+ </scm>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.0.2</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.5.1</version>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.9.1</version>
+ <configuration>
+ <links>
+ <link>http://download.oracle.com/javase/1.5.0/docs/api/</link>
+ </links>
+ <quiet>true</quiet>
+ </configuration>
+ <executions>
+ <execution>
+ <id>attach-javadoc</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <additionalparam>-Xdoclint:none</additionalparam>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>3.0.1</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.6</version>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <repository>
+ <id>sonatype-nexus-staging</id>
+ <name>Nexus Release Repository</name>
+ <url>https://oss.sonatype.org/service/local/staging/deploy/maven2</url>
+ </repository>
+ </distributionManagement>
+
+ <!-- To keep our project layout simple, we're not following the
+ 'one Maven way'. Now Maven is inflicting even more redundant
+ redundancy on us. We're stubborn though. -->
+
+ <modules>
+ <module>base</module>
+ <module>gui</module>
+ <module>ant</module>
+ <module>gradle</module>
+ <module>retrace</module>
+ </modules>
+
+ <profiles>
+ <profile>
+ <id>__wtk_plugin_build__</id>
+ <activation>
+ <file>
+ <exists>${wtk.home}/wtklib/kenv.zip</exists>
+ </file>
+ </activation>
+ <modules>
+ <module>wtk</module>
+ </modules>
+ </profile>
+ </profiles>
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/maven/retrace/pom.xml b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/retrace/pom.xml
new file mode 100644
index 0000000000..329c59b7ad
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/retrace/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>5.3.3</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-retrace</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/retrace/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/retrace/**.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <subpackages>proguard.retrace</subpackages>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ <mainClass>proguard.retrace.ReTrace</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/buildscripts/maven/wtk/pom.xml b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/wtk/pom.xml
new file mode 100644
index 0000000000..219ae89f8c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/buildscripts/maven/wtk/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.proguard</groupId>
+ <artifactId>proguard-parent</artifactId>
+ <version>5.3.3</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>proguard-wtk-plugin</artifactId>
+ <name>[${project.groupId}] ${project.artifactId}</name>
+
+ <build>
+ <sourceDirectory>../../../src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/wtk/**</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>proguard/wtk/**.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <subpackages>proguard.wtk</subpackages>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>../../../src</directory>
+ <includes>
+ <include>proguard/wtk/**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>proguard-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>wtklib</groupId>
+ <artifactId>kenv</artifactId>
+ <version>2.2</version>
+ <scope>system</scope>
+ <systemPath>${wtk.home}/wtklib/kenv.zip</systemPath>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/FAQ.html b/third_party/java/proguard/proguard5.3.3/docs/FAQ.html
new file mode 100644
index 0000000000..11d1eb6214
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/FAQ.html
@@ -0,0 +1,304 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard FAQ</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="index.html#FAQ.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="index.html#FAQ.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Frequently Asked Questions</h2>
+
+<h3>Contents</h3>
+
+<ol>
+<li><a href="#shrinking">What is shrinking?</a></li>
+<li><a href="#obfuscation">What is obfuscation?</a></li>
+<li><a href="#preverification">What is preverification?</a></li>
+<li><a href="#optimization">What kind of optimizations does <b>ProGuard</b>
+ support?</a></li>
+<li><a href="#commercial">Can I use <b>ProGuard</b> to process my commercial
+ application?</a></li>
+<li><a href="#jdk1.4">Does <b>ProGuard</b> work with Java 2, 5, ..., 8?</a></li>
+<li><a href="#jme">Does <b>ProGuard</b> work with Java Micro Edition?</a></li>
+<li><a href="#android">Does <b>ProGuard</b> work for Android apps?</a></li>
+<li><a href="#blackberry">Does <b>ProGuard</b> work for Blackberry
+ code?</a></li>
+<li><a href="#ant">Does <b>ProGuard</b> have support for Ant?</a></li>
+<li><a href="#gradle">Does <b>ProGuard</b> have support for Gradle?</a></li>
+<li><a href="#maven">Does <b>ProGuard</b> have support for Maven?</a></li>
+<li><a href="#gui">Does <b>ProGuard</b> come with a GUI?</a></li>
+<li><a href="#forname">Does <b>ProGuard</b> handle <code>Class.forName</code>
+ calls?</a></li>
+<li><a href="#resource">Does <b>ProGuard</b> handle resource files?</a></li>
+<li><a href="#encrypt">Does <b>ProGuard</b> encrypt string constants?</a></li>
+<li><a href="#flow">Does <b>ProGuard</b> perform control flow
+ obfuscation?</a></li>
+<li><a href="#incremental">Does <b>ProGuard</b> support incremental
+ obfuscation?</a></li>
+<li><a href="#keywords">Can <b>ProGuard</b> obfuscate using reserved
+ keywords?</a></li>
+<li><a href="#stacktrace">Can <b>ProGuard</b> reconstruct obfuscated stack
+ traces?</a></li>
+<li><a href="#dexguard">How is <b>DexGuard</b> different from
+ <b>ProGuard</b>?</a></li>
+</ol>
+
+<h3><a name="shrinking">What is shrinking?</a></h3>
+
+Java source code (.java files) is typically compiled to bytecode (.class
+files). Bytecode is more compact than Java source code, but it may still
+contain a lot of unused code, especially if it includes program libraries.
+Shrinking programs such as <b>ProGuard</b> can analyze bytecode and remove
+unused classes, fields, and methods. The program remains functionally
+equivalent, including the information given in exception stack traces.
+
+<h3><a name="obfuscation">What is obfuscation?</a></h3>
+
+By default, compiled bytecode still contains a lot of debugging information:
+source file names, line numbers, field names, method names, argument names,
+variable names, etc. This information makes it straightforward to decompile
+the bytecode and reverse-engineer entire programs. Sometimes, this is not
+desirable. Obfuscators such as <b>ProGuard</b> can remove the debugging
+information and replace all names by meaningless character sequences, making
+it much harder to reverse-engineer the code. It further compacts the code as a
+bonus. The program remains functionally equivalent, except for the class
+names, method names, and line numbers given in exception stack traces.
+
+<h3><a name="preverification">What is preverification?</a></h3>
+
+When loading class files, the class loader performs some sophisticated
+verification of the byte code. This analysis makes sure the code can't
+accidentally or intentionally break out of the sandbox of the virtual machine.
+Java Micro Edition and Java 6 introduced split verification. This means that
+the JME preverifier and the Java 6 compiler add preverification information to
+the class files (StackMap and StackMapTable attributes, respectively), in order
+to simplify the actual verification step for the class loader. Class files can
+then be loaded faster and in a more memory-efficient way. <b>ProGuard</b> can
+perform the preverification step too, for instance allowing to retarget older
+class files at Java 6.
+
+<h3><a name="optimization">What kind of optimizations does <b>ProGuard</b> support?</a></h3>
+
+Apart from removing unused classes, fields, and methods in the shrinking step,
+<b>ProGuard</b> can also perform optimizations at the bytecode level, inside
+and across methods. Thanks to techniques like control flow analysis, data flow
+analysis, partial evaluation, static single assignment, global value numbering,
+and liveness analysis, <b>ProGuard</b> can:
+
+<ul>
+<li>Evaluate constant expressions.</li>
+<li>Remove unnecessary field accesses and method calls.</li>
+<li>Remove unnecessary branches.</li>
+<li>Remove unnecessary comparisons and instanceof tests.</li>
+<li>Remove unused code blocks.</li>
+<li>Merge identical code blocks.</li>
+<li>Reduce variable allocation.</li>
+<li>Remove write-only fields and unused method parameters.</li>
+<li>Inline constant fields, method parameters, and return values.</li>
+<li>Inline methods that are short or only called once.</li>
+<li>Simplify tail recursion calls.</li>
+<li>Merge classes and interfaces.</li>
+<li>Make methods private, static, and final when possible.</li>
+<li>Make classes static and final when possible.</li>
+<li>Replace interfaces that have single implementations.</li>
+<li>Perform over 200 peephole optimizations, like replacing ...*2 by
+ ...&lt;&lt;1.</li>
+<li>Optionally remove logging code.</li>
+</ul>
+The positive effects of these optimizations will depend on your code and on
+the virtual machine on which the code is executed. Simple virtual machines may
+benefit more than advanced virtual machines with sophisticated JIT compilers.
+At the very least, your bytecode may become a bit smaller.
+<p>
+Some notable optimizations that aren't supported yet:
+<ul>
+<li>Moving constant expressions out of loops.</li>
+<li>Optimizations that require escape analysis
+ (<a href="http://www.guardsquare.com/dexguard" target="_top">DexGuard</a>
+ does).</li>
+</ul>
+
+<h3><a name="commercial">Can I use <b>ProGuard</b> to process my commercial application?</a></h3>
+
+Yes, you can. <b>ProGuard</b> itself is distributed under the GPL, but this
+doesn't affect the programs that you process. Your code remains yours, and
+its license can remain the same.
+
+<h3><a name="jdk1.4">Does <b>ProGuard</b> work with Java 2, 5, ..., 8?</a></h3>
+
+Yes, <b>ProGuard</b> supports all JDKs from 1.1 up to and including 8.0. Java
+2 introduced some small differences in the class file format. Java 5 added
+attributes for generics and for annotations. Java 6 introduced optional
+preverification attributes. Java 7 made preverification obligatory and
+introduced support for dynamic languages. Java 8 added more attributes and
+default methods. <b>ProGuard</b> handles all versions correctly.
+
+<h3><a name="jme">Does <b>ProGuard</b> work with Java Micro Edition?</a></h3>
+
+Yes. <b>ProGuard</b> itself runs in Java Standard Edition, but you can freely
+specify the run-time environment at which your programs are targeted,
+including Java Micro Edition. <b>ProGuard</b> then also performs the required
+preverification, producing more compact results than the traditional external
+preverifier.
+<p>
+<b>ProGuard</b> also comes with an obfuscator plug-in for the JME Wireless
+Toolkit.
+
+<h3><a name="android">Does <b>ProGuard</b> work for Android apps?</a></h3>
+
+Yes. Google's <code>dx</code> compiler converts Java bytecode into the Dalvik
+bytecode that runs on Android devices. By preprocessing the original
+bytecode, <b>ProGuard</b> can significantly reduce the file sizes and boost
+the run-time performance of the code. It is distributed as part of the Android
+SDK. <a href="http://www.guardsquare.com/dexguard"
+target="_top"><b>DexGuard</b></a>, <b>ProGuard</b>'s closed-source sibling for
+Android, offers additional optimizations and more application protection.
+
+<h3><a name="blackberry">Does <b>ProGuard</b> work for Blackberry code?</a></h3>
+
+It should. RIM's proprietary <code>rapc</code> compiler converts ordinary JME
+jar files into cod files that run on Blackberry devices. The compiler performs
+quite a few optimizations, but preprocessing the jar files with
+<b>ProGuard</b> can generally still reduce the final code size by a few
+percent. However, the <code>rapc</code> compiler also seems to contain some
+bugs. It sometimes fails on obfuscated code that is valid and accepted by other
+JME tools and VMs. Your mileage may therefore vary.
+
+<h3><a name="ant">Does <b>ProGuard</b> have support for Ant?</a></h3>
+
+Yes. <b>ProGuard</b> provides an Ant task, so that it integrates seamlessly
+into your Ant build process. You can still use configurations in
+<b>ProGuard</b>'s own readable format. Alternatively, if you prefer XML, you
+can specify the equivalent XML configuration.
+
+<h3><a name="gradle">Does <b>ProGuard</b> have support for Gradle?</a></h3>
+
+Yes. <b>ProGuard</b> also provides a Gradle task, so that it integrates into
+your Gradle build process. You can specify configurations in
+<b>ProGuard</b>'s own format or embedded in the Groovy configuration.
+
+<h3><a name="maven">Does <b>ProGuard</b> have support for Maven?</a></h3>
+
+<b>ProGuard</b>'s jar files are also distributed as artefacts from
+the <a href="http://search.maven.org/#search|ga|1|g:%22net.sf.proguard%22"
+target="other">Maven Central</a> repository. There are some third-party
+plugins that support <b>ProGuard</b>, such as the
+<a href="http://code.google.com/p/maven-android-plugin/"
+target="other">android-maven-plugin</a> and the
+<a href="http://mavenproguard.sourceforge.net/" target="other">IDFC Maven
+ProGuard Plug-in</a>.
+<a href="http://www.guardsquare.com/dexguard" target="_top"><b>DexGuard</b></a>
+also comes with a Maven plugin.
+
+<h3><a name="gui">Does <b>ProGuard</b> come with a GUI?</a></h3>
+
+Yes. First of all, <b>ProGuard</b> is perfectly usable as a command-line tool
+that can easily be integrated into any automatic build process. For casual
+users, there's also a graphical user interface that simplifies creating,
+loading, editing, executing, and saving ProGuard configurations.
+
+<h3><a name="forname">Does <b>ProGuard</b> handle <code>Class.forName</code> calls?</a></h3>
+
+Yes. <b>ProGuard</b> automatically handles constructs like
+<code>Class.forName("SomeClass")</code> and <code>SomeClass.class</code>. The
+referenced classes are preserved in the shrinking phase, and the string
+arguments are properly replaced in the obfuscation phase.
+<p>
+With variable string arguments, it's generally not possible to determine their
+possible values. They might be read from a configuration file, for instance.
+However, <b>ProGuard</b> will note a number of constructs like
+"<code>(SomeClass)Class.forName(variable).newInstance()</code>". These might
+be an indication that the class or interface <code>SomeClass</code> and/or its
+implementations may need to be preserved. The developer can adapt his
+configuration accordingly.
+
+<h3><a name="resource">Does <b>ProGuard</b> handle resource files?</a></h3>
+
+Yes. <b>ProGuard</b> copies all non-class resource files, optionally adapting
+their names and their contents to the obfuscation that has been applied.
+
+<h3><a name="encrypt">Does <b>ProGuard</b> encrypt string constants?</a></h3>
+
+No. String encryption in program code has to be perfectly reversible by
+definition, so it only improves the obfuscation level. It increases the
+footprint of the code. However, by popular demand, <b>ProGuard</b>'s
+closed-source sibling for Android, <a href="http://www.guardsquare.com/dexguard"
+target="_top"><b>DexGuard</b></a>, does provide string encryption, along with
+more protection techniques against static and dynamic analysis.
+
+<h3><a name="flow">Does <b>ProGuard</b> perform control flow obfuscation?</a></h3>
+
+Not explicitly. Control flow obfuscation injects additional branches into the
+bytecode, in an attempt to fool decompilers. <b>ProGuard</b> does not do this,
+except to some extent in its optimization techniques. <b>ProGuard</b>'s
+closed-source sibling for Android, <a href="http://www.guardsquare.com/dexguard"
+target="_top"><b>DexGuard</b></a>, does offer control flow obfuscation, as one
+of the many additional techniques to harden Android apps.
+
+<h3><a name="incremental">Does <b>ProGuard</b> support incremental obfuscation?</a></h3>
+
+Yes. This feature allows you to specify a previous obfuscation mapping file in
+a new obfuscation step, in order to produce add-ons or patches for obfuscated
+code.
+
+<h3><a name="keywords">Can <b>ProGuard</b> obfuscate using reserved keywords?</a></h3>
+
+Yes. You can specify your own obfuscation dictionary, such as a list of
+reserved key words, identifiers with foreign characters, random source files,
+or a text by Shakespeare. Note that this hardly improves the obfuscation.
+Decent decompilers can automatically replace reserved keywords, and the effect
+can be undone fairly easily, by obfuscating again with simpler names.
+
+<h3><a name="stacktrace">Can <b>ProGuard</b> reconstruct obfuscated stack traces?</a></h3>
+
+Yes. <b>ProGuard</b> comes with a companion tool, <b>ReTrace</b>, that can
+'de-obfuscate' stack traces produced by obfuscated applications. The
+reconstruction is based on the mapping file that <b>ProGuard</b> can write
+out. If line numbers have been obfuscated away, a list of alternative method
+names is presented for each obfuscated method name that has an ambiguous
+reverse mapping. Please refer to the <a href="manual/index.html">ProGuard User
+Manual</a> for more details.
+<p>
+Erik Andr&eacute; at Badoo has written a
+<a href="https://techblog.badoo.com/blog/2014/10/08/deobfuscating-hprof-memory-dumps/"
+target="other">tool to de-obfuscate HPROF memory dumps</a>.
+
+<h3><a name="dexguard">How is <b>DexGuard</b> different from <b>ProGuard</b>?</a></h3>
+
+<a href="http://www.guardsquare.com/dexguard"><b>DexGuard</b></a> is a
+commercial extension of <b>ProGuard</b>:
+<ul>
+<li><b>DexGuard</b> is specialized for Android applications and libraries: it
+ optimizes and obfuscates not just the bytecode, but also the manifest file,
+ resources, resource files, asset files, and native libraries.</li>
+<li><b>DexGuard</b> focuses on making apps self-defending against reverse
+ engineering and tampering. <b>DexGuard</b>'s techniques for obfuscation,
+ encryption, and detection are a lot stronger than <b>ProGuard</b>'s basic
+ name obfuscation.</li>
+<li><b>DexGuard</b> is backward compatible with <b>ProGuard</b>: it reads the
+ same configuration. It already comes with tuned configuration for the
+ Android runtime and for common Android libraries.</li>
+</ul>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/GPL.html b/third_party/java/proguard/proguard5.3.3/docs/GPL.html
new file mode 100644
index 0000000000..c7a24580ca
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/GPL.html
@@ -0,0 +1,406 @@
+<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<HTML>
+<HEAD>
+<TITLE>GNU General Public License</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#1F00FF" ALINK="#FF0000" VLINK="#9900DD">
+<H1>GNU General Public License</H1>
+<H2>Table of Contents</H2>
+<UL>
+
+ <LI><A NAME="TOC1" HREF="#SEC1">GNU GENERAL PUBLIC LICENSE</A>
+<UL>
+<LI><A NAME="TOC2" HREF="#SEC2">Preamble</A>
+<LI><A NAME="TOC3" HREF="#SEC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</A>
+
+</UL>
+</UL>
+
+<P>
+
+<HR>
+
+<P>
+
+
+
+<H2><A NAME="SEC1" HREF="#TOC1">GNU GENERAL PUBLIC LICENSE</A></H2>
+<P>
+Version 2, June 1991
+
+</P>
+
+<PRE>
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+</PRE>
+
+
+
+<H2><A NAME="SEC2" HREF="#TOC2">Preamble</A></H2>
+
+<P>
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+</P>
+<P>
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+</P>
+<P>
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+</P>
+<P>
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+</P>
+<P>
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+</P>
+<P>
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+</P>
+<P>
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+</P>
+<P>
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+</P>
+
+
+<H2><A NAME="SEC3" HREF="#TOC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</A></H2>
+
+
+<P>
+
+<STRONG>0.</STRONG>
+ This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+<P>
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+<P>
+
+<STRONG>1.</STRONG>
+ You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+<P>
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+<P>
+
+<STRONG>2.</STRONG>
+ You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+<P>
+
+<UL>
+
+<LI><STRONG>a)</STRONG>
+ You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+<P>
+<LI><STRONG>b)</STRONG>
+ You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+<P>
+<LI><STRONG>c)</STRONG>
+ If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+</UL>
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+<P>
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+<P>
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+<P>
+
+<STRONG>3.</STRONG>
+ You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+
+<!-- we use this doubled UL to get the sub-sections indented, -->
+<!-- while making the bullets as unobvious as possible. -->
+<UL>
+
+<LI><STRONG>a)</STRONG>
+ Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+<P>
+<LI><STRONG>b)</STRONG>
+ Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+<P>
+<LI><STRONG>c)</STRONG>
+ Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+</UL>
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+<P>
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+<P>
+
+<STRONG>4.</STRONG>
+ You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+<P>
+
+<STRONG>5.</STRONG>
+ You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+<P>
+
+<STRONG>6.</STRONG>
+ Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+<P>
+
+<STRONG>7.</STRONG>
+ If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+<P>
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+<P>
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+<P>
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+<P>
+
+<STRONG>8.</STRONG>
+ If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+<P>
+
+<STRONG>9.</STRONG>
+ The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+<P>
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+<P>
+
+
+<STRONG>10.</STRONG>
+ If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+
+
+<P><STRONG>NO WARRANTY</STRONG></P>
+
+<P>
+
+<STRONG>11.</STRONG>
+ BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+<P>
+
+<STRONG>12.</STRONG>
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+<P>
+
+
+<H2>END OF TERMS AND CONDITIONS</H2>
+</BODY>
+</HTML>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/GPL_exception.html b/third_party/java/proguard/proguard5.3.3/docs/GPL_exception.html
new file mode 100644
index 0000000000..683b2d5061
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/GPL_exception.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Special Exception to the GNU General Public License</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#1F00FF" ALINK="#FF0000" VLINK="#9900DD">
+<H1>Special Exception to the GNU General Public License</H1>
+
+<P>
+Copyright &copy; 2002-2017 GuardSquare NV
+</P>
+
+<P>
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+</P>
+
+<P>
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+</P>
+
+<P>
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+</P>
+
+<P>
+In addition, as a special exception, GuardSquare NV gives permission to link
+the code of this program with the following stand-alone applications:
+<ul>
+<li>Gradle,</li>
+<li>Apache Ant,</li>
+<li>Apache Maven,</li>
+<li>the Google Android SDK,</li>
+<li>the Eclipse ProGuardDT GUI,</li>
+<li>the EclipseME JME IDE,</li>
+<li>the Oracle NetBeans Java IDE,</li>
+<li>the Oracle JME Wireless Toolkit, and</li>
+<li>the Simple Build Tool for Scala (and its scripts).</li>
+</ul>
+and distribute linked combinations including the two. You must obey the GNU
+General Public License in all respects for all of the code used other than
+these programs. If you modify this file, you may extend this exception to your
+version of the file, but you are not obligated to do so. If you do not wish to
+do so, delete this exception statement from your version.
+</P>
+
+</BODY>
+</HTML>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/acknowledgements.html b/third_party/java/proguard/proguard5.3.3/docs/acknowledgements.html
new file mode 100644
index 0000000000..12678112fe
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/acknowledgements.html
@@ -0,0 +1,89 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Acknowledgements</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="index.html#acknowledgements.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="index.html#acknowledgements.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Acknowledgements</h2>
+
+The first versions of <b>ProGuard</b> grew out of <b>RetroGuard</b>, which its
+author Mark Welsh kindly made available under the GNU Lesser General Public
+License. RetroGuard is a very nice piece of code, but it only performed
+obfuscation. I started from the class file parsing code and wrote my own
+shrinker, optimizer, obfuscator, and preverifier. As of version 4.0, all of the
+original code has been rewritten, so the most obvious remaining similarity are
+the program names.
+<p>
+
+Dirk Schnelle has contributed and maintained the first versions of the Ant
+task. I have rewritten the implementation for version 3.0, but the XML schema
+is still based on his work.
+<p>
+
+Marcel Patzlaff has initiated a series of artifacts in the Maven Central
+repository. I am now maintaining them as part of the official builds.
+<p>
+
+Many other people have expressed their enthusiasm and have chimed in with
+interesting ideas, bug reports, and bug fixes: Thorsten Heit, Oliver Retzl,
+Jonathan Knudsen, Tarcisio Camara, Bob Drury, Dave Jarvis, Marc Chapman, Dave
+Morehouse, Richard Osbaldeston, Peter Hawkins, Mark Sherington, David Sitsky,
+James Manning, Ptolemy Oberin, Frank-Michael Moser, QZ Shines, Thomas Singer,
+Michele Puccini, Roman Bednarek, Natalia Pujol, Daniel Sj&ouml;blom, Jan
+Filipsky, Charles Smith, Gerrit Telkamp, Noel Grandin, Torbj&ouml;rn
+S&ouml;derstedt, Clemens Eisserer, Clark Bassett, Eduard Welch, Dawid Weiss,
+Andrew Wilson, Sean Owen, Niels Gron, Ishan Mehta, Steven Adams, Xavier Kral,
+Stefan Martin, Toby Reyelts, Bernhard Eder, Manfred Moser, Marco Bl&uuml;mel,
+David Reiss, Roy Williams, Marcel Heckel, Balazs Banyai,
+and many more. Thanks! Your feedback has been invaluable.
+<p>
+
+<a href="http://www.guardsquare.com/" target="_top">GuardSquare</a> is providing the
+financial resources for this project. At GuardSquare, we're also developing
+ProGuard's sibling for Android,
+<a href="http://www.guardsquare.com/dexguard" target="_top">DexGuard</a>.
+<p>
+
+<a href="http://www.sky.com/" rel="nofollow" target="other">British Sky</a>
+has kindly sponsored the optimization of <i>enum</i> types.
+<p>
+
+<a href="http://sourceforge.net/projects/proguard/"
+target="other">SourceForge</a> is providing the resources for hosting this
+project and many other projects.
+<p>
+
+<a href="http://www.sonatype.com/" target="other">Sonatype</a> and
+the <a href="http://search.maven.org/#search|ga|1|g:%22net.sf.proguard%22"
+target="other">Maven Central</a> repository are hosting the Maven artifacts.
+<p>
+
+The code and these web pages were written using Oracle/Sun's JDKs, Linux,
+IntelliJ IDEA, GNU emacs, bash, sed, awk, and a whole host of other tools that
+continue to make programming interesting.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/alternatives.html b/third_party/java/proguard/proguard5.3.3/docs/alternatives.html
new file mode 100644
index 0000000000..60163354c0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/alternatives.html
@@ -0,0 +1,790 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Alternatives</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="index.html#alternatives.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="index.html#alternatives.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Alternatives</h2>
+
+There are quite a few Java/Dalvik code shrinkers, optimizers, obfuscators, and
+preverifiers out there. Users of <b>ProGuard</b> tell me it easily compares
+with the best of them. However, you may want to check that out yourself.
+<p>
+This is a list of the programs of which I'm aware. Obviously, I've never
+personally tested all of them. Many programs, even commercial ones, have been
+abandoned. Please drop me a note if you know of any other shrinkers,
+optimizers, obfuscators, or preverifiers, or if some information provided
+below is incorrect.
+<p>
+
+<table>
+
+<tr>
+<th>Author/Company</th>
+<th>Program</th>
+<th>Shrink.</th>
+<th>Optim.</th>
+<th>Obfusc.</th>
+<th>Preverif.</th>
+<th>License</th>
+</tr>
+
+<tr>
+<td><a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a></td>
+<td><a target="_top" href="http://proguard.sourceforge.net/">ProGuard</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td>Free (GPL)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.informatik.uni-oldenburg.de/leute/hoenicke.html">Jochen Hoenicke</a></td>
+<td><a target="other" href="http://jode.sourceforge.net/">Jode</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Free (GPL)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="https://code.facebook.com/posts/998080480282805/open-sourcing-redex-making-android-apps-smaller-and-faster/">Facebook</a></td>
+<td><a target="other" href="https://github.com/facebook/redex">ReDex</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free (BSD)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.cs.cornell.edu/nystrom/">Nate Nystrom</a></td>
+<td><a target="other" href="http://www.cs.purdue.edu/homes/hosking/bloat/">Bloat</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://tools.android.com/">Google</a></td>
+<td><a target="other" href="http://tools.android.com/tech-docs/jackandjill">Jack</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Free (Apache)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://sourceforge.net/users/hchacha/">Hidetoshi Ohuchi</a></td>
+<td><a target="other" href="http://jarg.sourceforge.net/">Jarg</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Free (BSD)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.yworks.com/">yWorks</a></td>
+<td><a target="other" href="http://www.yworks.com/en/products_yguard_about.htm">yGuard</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Free (no source)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.riggshill.com/">RiggsHill Software</a></td>
+<td><a target="other" href="http://genjar.sourceforge.net/">GenJar</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free (Apache)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://ant.apache.org/">Apache</a></td>
+<td><a target="other" href="http://ant.apache.org/manual/Types/classfileset.html">Ant Classfileset</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free (Apache)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.celton.mobi/">Carsten Elton S&oslash;rensen</a></td>
+<td><a target="other" href="http://code.google.com/p/treeshaker/">Treeshaker</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free (Apache)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.ucdetector.org/">J&ouml;rg Spieler</a></td>
+<td><a target="other" href="http://www.ucdetector.org/">UCDetector</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free (EPL)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.curious-creature.org/">Romain Guy</a></td>
+<td><a target="other" href="http://www.jroller.com/gfx/entry/get_what_you_need_from">Harvester</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free (BSD)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://java.net/projects/dcd/">Emeric Vernat</a></td>
+<td><a target="other" href="http://java.net/projects/dcd/">DCD</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free (LGPL)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://sadun-util.sourceforge.net/">Cristiano Sadun</a></td>
+<td><a target="other" href="http://sadun-util.sourceforge.net/pack.html">Pack</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free (LGPL)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.sable.mcgill.ca/">Sable</a></td>
+<td><a target="other" href="http://www.sable.mcgill.ca/soot/">Soot</a></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Free (LGPL)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.sable.mcgill.ca/">Sable</a></td>
+<td><a target="other" href="http://www.sable.mcgill.ca/JBCO/">JBCO</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Free (LGPL)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://classencrypt.sourceforge.net/">Jeffrey Wheaton</a></td>
+<td><a target="other" href="http://classencrypt.sourceforge.net/">ClassEncrypt</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Free (GPL)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://sourceforge.net/users/glurk/">Thorsten Heit</a></td>
+<td><a target="other" href="http://sourceforge.net/projects/javaguard/">JavaGuard</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Free (LGPL)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://mwobfu.sourceforge.net/">Patrick Mueller</a></td>
+<td><a target="other" href="http://mwobfu.sourceforge.net/">Mwobfu</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Free (GPL)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.bebbosoft.de/">BebboSoft</a></td>
+<td><a target="other" href="http://www.bebbosoft.de/#java/mug/index.wiki">Bb_mug</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Free (no source)</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://github.com/v6ak">V&iacute;t &Scaron;est&aacute;k</a></td>
+<td><a target="other" href="http://github.com/v6ak/Preverifier/">Preverifier</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td>Free (EPL)</td>
+</tr>
+
+<tr>
+<td><a target="_top" href="http://www.guardsquare.com/">GuardSquare</a></td>
+<td><a target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.preemptive.com/">PreEmptive</a></td>
+<td><a target="other" href="http://www.preemptive.com/products/dasho/index.html">DashOPro</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.zelix.com/">Zelix</a></td>
+<td><a target="other" href="http://www.zelix.com/klassmaster/index.html">KlassMaster</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.s-cradle.com/english/index.html">Sophia Cradle</a></td>
+<td><a target="other" href="http://www.s-cradle.com/english/products/sophiacompress_java/index.html">SophiaCompress</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.e-t.com/">Eastridge Technology</a></td>
+<td><a target="other" href="http://www.e-t.com/jshrink.html">Jshrink</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.innaworks.com/">Innaworks</a></td>
+<td><a target="other" href="http://www.innaworks.com/mBooster">mBooster</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.uni-vologda.ac.ru/~c3c/">Sergey Sverdlov</a></td>
+<td><a target="other" href="http://www.uni-vologda.ac.ru/~c3c/jco/">J.Class Optimizer</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.smardec.com/">Smardec</a></td>
+<td><a target="other" href="http://www.allatori.com/">Allatori</a></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://cs.arizona.edu/">U. of Arizona</a></td>
+<td><a target="other" href="http://sandmark.cs.arizona.edu/">SandMark</a></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://zenofx.com/">Zenofx</a></td>
+<td><a target="other" href="http://zenofx.com/classguard/">ClassGuard</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.bisguard.com/">BIS Guard &amp; Co.</a></td>
+<td><a target="other" href="http://www.bisguard.com/">Java Antidecompiler</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.force5.com/">Force 5</a></td>
+<td><a target="other" href="http://www.force5.com/JCloak/ProductJCloak.html">JCloak</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.semdesigns.com/">Semantic Designs</a></td>
+<td><a target="other" href="http://www.semdesigns.com/Products/Obfuscators/JavaObfuscator.html">Obfuscator</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.duckware.com/">Duckware</a></td>
+<td><a target="other" href="http://www.duckware.com/jobfuscate/">Jobfuscate</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://secureteam.net/index.aspx">Secureteam</a></td>
+<td><a target="other" href="http://secureteam.net/Java-Obfuscator-Features.aspx">Jfuscator</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.arxan.com/">Arxan</a></td>
+<td><a target="other" href="http://www.arxan.com/products/desktop/guardit-for-java/">GuardIT</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.bfa-it.com/">Bfa-it</a></td>
+<td><a target="other" href="http://www.bfa-it.com/?id=products/jarprotector">JarProtector</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial</td>
+</tr>
+
+<tr>
+<td><a target="other" rel="nofollow" href="http://www.chez.com/vasile/">Vasile Calmatui</a></td>
+<td><a target="other" href="http://www.chez.com/vasile/obfu/VasObfuLite.html">VasObfuLite</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Free</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.alphaworks.ibm.com/">IBM AlphaWorks</a></td>
+<td><a target="other" href="http://www.research.ibm.com/jax/">JAX</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(discontinued)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.nq4.de/">NQ4</a></td>
+<td><a target="other" rel="nofollow" href="http://www.nq4.de/">Joga</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www-i2.informatik.rwth-aachen.de/~markusj/">Markus Jansen</a></td>
+<td><a target="other" rel="nofollow" href="http://www-i2.informatik.rwth-aachen.de/~markusj/jopt/">Jopt</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.geocities.com/CapeCanaveral/Hall/2334/resume.html">Alexander Shvets</a></td>
+<td><a target="other" rel="nofollow" href="http://www.geocities.com/CapeCanaveral/Hall/2334/Programs/cafebabe.html">CafeBabe</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://mojo.codehaus.org/">Mojo</a></td>
+<td><a target="other" rel="nofollow" href="http://mojo.codehaus.org/minijar-maven-plugin/">Minijar</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>(discontinued)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://darcs.brianweb.net/">Brian Alliet</a></td>
+<td><a target="other" rel="nofollow" href="http://darcs.brianweb.net/gcclass/">Gcclass</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.cs.purdue.edu/homes/grothoff/">Christian Grothoff</a></td>
+<td><a target="other" rel="nofollow" href="http://www.ovmj.org/jamit/">Jamit</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.garret.ru/~knizhnik/">Konstantin Knizhnik</a></td>
+<td><a target="other" rel="nofollow" href="http://www.garret.ru/~knizhnik/javago/ReadMe.htm">JavaGO</a></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://donquixote.cafebabe.jp/">Haruaki Tamada</a></td>
+<td><a target="other" rel="nofollow" href="http://donquixote.cafebabe.jp/">DonQuixote</a></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.utdallas.edu/~gxz014000/">Bajie</a></td>
+<td><a target="other" rel="nofollow" href="http://www.utdallas.edu/~gxz014000/jcmp/">JCMP</a></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.elegant-software.com/">Elegant Software</a></td>
+<td><a target="other" rel="nofollow" href="http://www.elegant-software.com/software/jmangle/">JMangle</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.primenet.com/~ej">Eron Jokipii</a></td>
+<td><a target="other" rel="nofollow" href="http://www.primenet.com/~ej">Jobe</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://jrc.krdl.org.sg/">JRC</a></td>
+<td><a target="other" rel="nofollow" href="http://jrc.krdl.org.sg/decaf/">DeCaf</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.drjava.de/">Dr. Java</a></td>
+<td><a target="other" rel="nofollow" href="http://www.drjava.de/obfuscator/">Marvin Obfuscator</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>(disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.ibm.com/">IBM</a></td>
+<td><a target="other" rel="nofollow" href="http://www-306.ibm.com/software/wireless/wsdd/">WSDD</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.s5systems.com/">S5 Systems</a></td>
+<td><a target="other" rel="nofollow" href="http://www.s5systems.com/jPresto.htm">jPresto</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.plumbdesign.com/">Plumb Design</a></td>
+<td><a target="other" rel="nofollow" href="http://www.condensity.com/">Condensity</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (discontinued)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.4thpass.com/">4th Pass</a></td>
+<td><a target="other" rel="nofollow" href="http://www.4thpass.com/">SourceGuard</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.codingart.com/">CodingArt</a></td>
+<td><a target="other" rel="nofollow" href="http://www.codingart.com/codeshield.html">CodeShield</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.retrologic.com/">RetroLogic</a></td>
+<td><a target="other" rel="nofollow" href="http://www.retrologic.com/">RetroGuard</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.helseth.com/">Helseth</a></td>
+<td><a target="other" rel="nofollow" href="http://www.helseth.com/HJO.htm">JObfuscator</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.vegatech.com/">Vega Technologies</a></td>
+<td><a target="other" rel="nofollow" href="http://www.vegatech.com/jzipper/">JZipper</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.leesw.com/">LeeSoftware</a></td>
+<td><a target="other" rel="nofollow" href="http://www.leesw.com/">Smokescreen Obfuscator</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://shield4j.com/">Eduardo Coca</a></td>
+<td><a target="other" rel="nofollow" href="http://shield4j.com/">Shield4J</a></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.software4j.com/">Software4j</a></td>
+<td><a target="other" rel="nofollow" href="http://www.software4j.com/obfuscate4j/">Obfuscate4j</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.jammconsulting.com/">JAMM Consulting</a></td>
+<td><a target="other" rel="nofollow" href="http://www.jammconsulting.com/jamm/servlet/com.jammconsulting.servlet.JAMMServlet?pageId=ObfuscateProPage">ObfuscatePro</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.jdevelop.com/">JDevelop</a></td>
+<td><a target="other" rel="nofollow" href="http://www.jdevelop.com/best-java-obfuscator.html">JSCO</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.4fang.net/">4Fang</a></td>
+<td><a target="other" rel="nofollow" href="http://www.4fang.net/jmix/">JMix</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (discontinued?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.jproof.com/">JProof</a></td>
+<td><a target="other" rel="nofollow" href="http://www.jproof.com/">JProof</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.chainkey.com/">ChainKey</a></td>
+<td><a target="other" rel="nofollow" href="http://www.chainkey.com/en/jcp/">Java Code Protector</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.2lkit.com/">2LKit</a></td>
+<td><a target="other" rel="nofollow" href="http://www.2lkit.com/products/2LKitObf/index.htm">2LKit Obfuscator</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.wingsoft.com/">WingSoft</a></td>
+<td><a target="other" rel="nofollow" href="http://www.wingsoft.com/wingguard.html">WingGuard</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.sbktech.org/">HashJava</a></td>
+<td><a target="other" rel="nofollow" href="http://www.sbktech.org/">HashJava</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (disappeared?)</td>
+</tr>
+
+<tr class="disappeared">
+<td><a target="other" rel="nofollow" href="http://www.solutia.ro/">GITS</a></td>
+<td><a target="other" rel="nofollow" href="http://www.solutia.ro/pages/javadc/">Blurfuscator</a></td>
+<td align="center"><br /></td>
+<td align="center"><br /></td>
+<td align="center"><img src="checkmark.gif" width="11" height="11" alt="x" /></td>
+<td align="center"><br /></td>
+<td>Commercial (disappeared?)</td>
+</tr>
+
+</table>
+<p>
+All trademarks are property of their respective holders.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/android_shades.png b/third_party/java/proguard/proguard5.3.3/docs/android_shades.png
new file mode 100644
index 0000000000..96e54f00b7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/android_shades.png
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/checkmark.gif b/third_party/java/proguard/proguard5.3.3/docs/checkmark.gif
new file mode 100644
index 0000000000..8afa67739a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/checkmark.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/dexguard.png b/third_party/java/proguard/proguard5.3.3/docs/dexguard.png
new file mode 100644
index 0000000000..ed8f1f4601
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/dexguard.png
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/downloads.html b/third_party/java/proguard/proguard5.3.3/docs/downloads.html
new file mode 100644
index 0000000000..a6ce1d7c2b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/downloads.html
@@ -0,0 +1,803 @@
+
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Downloads</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="index.html#downloads.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="index.html#downloads.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Downloads</h2>
+
+<b>ProGuard</b> is distributed under the terms of the GNU General Public
+License. Please consult the <a href="license.html">license page</a> for more
+details.
+<p>
+<b>ProGuard</b> is written in Java, so it requires a Java Runtime Environment
+ (JRE 1.6 or higher).
+<p>
+You can download the latest release (containing the program jars, the
+documentation that you're reading now, examples, and the source code) from this
+location:
+<p>
+<center><a href="http://sourceforge.net/projects/proguard/files/"
+target="other">Download section at SourceForge</a></center>
+<p>
+
+The <a href="http://sourceforge.net/projects/proguard/files/proguard/"
+target="other">proguard</a> section contains major releases and updates with
+sub-minor version numbers, for applying emergency fixes. The
+<a href="http://sourceforge.net/projects/proguard/files/proguard%20beta/"
+target="other">proguard beta</a> section contains beta releases. These include
+new features and any less urgent bug fixes collected since the previous
+release.
+<p>
+If you're still working with an older version of <b>ProGuard</b>, check out
+the summary of changes below, to see if you're missing something essential.
+Better look at the up-to-date <a
+href="http://proguard.sourceforge.net/downloads.html">on-line version</a> if
+you're reading a local copy of this page. Unless noted otherwise,
+<b>ProGuard</b> remains compatible across versions, so don't be afraid to
+update.
+<p>
+If you're only interested in individual jar files for your build process, you
+can also download them from the Maven Central repository, with GroupId
+<a href="http://search.maven.org/#search|ga|1|g:%22net.sf.proguard%22"
+target="other">net.sf.proguard</a> and ArtifactIds
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-parent%22"
+target="other">proguard-parent</a>,
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-base%22"
+target="other">proguard-base</a>,
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-gui%22"
+target="other">proguard-gui</a>,
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-anttask%22"
+target="other">proguard-anttask</a>,
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-gradle%22"
+target="other">proguard-gradle</a>,
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-wtk-plugin%22"
+target="other">proguard-wtk-plugin</a>, and
+<a href="http://search.maven.org/#search|ga|1|a:%22proguard-retrace%22"
+target="other">proguard-retrace</a>.
+
+<h3><div>In progress</div> Version 5.3.x</h3>
+<ul>
+<li>[PGD-630] Fixed possible NullPointerException in optimization step.
+<li>[PGD-637] Fixed simplification of enum types in invokedynamic calls.
+<li>Fixed merging of classes sometimes resulting in final methods being
+ overridden.
+<li>Fixed simplification of enum types that are stored in arrays.
+<li>Fixed VerifyError triggered by merging classes with shrinking disabled.
+</ul>
+
+<h3><div>Sep 2016</div> Version 5.3</h3>
+<ul>
+<li>Avoiding obfuscated name clashes with library classes.
+<li>Fixed processing of generic signatures with inner classes.
+<li>Fixed processing of generic signatures with array types as bounds.
+<li>Fixed processing of wide branch instructions.
+<li>Fixed shrinking of nameless parameters attribute.
+<li>Fixed optimization of code with unreachable exception handlers.
+<li>Fixed optimization of enum types with custom fields.
+<li>Fixed optimization of enum types with custom static methods.
+<li>Fixed optimization of lambda method types.
+<li>Fixed optimization of parameter annotations.
+<li>Fixed optimization of swap/pop constructs.
+<li>Fixed adapting class access for referenced class members.
+<li>Fixed adapting invocations for referenced class members.
+<li>Preserving class member signature classes if
+ <code>includedescriptorclasses</code> is specified.
+<li>Allowing empty output jars if <code>-ignorewarnings</code> is specified.
+<li>Avoiding exceptions when inlining invalid line number instruction offsets.
+<lI>Fixed preverification of wildcard exceptions.
+<li>Fixed ReTrace for field names.
+<li>Fixed ReTrace for negative line numbers.
+<li>Improved ReTrace regular expression for Logback and Log4j.
+<li>Added Gradle build file.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Jan 2015</div> Version 5.2</h3>
+<ul>
+<li>Added encoding of optimized line numbers in ProGuard.
+<li>Added decoding of optimized stack frames in ReTrace.
+<li>Added overflow checks when writing out class files.
+<li>Fixed shrinking of default methods in subinterfaces.
+<li>Fixed optimization of closures with signatures containing merged classes.
+<li>Fixed conservative optimization of instructions that may throw exceptions.
+<li>Fixed internal processing of primitive array types.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Oct 2014</div> Version 5.1</h3>
+<ul>
+<li>Fixed processing of various kinds of closures in Java 8.
+<li>Fixed shrinking of generic signatures in classes and methods.
+<li>Fixed shrinking of debug information about generic local variable types.
+<li>Fixed optimization of default implementations in interfaces.
+<li>Fixed optimization of variable initializations.
+<li>Fixed obfuscation of internal class names in strings.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Aug 2014</div> Version 5.0</h3>
+<ul>
+<li>Added support for Java 8.
+<li>Added <code>-keep</code> modifier <code>includedescriptorclasses</code>.
+<li>Added automatic suggestions for keeping attributes.
+<li>Clearing preverification information when <code>-dontpreverify</code> is
+ specified.
+<li>Extended optimization support for conservative optimization with java
+ system property <code>optimize.conservatively</code>.
+<li>Fixed occasional preverification problem.
+<li>Fixed shrinking of generic class signatures.
+<li>Fixed shrinking of generic variable signatures.
+<li>Fixed analysis of unused parameters for bootstrap methods in library
+ classes.
+<li>Fixed inlining problem of non-returning subroutines.
+<li>Fixed possible IllegalArgumentException and ArrayIndexOutOfBoundsException
+ in enum simplification.
+<li>Fixed unnecessary notes about dynamic class instantiations with constant
+ class names.
+<li>Fixed preverification of unnecessary casts of null values.
+<li>Fixed lazy resolution of output jars in Gradle task.
+<li>Fixed processing of synthetic code with alternative initializer invocations.
+<li>Improved handling of symbolic links in shell scripts.
+<li>Improved default path in Windows bat files.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Dec 2013</div> Version 4.11</h3>
+<ul>
+<li>Added simplification of basic enum types.
+<li>Added reading and writing of apk and aar archives.
+<li>Fixed criteria for class merging.
+<li>Fixed simplification of variable initializations.
+<li>Fixed simplification of redundant boolean variables.
+<li>Fixed optimization of unused stack entries in exception handlers.
+<li>Fixed correction of access flags after class merging, method inlining, and
+ class repackaging.
+<li>Refined criterion for method inlining.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Jul 2013</div> Version 4.10</h3>
+<ul>
+<li>Made Gradle task resolve files lazily.
+<li>Enabled as-needed execution in Gradle task.
+<li>Using standard string interpolation for Gradle configuration.
+<li>Reduced log levels for console output in Gradle task.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Mar 2013</div> Version 4.9</h3>
+<ul>
+<li>Added Gradle task.
+<li>Added more peephole optimizations for strings.
+<li>Improved optimization of classes with static initializers.
+<li>Improved processing of finally blocks compiled with JDK 1.4 or older.
+<li>Fixed shrinking of access widening abstract methods, for the Dalvik VM.
+<li>Fixed overly aggressive shrinking of class annotations.
+<li>Fixed processing of unused classes in generic signatures.
+<li>Fixed merging of classes with similar class members.
+<li>Added java system property <code>optimize.conservatively</code> to allow
+ for instructions intentionally throwing <code>NullPointerException</code>,
+ <code>ArrayIndexOutOfBoundsException</code>, or
+ <code>ClassCastException</code> without other useful effects.
+<li>Fixed optimization of unnecessary variable initializations.
+<li>Fixed optimization of code involving NaN.
+<li>Fixed inlining of methods that are supposed to be kept.
+<li>Fixed preverification of artificially convoluted dup constructs.
+<li>Fixed quotes for java commands in .bat scripts.
+<li>Improved handling of non-sequential line number information.
+<li>Now requiring Java 5 or higher for running ProGuard.
+<li>Updated build files.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>May 2012</div> Version 4.8</h3>
+<ul>
+<li>Added more peephole optimizations for strings.
+<li>Added support for multiple external configuration files in Ant
+ configurations.
+<li>Added support for Ant properties in external configuration files.
+<li>Fixed parsing of empty file filters on input and output.
+<li>Fixed parsing of '*' wildcard for file filters and name filters.
+<li>Fixed obfuscation of private methods that are overridden in concrete
+ classes with intermediary abstract classes and interfaces (workaround
+ for Oracle bugs #6691741 and #6684387).
+<li>Fixed optimization of complex finally blocks, compiled with JDK 1.4 or
+ earlier.
+<li>Fixed optimizing signatures of methods that are marked as not having
+ side effects.
+<li>Fixed optimization of long local variables possibly causing verification
+ error for register pairs.
+<li>Fixed merging of classes defined inside methods.
+<li>Fixed stack consistency in optimization step.
+<li>No longer removing debug information about unused parameters, for
+ <code>-keepparameternames</code> or <code>-keepattributes</code>.
+<li>Fixed updating manifest files with carriage return characters.
+<li>Now removing unreachable code in preverification step.
+<li>Improved default regular expression for stack traces in ReTrace.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Dec 2011</div> Version 4.7</h3>
+<ul>
+<li>Added support for Java 7.
+<li>Parsing unquoted file names with special characters more leniently.
+<li>Added support for instance methods overriding class methods.
+<li>Added removal of unused parameterless constructors.
+<li>Added removal of empty class initializers.
+<li>Added peephole optimizations for constant strings.
+<li>Avoiding idle optimization passes.
+<li>Improved removal of unused constants after obfuscation.
+<li>Fixed removal of unused classes referenced by annotations.
+<li>Fixed simplifying parameters of constructors that should actually be
+ preserved.
+<li>Fixed simplifying parameters of large numbers of similar constructors.
+<li>Fixed exceptions in optimization of unusual obfuscated code.
+<li>Fixed NullPointerException when specifying <code>-keepclassmembers</code>
+ without specific class or class members.
+<li>Fixed potential problems with mixed-case class name dictionaries when not
+ allowing mixed-case class names.
+<li>Fixed obfuscation of classes with EnclosingMethod attributes that don't
+ specify methods.
+<li>Fixed preverification of returning try blocks with finally blocks, inside
+ try blocks, when compiled with JDK 1.4.
+<li>Fixed sorting of interfaces containing generics.
+<li>Fixed paths in shell scripts.
+<li>Fixed filling in of text fields showing class obfuscation dictionary and
+ package obfuscation dictionary from configuration in GUI.
+<li>Worked around Oracle Java 6/7 bug #7027598 that locked the GUI on Linux.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Feb 2011</div> Version 4.6</h3>
+<ul>
+<li>Added support for synthetic, bridge, and varargs modifiers in configuration.
+<li>Added detection of atomic updater construction with constant arguments.
+<li>Fixed merging of package visible classes.
+<li>Fixed optimization of fields that are only accessed by reflection.
+<li>Fixed optimization of read-only or write-only fields that are volatile.
+<li>Fixed handling of side-effects due to static initializers.
+<li>Fixed handling of bridge flags in obfuscation step.
+<li>Fixed handling of super flag when merging classes.
+<li>Fixed updating of variable tables when optimizing variables.
+<li>Fixed removal of unused parameters with 32 or more parameters.
+<li>Fixed incorrect removal of exception handler for instanceof instruction.
+<li>Fixed inlining of methods with unusual exception handlers.
+<li>Fixed optimization of unusual code causing stack underflow.
+<li>Fixed keeping of constructor parameter names.
+<li>Fixed unwanted wrapping of non-standard META-INF files.
+<li>Fixed filtering of warnings about references to array types.
+<li>Fixed overriding of warning option and note option in Ant task.
+<li>Improved detection of file name extensions for canonical paths.
+<li>Improved printing of seeds specified by <code>-keep</code> options.
+<li>Improved printing of notes about unkept classes.
+<li>Improved checking whether output is up to date.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Jun 2010</div> Version 4.5</h3>
+<ul>
+<li>Added option <code>-keepparameternames</code>.
+<li><code>-dontskipnonpubliclibraryclasses</code> is now set by default. Added
+ <code>-skipnonpubliclibraryclasses</code> as an option.
+<li>Made processing independent of order of input classes to get even more
+ deterministic output.
+<li>Improved constant field propagation.
+<li>Improved renaming of resource files in subdirectories of packages.
+<li>Avoiding making fields in interfaces private.
+<li>Optimizing exception handlers for monitorexit instruction.
+<li>Reduced maximum allowed code length after inlining from 8000 bytes to
+ 7000 bytes.
+<li>Fixed missing warnings about missing library classes.
+<li>Fixed shrinking of annotations with arrays of length 0.
+<li>Fixed handling of -0.0 and NaN values when simplifying expressions.
+<li>Fixed copying of exception handlers when simplifying tail recursion calls.
+<li>Fixed optimization of introspected fields.
+<li>Fixed simplification of unnecessary variable initializations.
+<li>Fixed evaluation of subroutines in pre-JDK 1.5 code.
+<li>Fixed updating of access flags in inner classes information.
+<li>Fixed disabling of field privatization.
+<li>Fixed invocations of privatized methods.
+<li>Fixed updating of local variable debug information in optimization step.
+<li>Fixed print settings without file name in GUI.
+<li>Fixed field privatization setting in GUI.
+<li>Fixed saving incorrectly quoted arguments in GUI.
+<li>Fixed handling of regular expressions with only negators.
+<li>Fixed unwanted wrapping of non-standard META-INF files.
+<li>Fixed regular expression pattern for constructors in ReTrace.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Jul 2009</div> Version 4.4</h3>
+<ul>
+<li>Added new peephole optimizations.
+<li>Added option <code>-optimizations</code> for fine-grained configuration of
+ optimizations.
+<li>Added option <code>-adaptclassstrings</code> for adapting string constants
+ that correspond to obfuscated classes.
+<li>Added option <code>-keeppackagenames</code> for keeping specified package
+ names from being obfuscated.
+<li>Added option <code>-keepdirectories</code> for keeping specified directory
+ entries in output jars.
+<li>Extended options <code>-dontnote</code> and <code>-dontwarn</code> for
+ fine-grained configuration of notes and warnings.
+<li>Added option <code>-regex</code> in ReTrace, for specifying alternative
+ regular expressions to parse stack traces.
+<li>Extended renaming of resource files based on obfuscation.
+<li>Improved inlining of constant parameters and removal of unused parameters.
+<li>Avoiding bug in IBM's JVM for JSE, in optimization step.
+<li>Avoiding ArrayIndexOutOfBoundsException in optimization step.
+<li>Fixed configuration with annotations that are not preserved themselves.
+<li>Fixed preverification of invocations of super constructors with arguments
+ containing ternary operators.
+<li>Fixed processing of unreachable exception handlers.
+<li>Fixed merging of exception classes.
+<li>Fixed repeated method inlining.
+<li>Fixed inlining of finally blocks surrounded by large try blocks, compiled
+ with JDK 1.4 or earlier.
+<li>Fixed optimization of complex finally blocks, compiled with JDK 1.4 or
+ earlier.
+<li>Fixed obfuscation of anonymous class names, if <code>EnclosingMethod</code>
+ attributes are being kept.
+<li>Fixed obfuscation of inner class names in generic types.
+<li>Fixed decoding of UTF-8 strings containing special characters.
+<li>Fixed copying of debug information and annotations when merging classes.
+<li>Fixed writing out of unknown attributes.
+<li>Fixed updating manifest files with split lines.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Dec 2008</div> Version 4.3</h3>
+<ul>
+<li>Added class merging.
+<li>Added static single assignment analysis.
+<li>Added support for annotation and enumeration class types in configuration.
+<li>Refined shrinking of fields in case of unusual
+ <code>-keepclassmembers</code> options.
+<li>Added simplification of tail recursion calls.
+<li>Added new peephole optimizations.
+<li>Fixed optimization of unused variable initializations causing negative
+ stack sizes.
+<li>Fixed optimization of unusual initialization code causing
+ NullPointerExceptions.
+<li>Fixed optimization of half-used long and double parameters.
+<li>Fixed processing of complex generics signatures.
+<li>Working around suspected java compiler bug with parameter annotations on
+ constructors of non-static inner classes.
+<li>Fixed obfuscation of classes with inner classes whose names are preserved.
+<li>Fixed access of protected methods in repackaged classes.
+<li>Added options <code>-classobfuscationdictionary</code> and
+ <code>-packageobfuscationdictionary</code>.
+<li>Adapting more types of resource file names based on obfuscation.
+<li>Extended warnings about incorrect dependencies.
+<li>Added start-up scripts and build scripts.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Mar 2008</div> Version 4.2</h3>
+<ul>
+<li>Refined data flow analysis in optimization step.
+<li>Fixed handling of exceptions when inlining subroutines.
+<li>Fixed inlining of incompatible code constructs between different java
+ versions.
+<li>Fixed computation of local variable frame size.
+<li>Fixed optimization of infinite loops.
+<li>Fixed optimization of subroutine invocations.
+<li>Fixed optimization of floating point remainder computations.
+<li>Fixed removal of unused parameters in method descriptors containing arrays
+ of longs or doubles.
+<li>Added undocumented java system properties
+ <code>maximum.inlined.code.length</code> (default is 8) and
+ <code>maximum.resulting.code.length</code> (defaults are 8000 for JSE and
+ 2000 for JME), for expert users who read release notes.
+<li>Fixed processing of generic types in Signature attributes in shrinking and
+ optimization steps.
+<li>Fixed processing of inner class names in Signature attributes in obfuscation
+ step.
+<li>Improved adapting resource file names following obfuscated class names.
+<li>Fixed interpretation of package names in GUI.
+<li>Fixed default settings for Xlets in GUI.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Dec 2007</div> Version 4.1</h3>
+<ul>
+<li>Fixed shrinking of default annotation element values.
+<li>Fixed optimization of invocations of methods in same class that are
+ accessed through extensions.
+<li>Fixed optimization of invocations of synchronized methods without other
+ side-effects.
+<li>Fixed optimization of some non-returning subroutines.
+<li>Fixed handling of local variable debug information when inlining methods.
+<li>Avoiding StackOverflowErrors during optimization of complex methods.
+<li>Fixed obfuscation of potentially ambiguous non-primitive constants in
+ interfaces.
+<li>Fixed preverification of some code constructs involving String, Class, and
+ exception types.
+<li>The Ant task now allows empty <code>&lt;injars&gt;</code> and
+ <code>&lt;libraryjars&gt;</code> elements.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Sep 2007</div> Version 4.0</h3>
+<ul>
+<li>Added preverifier for Java 6 and Java Micro Edition, with new options
+ <code>-microedition</code> and <code>-dontpreverify</code>.
+<li>Added new option <code>-target</code> to modify java version of processed
+ class files.
+<li>Made <code>-keep</code> options more orthogonal and flexible, with option
+ modifiers <code>allowshrinking</code>, <code>allowoptimization</code>, and
+ <code>allowobfuscation</code>.
+<li>Added new wildcards for class member descriptors: "<code>***</code>",
+ matching any type, and "<code>...</code>", matching any number of
+ arguments.
+<li>Added support for configuration by means of annotations.
+<li>Improved shrinking of unused annotations.
+<li>Added check on modification times of input and output, to avoid unnecessary
+ processing, with new option <code>-forceprocessing</code>.
+<li>Added new options <code>-flattenpackagehierarchy</code> and
+ <code>-repackageclasses</code> (replacing <code>-defaultpackage</code>) to
+ control obfuscation of package names.
+<li>Added new options <code>-adaptresourcefilenames</code> and
+ <code>-adaptresourcefilecontents</code>, with file filters, to update
+ resource files corresponding to obfuscated class names.
+<li>Added detection of dynamically accessed fields and methods.
+<li>Now treating <code>Exceptions</code> attributes as optional.
+<li>Now respecting naming rule for nested class names
+ (<code>EnclosingClass$InnerClass</code>) in obfuscation step, if
+ <code>InnerClasses</code> attributes or <code>EnclosingMethod</code>
+ attributes are being kept.
+<li>Added new inter-procedural optimizations: method inlining and propagation
+ of constant fields, constant arguments, and constant return values.
+<li>Added optimized local variable allocation.
+<li>Added more than 250 new peephole optimizations.
+<li>Improved making classes and class members public or protected.
+<li>Now printing notes on suspiciously unkept classes in parameters of
+ specified methods.
+<li>Now printing notes for class names that don't seem to be fully qualified.
+<li>Added support for uppercase filename extensions.
+<li>Added tool tips to the GUI.
+<li>Rewritten class file I/O code.
+<li>Updated documentation and examples.
+</ul>
+Upgrade considerations:
+<ul>
+
+<li>Since ProGuard now treats the <code>Exceptions</code> attribute as
+ optional, you may have to specify <code>-keepattributes Exceptions</code>,
+ notably when processing code that is to be used as a library.
+
+<li>ProGuard now preverifies code for Java Micro Edition, if you specify the
+ option <code>-microedition</code>. You then no longer need to process the
+ code with an external preverifier.
+
+<li>You should preferably specify <code>-repackageclasses</code> instead of the
+ old option name <code>-defaultpackage</code>.
+</ul>
+
+<h3><div>Dec 2007</div> Version 3.11</h3>
+<ul>
+<li>Fixed optimization of invocations of methods in same class that are
+ accessed through extensions.
+<li>Fixed optimization of invocations of synchronized methods without other
+ side-effects.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Aug 2007</div> Version 3.10</h3>
+<ul>
+<li>Now handling mixed-case input class names when
+ <code>-dontusemixedcaseclassnames</code> is specified.
+<li>Fixed optimization of synchronization on classes, as compiled by Eclipse
+ and Jikes.
+<li>Fixed optimization of switch statements with unreachable cases.
+<li>Avoiding merging subsequent identically named files.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Jun 2007</div> Version 3.9</h3>
+<ul>
+<li>Fixed processing of .class constructs in Java 6.
+<li>Fixed repeated processing of .class constructs.
+<li>Fixed possible division by 0 in optimization step.
+<li>Fixed handling of variable instructions with variable indices larger than
+ 255.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Mar 2007</div> Version 3.8</h3>
+<ul>
+<li>Fixed optimization of parameters used as local variables.
+<li>Fixed obfuscation with conflicting class member names.
+<li>Fixed incremental obfuscation with incomplete mapping file for library jars.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Dec 2006</div> Version 3.7</h3>
+<ul>
+<li>Now accepting Java 6 class files.
+<li>Fixed shrinking of partially used annotations.
+<li>Improved incremental obfuscation, with new option
+ <code>-useuniqueclassmembernames</code>.
+<li>Printing more information in case of conflicting configuration and input.
+<li>Fixed optimization of repeated array length instruction.
+<li>Fixed optimization of subsequent try/catch/finally blocks with return
+ statements.
+<li>Fixed optimization of complex stack operations.
+<li>Fixed optimization of simple infinite loops.
+<li>Fixed optimization of expressions with constant doubles.
+<li>Tuned optimization to improve size reduction after preverification.
+<li>Fixed overflows of offsets in long code blocks.
+<li>Now allowing class names containing dashes.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>May 2006</div> Version 3.6</h3>
+<ul>
+<li>No longer automatically keeping classes in parameters of specified methods
+ from obfuscation and optimization (introduced in version 3.4).
+<li>Fixed inlining of interfaces that are used in .class constructs.
+<li>Fixed removal of busy-waiting loops reading volatile fields.
+<li>Fixed optimization of comparisons of known integers.
+<li>Fixed optimization of known branches.
+<li>Fixed optimization of method calls on arrays of interfaces.
+<li>Fixed optimization of method calls without side-effects.
+<li>Fixed optimization of nested try/catch/finally blocks with return
+ statements.
+<li>Fixed initialization of library classes that only appear in descriptors.
+<li>Fixed matching of primitive type wildcards in configuration.
+<li>Fixed the boilerplate specification for enumerations in the GUI.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Jan 2006</div> Version 3.5</h3>
+<ul>
+<li>Fixed obfuscation of class members with complex visibility.
+<li>Fixed optimization bugs causing stack verification errors.
+<li>Fixed optimization bug causing overridden methods to be finalized.
+<li>Fixed optimization bug causing abstract method errors for retro-fitted
+ library methods.
+<li>Fixed optimization bug evaluating code with constant long values.
+<li>Fixed bug in updating of optional local variable table attributes and local
+ variable type table attributes after optimization.
+<li>Fixed interpretation of comma-separated class names without wildcards.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Oct 2005</div> Version 3.4</h3>
+<ul>
+<li>Extended optimizations: removing duplicate code within methods.
+<li>Extended regular expressions for class names to comma-separated lists.
+<li>Now automatically keeping classes in descriptors of kept class members.
+<li>Added verbose statistics for optimizations.
+<li>Added boilerplate Number optimizations in GUI.
+<li>Fixed <code>Class.forName</code> detection.
+<li>Fixed incremental obfuscation bug.
+<li>Fixed optimization bug causing stack verification errors.
+<li>Fixed optimization bugs related to removal of unused parameters.
+<li>Fixed exception when optimizing code with many local variables.
+<li>Fixed exception when saving configuration with initializers in GUI.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Jun 2005</div> Version 3.3</h3>
+<ul>
+<li>Extended optimizations: making methods private and static when possible,
+ making classes static when possible, removing unused parameters.
+<li>Made file names relative to the configuration files in which they are
+ specified. Added <code>-basedirectory</code> option.
+<li>Added <code>-whyareyoukeeping</code> option to get details on why given
+ classes and class members are being kept.
+<li>Added warnings for misplaced class files.
+<li>Improved printing of notes for <code>Class.forName</code> constructs.
+<li>Implemented '<code>assumenosideeffects</code>' nested element in Ant task.
+<li>Improved processing of annotations.
+<li>Fixed reading and writing of parameter annotations.
+<li>Fixed various optimization bugs.
+<li>Fixed wildcards not matching '-' character.
+<li>Fixed wildcard bug and checkbox bugs in GUI.
+<li>Setting file chooser defaults in GUI.
+<li>Leaving room for growBox in GUI on Mac OS X.
+<li>Properly closing configuration files.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Dec 2004</div> Version 3.2</h3>
+<ul>
+<li>Fixed JDK5.0 processing bugs.
+<li>Fixed optimization bugs.
+<li>Fixed relative paths in Ant task.
+<li>Improved speed of shrinking step.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Nov 2004</div> Version 3.1</h3>
+<ul>
+<li>Improved obfuscation and shrinking of private class members.
+<li>Added inlining of interfaces with single implementations.
+<li>Added option to specify obfuscation dictionary.
+<li>Added option to read package visible library class members.
+<li>Extended support for JDK5.0 attributes.
+<li>Fixed various optimization bugs.
+<li>Modified Ant task to accept paths instead of filesets.
+<li>Fixed two Ant task bugs.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Aug 2004</div> Version 3.0</h3>
+<ul>
+<li>Added bytecode optimization step, between shrinking step and obfuscation
+ step.
+<li>Generalized filtered recursive reading and writing of jars, wars, ears,
+ zips, and directories.
+<li>Added support for grouping input and output jars, wars, ears, zips, and
+ directories.
+<li>Added support for applying mapping files to library classes.
+<li>Removed <code>-resourcejars</code> option. Resources should now be read
+ using regular <code>-injars</code> options, using filters if necessary.
+<li>Rewrote Ant task. Input and output modification dates are not checked at
+ the moment. Minor changes in XML schema:
+ <ul>
+ <li>Filters now specified using attributes.
+ <li>'<code>outjars</code>' now nested element instead of attribute.
+ <li>'<code>type</code>' attribute of <code>&lt;method&gt;</code> element no
+ longer defaults to '<code>void</code>'.
+ <li><code>&lt;</code> and <code>&gt;</code> characters now have to be
+ encoded in embedded configurations.
+ <li><code>&lt;proguardconfiguration&gt;</code> task no longer accepts
+ attributes.
+ </ul>
+<li>Updated J2ME WTK plugin, now customizable through configuration file.
+<li>Updated GUI.
+<li>Fixed various processing bugs.
+<li>Fixed ReTrace parsing bugs.
+<li>Improved jar compression.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Mar 2004</div> Version 2.1</h3>
+<ul>
+<li>Added support for JDK1.5 classes.
+<li>Added additional wildcard for matching primitive types.
+<li>Added possibility to switch off notes about duplicate class definitions.
+<li>Fixed use of multiple filters on output jars.
+<li>Fixed option to keep all attributes.
+<li>Fixed various Ant task bugs.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Dec 2003</div> Version 2.0</h3>
+<ul>
+<li>Added a graphical user interface for ProGuard and ReTrace.
+<li>Added <code>-applymapping</code> option for incremental obfuscation.
+<li>Added support for filtering input and output files.
+<li>Added support for the J++ <code>SourceDir</code> attribute.
+<li>Improved detection of <code>.class</code> constructs.
+<li>Improved handling of misplaced manifest files.
+<li>Improved implementation of ReTrace.
+<li>Worked around String UTF-8 encoding bug affecting foreign characters.
+<li>Fixed exception when ignoring warnings.
+<li>Fixed various Ant task bugs.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Aug 2003</div> Version 1.7</h3>
+<ul>
+<li>Fixed various Ant task bugs.
+<li>Fixed ClassCastException due to explicitly used abstract classes with
+ implicitly used interfaces targeted at JRE1.2 (the default in JDK1.4).
+<li>Fixed <code>-defaultpackage</code> bug for protected classes and class
+ members.
+<li>Fixed ReTrace bug when retracing without line number tables.
+<li>Worked around zip package problems with duplicate out entries and rogue
+ manifest files.
+<li>Added work-around for handling malformed legacy interface class files.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>May 2003</div> Version 1.6</h3>
+<ul>
+<li>Added support for Ant.
+<li>Added support for the J2ME Wireless Toolkit.
+<li>Added support for reading and writing directory hierarchies.
+<li>Added option for specifying resource jars and directories.
+<li>Added support for wildcards in class member specifications.
+<li>Improved handling of the <code>-defaultpackage</code> option.
+<li>Improved stack trace parsing in ReTrace tool.
+<li>Fixed processing of libraries containing public as well as non-public
+ extensions of non-public classes.
+<li>Fixed examples for processing libraries, midlets, and serializable code.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Jan 2003</div> Version 1.5</h3>
+<ul>
+<li>Fixed processing of retrofitted library interfaces.
+<li>Fixed processing of <code>.class</code> constructs in internal classes
+ targeted at JRE1.2 (the default in JDK1.4).
+<li>Fixed <code>-dump</code> option when <code>-outjar</code> option is not
+ present.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Nov 2002</div> Version 1.4</h3>
+<ul>
+<li>Now copying resource files over from the input jars to the output jar.
+<li>Added option to obfuscate using lower-case class names only.
+<li>Added better option for obfuscating native methods.
+<li>Added option not to ignore non-public library classes.
+<li>Added automatic <code>.class</code> detection for classes compiled with
+ Jikes.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Sep 2002</div> Version 1.3</h3>
+<ul>
+<li>Added support for wildcards in class names.
+<li>Added tool to de-obfuscate stack traces.
+<li>Added options to print processing information to files.
+<li>Added option to rename source file attributes.
+<li>Fixed processing of implicitly used interfaces targeted at JRE1.2 (the
+ default in JDK1.4)
+<li>Fixed processing of configurations with negated access modifiers.
+<li>Fixed duplicate class entry bug.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Aug 2002</div> Version 1.2</h3>
+<ul>
+<li>Improved speed.
+<li>Fixed processing of classes targeted at JRE1.2 (the default in JDK1.4)
+ with references to their own subclasses.
+<li>Fixed processing of static initializers in J2ME MIDP applications.
+<li>Fixed processing of retrofitted interfaces (again).
+<li>Added more flexible handling of white space in configuration.
+<li>Updated documentation.
+</ul>
+
+<h3><div>Jul 2002</div> Version 1.1</h3>
+<ul>
+<li>Added automatic detection of <code>Class.forName("MyClass")</code>,
+ <code>MyClass.class</code>, and
+ <code>(MyClass)Class.forName(variable).newInstance()</code> constructs.
+ This greatly simplifies configuration.
+<li>Added options to keep class names and class member names without affecting
+ any shrinking. They are mostly useful for native methods and serializable
+ classes.
+<li>Fixed processing of retrofitted interfaces.
+<li>Added handling of missing/invalid manifest file in input jar.
+<li>Updated documentation and examples.
+</ul>
+
+<h3><div>Jun 2002</div> Version 1.0</h3>
+<ul>
+<li>First public release, based on class parsing code from Mark Welsh's
+ <b>RetroGuard</b>.
+</ul>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/drop1.gif b/third_party/java/proguard/proguard5.3.3/docs/drop1.gif
new file mode 100644
index 0000000000..426d856412
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/drop1.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/drop2.gif b/third_party/java/proguard/proguard5.3.3/docs/drop2.gif
new file mode 100644
index 0000000000..b6075421d8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/drop2.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/drop3.gif b/third_party/java/proguard/proguard5.3.3/docs/drop3.gif
new file mode 100644
index 0000000000..11ce424b2e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/drop3.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/favicon.ico b/third_party/java/proguard/proguard5.3.3/docs/favicon.ico
new file mode 100644
index 0000000000..3923ec14ef
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/favicon.ico
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/feedback.html b/third_party/java/proguard/proguard5.3.3/docs/feedback.html
new file mode 100644
index 0000000000..30668ddd3b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/feedback.html
@@ -0,0 +1,104 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-script-type" content="text/javascript">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Feedback</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="index.html#feedback.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="index.html#feedback.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Feedback</h2>
+
+By now, I've invested an enormous amount of time in <b>ProGuard</b>. You can
+help by providing feedback! If you have problems, bugs, bug fixes, ideas,
+encouragements, etc., please let me know:
+<p>
+<ul class="spacious">
+<li>Through
+ <a href="http://www.guardsquare.com/proguard/support" target="_top">GuardSquare</a>,
+ we provide professional support for ProGuard. If you find ProGuard useful
+ and you would like to have some professional backing, this is the place to
+ go.</li>
+
+<li>The <a href="https://sourceforge.net/projects/proguard/forums/forum/182456"
+ target="other">help forum</a> (at SourceForge)
+ and <a href="http://stackoverflow.com/questions/tagged/proguard"
+ target="other">Stack Overflow</a> are common places to ask questions about
+ any problems you might have configuring and running ProGuard. At this
+ time, I can generally only assist other open source projects though. If
+ you're working on commercial software, please consider our professional
+ support above.</li>
+
+<li>The <a href="https://sourceforge.net/projects/proguard/forums/forum/182455"
+ target="other">open discussion forum</a> (at SourceForge) offers a place
+ to share your thoughts and discuss new ideas.</li>
+
+<li>The <a href="http://sourceforge.net/p/proguard/bugs/" target="other">bug
+ tracking page</a> (at SourceForge) allows you to submit and consult bug
+ reports. Please make sure the reports are complete and concise. If I can't
+ reproduce the problem, I most likely can't fix it either.</li>
+
+<li>The <a href="http://sourceforge.net/p/proguard/feature-requests/"
+ target="other">feature request page</a> (at SourceForge) allows you to
+ submit and consult feature requests. I generally have my own road map in
+ mind, but this is the place express your interest in new and existing
+ ideas.</li>
+
+<li>The <a href="https://sourceforge.net/projects/proguard/files/"
+ target="other">download section</a> at SourceForge may offer the
+ possibility to subscribe to the announcements of new releases. They are
+ the most efficient way to stay abreast of the latest developments.</li>
+
+<li>For anything that doesn't fall in the above categories, you can mail me
+ directly at
+
+<script type="text/javascript" language="JavaScript">
+<!--
+document.write("<a href=\"ma");
+document.write("ilto:");
+document.write("lafortune");
+document.write("&#64;");
+document.write("users.sourceforge.net\">");
+document.write("lafortune");
+document.write("&#64;");
+document.write("users.sourceforge.net");
+document.write("<\/a>");
+//-->
+</script>
+<noscript>
+&lt;&nbsp;lafortune&nbsp;&#64;&nbsp;users&nbsp;.&nbsp;sourceforge&nbsp;.&nbsp;net&nbsp;&gt; (please remove the spaces)
+</noscript>
+.</li>
+</ul>
+<p>
+I can't promise an answer, but it's always great to see constructive comments.
+<p>
+
+<b>ProGuard</b> isn't a typical open source project, in the sense that I am
+<em>not</em> looking for code contributions. Developing on my own allows me to
+do things my way, without the overhead and compromises associated with larger
+projects.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.eot b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.eot
new file mode 100644
index 0000000000..e1c7674430
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.eot
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.svg b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.svg
new file mode 100644
index 0000000000..364b368678
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.svg
@@ -0,0 +1,146 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG webfont generated by Font Squirrel.
+Copyright : Digitized data copyright 20102011 Google Corporation
+Foundry : Ascender Corporation
+Foundry URL : httpwwwascendercorpcom
+</metadata>
+<defs>
+<font id="OpenSansBold" horiz-adv-x="1169" >
+<font-face units-per-em="2048" ascent="1638" descent="-410" />
+<missing-glyph horiz-adv-x="532" />
+<glyph unicode=" " horiz-adv-x="532" />
+<glyph unicode="&#x09;" horiz-adv-x="532" />
+<glyph unicode="&#xa0;" horiz-adv-x="532" />
+<glyph unicode="!" horiz-adv-x="586" d="M117 143q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5zM121 1462h346l-51 -977h-244z" />
+<glyph unicode="&#x22;" horiz-adv-x="967" d="M133 1462h279l-41 -528h-197zM555 1462h279l-41 -528h-197z" />
+<glyph unicode="#" horiz-adv-x="1323" d="M45 406v206h277l47 232h-252v209h289l77 407h219l-77 -407h198l78 407h215l-78 -407h240v-209h-279l-47 -232h258v-206h-297l-77 -406h-220l78 406h-194l-76 -406h-215l74 406h-238zM539 612h196l47 232h-196z" />
+<glyph unicode="$" d="M88 1049q0 145 113.5 238.5t316.5 113.5v153h137v-149q229 -10 414 -92l-94 -234q-156 64 -320 78v-295q195 -75 277.5 -130t121 -121t38.5 -154q0 -159 -115 -255.5t-322 -115.5v-205h-137v201q-244 5 -428 86v264q87 -43 209.5 -76t218.5 -39v310l-67 26 q-198 78 -280.5 169.5t-82.5 226.5zM389 1049q0 -44 30.5 -72.5t98.5 -58.5v235q-129 -19 -129 -104zM655 324q136 23 136 118q0 42 -34 71t-102 60v-249z" />
+<glyph unicode="%" horiz-adv-x="1845" d="M63 1026q0 457 345 457q169 0 259.5 -118.5t90.5 -338.5q0 -230 -89 -345.5t-261 -115.5q-165 0 -255 118.5t-90 342.5zM315 1024q0 -127 22.5 -189.5t72.5 -62.5q96 0 96 252q0 250 -96 250q-50 0 -72.5 -61.5t-22.5 -188.5zM395 0l811 1462h240l-811 -1462h-240z M1087 442q0 457 345 457q169 0 259.5 -118.5t90.5 -338.5q0 -229 -89 -344.5t-261 -115.5q-165 0 -255 118.5t-90 341.5zM1339 440q0 -127 22.5 -189.5t72.5 -62.5q96 0 96 252q0 250 -96 250q-50 0 -72.5 -61.5t-22.5 -188.5z" />
+<glyph unicode="&#x26;" horiz-adv-x="1536" d="M82 395q0 137 60.5 233.5t207.5 180.5q-75 86 -109 164.5t-34 171.5q0 152 116.5 245t311.5 93q186 0 297.5 -86.5t111.5 -231.5q0 -119 -69 -217.5t-223 -187.5l284 -277q71 117 123 301h318q-36 -135 -99 -263.5t-143 -227.5l301 -293h-377l-115 113 q-191 -133 -432 -133q-244 0 -387 112t-143 303zM403 424q0 -86 64.5 -137t165.5 -51q126 0 227 61l-332 330q-58 -44 -91.5 -92t-33.5 -111zM489 1124q0 -88 95 -194q86 48 132 94.5t46 108.5q0 53 -36 83.5t-93 30.5q-67 0 -105.5 -32t-38.5 -91z" />
+<glyph unicode="'" horiz-adv-x="545" d="M133 1462h279l-41 -528h-197z" />
+<glyph unicode="(" horiz-adv-x="694" d="M82 561q0 265 77.5 496t223.5 405h250q-141 -193 -213 -424t-72 -475q0 -245 73.5 -473.5t209.5 -413.5h-248q-147 170 -224 397t-77 488z" />
+<glyph unicode=")" horiz-adv-x="694" d="M61 1462h250q147 -175 224 -406.5t77 -494.5t-77.5 -490t-223.5 -395h-248q135 184 209 412.5t74 474.5q0 244 -72 475t-213 424z" />
+<glyph unicode="*" horiz-adv-x="1116" d="M63 1042l39 250l365 -104l-41 368h262l-41 -368l373 104l33 -252l-340 -24l223 -297l-227 -121l-156 313l-137 -311l-236 119l221 297z" />
+<glyph unicode="+" d="M88 612v219h387v390h219v-390h387v-219h-387v-385h-219v385h-387z" />
+<glyph unicode="," horiz-adv-x="594" d="M63 -264q65 266 101 502h280l15 -23q-52 -202 -176 -479h-220z" />
+<glyph unicode="-" horiz-adv-x="659" d="M61 424v250h537v-250h-537z" />
+<glyph unicode="." horiz-adv-x="584" d="M117 143q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5z" />
+<glyph unicode="/" horiz-adv-x="846" d="M14 0l545 1462h277l-545 -1462h-277z" />
+<glyph unicode="0" d="M74 731q0 387 125 570.5t385 183.5q253 0 382.5 -192t129.5 -562q0 -383 -125.5 -567t-386.5 -184q-253 0 -381.5 190t-128.5 561zM381 731q0 -269 46.5 -385.5t156.5 -116.5q108 0 156 118t48 384q0 269 -48.5 386.5t-155.5 117.5q-109 0 -156 -117.5t-47 -386.5z" />
+<glyph unicode="1" d="M121 1087l471 375h254v-1462h-309v846l3 139l5 152q-77 -77 -107 -101l-168 -135z" />
+<glyph unicode="2" d="M78 1274q108 92 179 130t155 58.5t188 20.5q137 0 242 -50t163 -140t58 -206q0 -101 -35.5 -189.5t-110 -181.5t-262.5 -265l-188 -177v-14h637v-260h-1022v215l367 371q163 167 213 231.5t72 119.5t22 114q0 88 -48.5 131t-129.5 43q-85 0 -165 -39t-167 -111z" />
+<glyph unicode="3" d="M78 59v263q85 -43 187 -70t202 -27q153 0 226 52t73 167q0 103 -84 146t-268 43h-111v237h113q170 0 248.5 44.5t78.5 152.5q0 166 -208 166q-72 0 -146.5 -24t-165.5 -83l-143 213q200 144 477 144q227 0 358.5 -92t131.5 -256q0 -137 -83 -233t-233 -132v-6 q177 -22 268 -107.5t91 -230.5q0 -211 -153 -328.5t-437 -117.5q-238 0 -422 79z" />
+<glyph unicode="4" d="M35 303v215l641 944h285v-919h176v-240h-176v-303h-302v303h-624zM307 543h352v248q0 62 5 180t8 137h-8q-37 -82 -89 -160z" />
+<glyph unicode="5" d="M100 59v267q79 -42 184 -68.5t199 -26.5q283 0 283 232q0 221 -293 221q-53 0 -117 -10.5t-104 -22.5l-123 66l55 745h793v-262h-522l-27 -287l35 7q61 14 151 14q212 0 337.5 -119t125.5 -326q0 -245 -151 -377t-432 -132q-244 0 -394 79z" />
+<glyph unicode="6" d="M72 621q0 434 183.5 646t549.5 212q125 0 196 -15v-247q-89 20 -176 20q-159 0 -259.5 -48t-150.5 -142t-59 -267h13q99 170 317 170q196 0 307 -123t111 -340q0 -234 -132 -370.5t-366 -136.5q-162 0 -282.5 75t-186 219t-65.5 347zM379 510q0 -119 62.5 -201t158.5 -82 q99 0 152 66.5t53 189.5q0 107 -49.5 168.5t-149.5 61.5q-94 0 -160.5 -61t-66.5 -142z" />
+<glyph unicode="7" d="M55 1200v260h1049v-194l-553 -1266h-324l549 1200h-721z" />
+<glyph unicode="8" d="M72 371q0 125 66.5 222t213.5 171q-125 79 -180 169t-55 197q0 157 130 254t339 97q210 0 338.5 -95.5t128.5 -257.5q0 -112 -62 -199.5t-200 -156.5q164 -88 235.5 -183.5t71.5 -209.5q0 -180 -141 -289.5t-371 -109.5q-240 0 -377 102t-137 289zM358 389q0 -86 60 -134 t164 -48q115 0 172 49.5t57 130.5q0 67 -56.5 125.5t-183.5 124.5q-213 -98 -213 -248zM408 1106q0 -60 38.5 -107.5t139.5 -97.5q98 46 137 94t39 111q0 69 -50 109t-128 40q-79 0 -127.5 -40.5t-48.5 -108.5z" />
+<glyph unicode="9" d="M66 971q0 235 133.5 371.5t363.5 136.5q162 0 283.5 -76t186.5 -220.5t65 -344.5q0 -432 -182 -645t-551 -213q-130 0 -197 14v248q84 -21 176 -21q155 0 255 45.5t153 143t61 268.5h-12q-58 -94 -134 -132t-190 -38q-191 0 -301 122.5t-110 340.5zM365 975 q0 -106 49 -168t149 -62q94 0 161 61.5t67 141.5q0 119 -62.5 201t-159.5 82q-96 0 -150 -66t-54 -190z" />
+<glyph unicode=":" horiz-adv-x="584" d="M117 143q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5zM117 969q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -81 -46.5 -125.5t-127.5 -44.5q-84 0 -130 44t-46 126z" />
+<glyph unicode=";" horiz-adv-x="594" d="M63 -264q65 266 101 502h280l15 -23q-52 -202 -176 -479h-220zM117 969q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -81 -46.5 -125.5t-127.5 -44.5q-84 0 -130 44t-46 126z" />
+<glyph unicode="&#x3c;" d="M88 641v143l993 496v-240l-684 -317l684 -281v-239z" />
+<glyph unicode="=" d="M88 418v219h993v-219h-993zM88 805v219h993v-219h-993z" />
+<glyph unicode="&#x3e;" d="M88 203v239l684 281l-684 317v240l993 -496v-143z" />
+<glyph unicode="?" horiz-adv-x="977" d="M6 1358q223 125 473 125q206 0 327.5 -99t121.5 -264q0 -110 -50 -190t-190 -180q-96 -71 -121.5 -108t-25.5 -97v-60h-265v74q0 96 41 167t150 151q105 75 138.5 122t33.5 105q0 65 -48 99t-134 34q-150 0 -342 -98zM244 143q0 84 45 127t131 43q83 0 128.5 -44 t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5z" />
+<glyph unicode="@" horiz-adv-x="1837" d="M102 602q0 247 108.5 448.5t309 316t461.5 114.5q220 0 393 -90t267 -256t94 -383q0 -144 -46 -263.5t-130 -187.5t-195 -68q-74 0 -131 35.5t-82 93.5h-16q-108 -129 -275 -129q-177 0 -279 106.5t-102 291.5q0 211 134 340t350 129q86 0 189.5 -16.5t170.5 -39.5 l-23 -489q0 -139 76 -139q64 0 102 93.5t38 244.5q0 161 -67 284.5t-188.5 188.5t-277.5 65q-202 0 -351 -83t-228.5 -239.5t-79.5 -361.5q0 -276 147.5 -423.5t427.5 -147.5q106 0 233 23.5t250 68.5v-192q-214 -91 -475 -91q-380 0 -592.5 200t-212.5 556zM711 627 q0 -211 172 -211q90 0 137 63.5t57 206.5l13 221q-51 11 -115 11q-125 0 -194.5 -78t-69.5 -213z" />
+<glyph unicode="A" horiz-adv-x="1413" d="M0 0l516 1468h379l518 -1468h-334l-106 348h-533l-106 -348h-334zM518 608h381q-147 473 -165.5 535t-26.5 98q-33 -128 -189 -633z" />
+<glyph unicode="B" horiz-adv-x="1376" d="M184 0v1462h455q311 0 451.5 -88.5t140.5 -281.5q0 -131 -61.5 -215t-163.5 -101v-10q139 -31 200.5 -116t61.5 -226q0 -200 -144.5 -312t-392.5 -112h-547zM494 256h202q128 0 189 49t61 150q0 182 -260 182h-192v-381zM494 883h180q126 0 182.5 39t56.5 129 q0 84 -61.5 120.5t-194.5 36.5h-163v-325z" />
+<glyph unicode="C" horiz-adv-x="1305" d="M119 729q0 228 83 399.5t238.5 263t364.5 91.5q213 0 428 -103l-100 -252q-82 39 -165 68t-163 29q-175 0 -271 -131.5t-96 -366.5q0 -489 367 -489q154 0 373 77v-260q-180 -75 -402 -75q-319 0 -488 193.5t-169 555.5z" />
+<glyph unicode="D" horiz-adv-x="1516" d="M184 0v1462h459q358 0 556 -189t198 -528q0 -361 -205.5 -553t-593.5 -192h-414zM494 256h133q448 0 448 481q0 471 -416 471h-165v-952z" />
+<glyph unicode="E" horiz-adv-x="1147" d="M184 0v1462h842v-254h-532v-321h495v-254h-495v-377h532v-256h-842z" />
+<glyph unicode="F" horiz-adv-x="1124" d="M184 0v1462h838v-254h-533v-377h496v-253h-496v-578h-305z" />
+<glyph unicode="G" horiz-adv-x="1483" d="M119 733q0 354 202.5 552t561.5 198q225 0 434 -90l-103 -248q-160 80 -333 80q-201 0 -322 -135t-121 -363q0 -238 97.5 -363.5t283.5 -125.5q97 0 197 20v305h-277v258h580v-758q-141 -46 -265.5 -64.5t-254.5 -18.5q-331 0 -505.5 194.5t-174.5 558.5z" />
+<glyph unicode="H" horiz-adv-x="1567" d="M184 0v1462h310v-573h579v573h309v-1462h-309v631h-579v-631h-310z" />
+<glyph unicode="I" horiz-adv-x="678" d="M184 0v1462h310v-1462h-310z" />
+<glyph unicode="J" horiz-adv-x="678" d="M-152 -150q80 -20 146 -20q102 0 146 63.5t44 198.5v1370h310v-1368q0 -256 -117 -390t-346 -134q-105 0 -183 22v258z" />
+<glyph unicode="K" horiz-adv-x="1360" d="M184 0v1462h310v-669l122 172l396 497h344l-510 -647l514 -815h-352l-383 616l-131 -94v-522h-310z" />
+<glyph unicode="L" horiz-adv-x="1157" d="M184 0v1462h310v-1206h593v-256h-903z" />
+<glyph unicode="M" horiz-adv-x="1931" d="M184 0v1462h422l346 -1118h6l367 1118h422v-1462h-289v692q0 49 1.5 113t13.5 340h-9l-377 -1145h-284l-352 1147h-9q19 -350 19 -467v-680h-277z" />
+<glyph unicode="N" horiz-adv-x="1665" d="M184 0v1462h391l635 -1095h7q-15 285 -15 403v692h279v-1462h-394l-636 1106h-9q19 -293 19 -418v-688h-277z" />
+<glyph unicode="O" horiz-adv-x="1630" d="M119 735q0 365 180.5 557.5t517.5 192.5t515.5 -194t178.5 -558q0 -363 -180 -558t-516 -195t-516 195t-180 560zM444 733q0 -245 93 -369t278 -124q371 0 371 493q0 494 -369 494q-185 0 -279 -124.5t-94 -369.5z" />
+<glyph unicode="P" horiz-adv-x="1286" d="M184 0v1462h467q266 0 404.5 -114.5t138.5 -341.5q0 -236 -147.5 -361t-419.5 -125h-133v-520h-310zM494 774h102q143 0 214 56.5t71 164.5q0 109 -59.5 161t-186.5 52h-141v-434z" />
+<glyph unicode="Q" horiz-adv-x="1630" d="M119 735q0 365 180.5 557.5t517.5 192.5t515.5 -194t178.5 -558q0 -258 -91.5 -432.5t-268.5 -255.5l352 -393h-397l-268 328h-23q-336 0 -516 195t-180 560zM444 733q0 -245 93 -369t278 -124q371 0 371 493q0 494 -369 494q-185 0 -279 -124.5t-94 -369.5z" />
+<glyph unicode="R" horiz-adv-x="1352" d="M184 0v1462h426q298 0 441 -108.5t143 -329.5q0 -129 -71 -229.5t-201 -157.5q330 -493 430 -637h-344l-349 561h-165v-561h-310zM494 813h100q147 0 217 49t70 154q0 104 -71.5 148t-221.5 44h-94v-395z" />
+<glyph unicode="S" horiz-adv-x="1128" d="M94 68v288q148 -66 250.5 -93t187.5 -27q102 0 156.5 39t54.5 116q0 43 -24 76.5t-70.5 64.5t-189.5 99q-134 63 -201 121t-107 135t-40 180q0 194 131.5 305t363.5 111q114 0 217.5 -27t216.5 -76l-100 -241q-117 48 -193.5 67t-150.5 19q-88 0 -135 -41t-47 -107 q0 -41 19 -71.5t60.5 -59t196.5 -102.5q205 -98 281 -196.5t76 -241.5q0 -198 -142.5 -312t-396.5 -114q-234 0 -414 88z" />
+<glyph unicode="T" horiz-adv-x="1186" d="M41 1204v258h1104v-258h-397v-1204h-310v1204h-397z" />
+<glyph unicode="U" horiz-adv-x="1548" d="M174 520v942h309v-895q0 -169 68 -248t225 -79q152 0 220.5 79.5t68.5 249.5v893h309v-946q0 -162 -72.5 -284t-209.5 -187t-324 -65q-282 0 -438 144.5t-156 395.5z" />
+<glyph unicode="V" horiz-adv-x="1331" d="M0 1462h313l275 -870q23 -77 47.5 -179.5t30.5 -142.5q11 92 75 322l277 870h313l-497 -1462h-338z" />
+<glyph unicode="W" horiz-adv-x="1980" d="M0 1462h305l187 -798q49 -221 71 -383q6 57 27.5 176.5t40.5 185.5l213 819h293l213 -819q14 -55 35 -168t32 -194q10 78 32 194.5t40 188.5l186 798h305l-372 -1462h-353l-198 768q-11 41 -37.5 169.5t-30.5 172.5q-6 -54 -30 -173.5t-37 -170.5l-197 -766h-352z" />
+<glyph unicode="X" horiz-adv-x="1366" d="M0 0l485 754l-454 708h342l315 -526l309 526h334l-459 -725l494 -737h-354l-340 553l-340 -553h-332z" />
+<glyph unicode="Y" horiz-adv-x="1278" d="M0 1462h336l303 -602l305 602h334l-485 -893v-569h-308v559z" />
+<glyph unicode="Z" horiz-adv-x="1186" d="M49 0v201l701 1005h-682v256h1050v-200l-700 -1006h719v-256h-1088z" />
+<glyph unicode="[" horiz-adv-x="678" d="M143 -324v1786h484v-211h-224v-1364h224v-211h-484z" />
+<glyph unicode="\" horiz-adv-x="846" d="M12 1462h277l545 -1462h-277z" />
+<glyph unicode="]" horiz-adv-x="678" d="M51 -113h223v1364h-223v211h484v-1786h-484v211z" />
+<glyph unicode="^" horiz-adv-x="1090" d="M8 520l438 950h144l495 -950h-239l-322 643l-280 -643h-236z" />
+<glyph unicode="_" horiz-adv-x="842" d="M-4 -184h850v-140h-850v140z" />
+<glyph unicode="`" horiz-adv-x="1243" d="M332 1548v21h342q63 -101 235 -301v-27h-202q-63 44 -185 142.5t-190 164.5z" />
+<glyph unicode="a" horiz-adv-x="1237" d="M86 334q0 178 124.5 262.5t375.5 93.5l194 6v49q0 170 -174 170q-134 0 -315 -81l-101 206q193 101 428 101q225 0 345 -98t120 -298v-745h-213l-59 152h-8q-77 -97 -158.5 -134.5t-212.5 -37.5q-161 0 -253.5 92t-92.5 262zM399 332q0 -129 148 -129q106 0 169.5 61 t63.5 162v92l-118 -4q-133 -4 -198 -48t-65 -134z" />
+<glyph unicode="b" horiz-adv-x="1296" d="M160 0v1556h305v-362q0 -69 -12 -221h12q107 166 317 166q198 0 310 -154.5t112 -423.5q0 -277 -115.5 -429t-314.5 -152q-197 0 -309 143h-21l-51 -123h-233zM465 563q0 -180 53.5 -258t169.5 -78q94 0 149.5 86.5t55.5 251.5t-56 247.5t-153 82.5q-113 0 -165 -69.5 t-54 -229.5v-33z" />
+<glyph unicode="c" horiz-adv-x="1053" d="M92 553q0 285 142 435.5t407 150.5q194 0 348 -76l-90 -236q-72 29 -134 47.5t-124 18.5q-238 0 -238 -338q0 -328 238 -328q88 0 163 23.5t150 73.5v-261q-74 -47 -149.5 -65t-190.5 -18q-522 0 -522 573z" />
+<glyph unicode="d" horiz-adv-x="1296" d="M92 557q0 275 114.5 428.5t315.5 153.5q211 0 322 -164h10q-23 125 -23 223v358h306v-1556h-234l-59 145h-13q-104 -165 -317 -165q-197 0 -309.5 153t-112.5 424zM401 553q0 -165 57 -247.5t163 -82.5q117 0 171.5 68t59.5 231v33q0 180 -55.5 258t-180.5 78 q-102 0 -158.5 -86.5t-56.5 -251.5z" />
+<glyph unicode="e" horiz-adv-x="1210" d="M92 551q0 281 140.5 434.5t388.5 153.5q237 0 369 -135t132 -373v-148h-721q5 -130 77 -203t202 -73q101 0 191 21t188 67v-236q-80 -40 -171 -59.5t-222 -19.5q-270 0 -422 149t-152 422zM408 686h428q-2 113 -59 174.5t-154 61.5t-152 -61.5t-63 -174.5z" />
+<glyph unicode="f" horiz-adv-x="793" d="M41 889v147l168 82v82q0 191 94 279t301 88q158 0 281 -47l-78 -224q-92 29 -170 29q-65 0 -94 -38.5t-29 -98.5v-70h264v-229h-264v-889h-305v889h-168z" />
+<glyph unicode="g" horiz-adv-x="1157" d="M6 -182q0 101 63 169t185 97q-47 20 -82 65.5t-35 96.5q0 64 37 106.5t107 83.5q-88 38 -139.5 122t-51.5 198q0 183 119 283t340 100q47 0 111.5 -8.5t82.5 -12.5h390v-155l-175 -45q48 -75 48 -168q0 -180 -125.5 -280.5t-348.5 -100.5l-55 3l-45 5q-47 -36 -47 -80 q0 -66 168 -66h190q184 0 280.5 -79t96.5 -232q0 -196 -163.5 -304t-469.5 -108q-234 0 -357.5 81.5t-123.5 228.5zM270 -158q0 -63 60.5 -99t169.5 -36q164 0 257 45t93 123q0 63 -55 87t-170 24h-158q-84 0 -140.5 -39.5t-56.5 -104.5zM381 752q0 -91 41.5 -144t126.5 -53 q86 0 126 53t40 144q0 202 -166 202q-168 0 -168 -202z" />
+<glyph unicode="h" horiz-adv-x="1346" d="M160 0v1556h305v-317q0 -37 -7 -174l-7 -90h16q102 164 324 164q197 0 299 -106t102 -304v-729h-305v653q0 242 -180 242q-128 0 -185 -87t-57 -282v-526h-305z" />
+<glyph unicode="i" horiz-adv-x="625" d="M147 1407q0 149 166 149t166 -149q0 -71 -41.5 -110.5t-124.5 -39.5q-166 0 -166 150zM160 0v1118h305v-1118h-305z" />
+<glyph unicode="j" horiz-adv-x="625" d="M-131 -227q70 -19 143 -19q77 0 112.5 43t35.5 127v1194h305v-1239q0 -178 -103 -274.5t-292 -96.5q-117 0 -201 25v240zM147 1407q0 149 166 149t166 -149q0 -71 -41.5 -110.5t-124.5 -39.5q-166 0 -166 150z" />
+<glyph unicode="k" horiz-adv-x="1270" d="M160 0v1556h305v-694l-16 -254h4l133 170l313 340h344l-444 -485l471 -633h-352l-322 453l-131 -105v-348h-305z" />
+<glyph unicode="l" horiz-adv-x="625" d="M160 0v1556h305v-1556h-305z" />
+<glyph unicode="m" horiz-adv-x="2011" d="M160 0v1118h233l41 -143h17q45 77 130 120.5t195 43.5q251 0 340 -164h27q45 78 132.5 121t197.5 43q190 0 287.5 -97.5t97.5 -312.5v-729h-306v653q0 121 -40.5 181.5t-127.5 60.5q-112 0 -167.5 -80t-55.5 -254v-561h-305v653q0 121 -40.5 181.5t-127.5 60.5 q-117 0 -170 -86t-53 -283v-526h-305z" />
+<glyph unicode="n" horiz-adv-x="1346" d="M160 0v1118h233l41 -143h17q51 81 140.5 122.5t203.5 41.5q195 0 296 -105.5t101 -304.5v-729h-305v653q0 121 -43 181.5t-137 60.5q-128 0 -185 -85.5t-57 -283.5v-526h-305z" />
+<glyph unicode="o" horiz-adv-x="1268" d="M92 561q0 274 143 426t402 152q161 0 284 -70t189 -201t66 -307q0 -273 -144 -427t-401 -154q-161 0 -284 70.5t-189 202.5t-66 308zM403 561q0 -166 54.5 -251t177.5 -85q122 0 175.5 84.5t53.5 251.5q0 166 -54 249t-177 83q-122 0 -176 -82.5t-54 -249.5z" />
+<glyph unicode="p" horiz-adv-x="1296" d="M160 -492v1610h248l43 -145h14q107 166 317 166q198 0 310 -153t112 -425q0 -179 -52.5 -311t-149.5 -201t-228 -69q-197 0 -309 143h-16q16 -140 16 -162v-453h-305zM465 563q0 -180 53.5 -258t169.5 -78q205 0 205 338q0 165 -50.5 247.5t-158.5 82.5 q-113 0 -165 -69.5t-54 -229.5v-33z" />
+<glyph unicode="q" horiz-adv-x="1296" d="M92 557q0 274 114.5 428t313.5 154q106 0 185 -40t139 -124h8l27 143h258v-1610h-306v469q0 61 13 168h-13q-49 -81 -130 -123t-187 -42q-198 0 -310 152.5t-112 424.5zM403 553q0 -168 53.5 -251t166.5 -83q116 0 170 66.5t59 232.5v37q0 180 -55.5 258t-178.5 78 q-215 0 -215 -338z" />
+<glyph unicode="r" horiz-adv-x="930" d="M160 0v1118h231l45 -188h15q52 94 140.5 151.5t192.5 57.5q62 0 103 -9l-23 -286q-37 10 -90 10q-146 0 -227.5 -75t-81.5 -210v-569h-305z" />
+<glyph unicode="s" horiz-adv-x="1018" d="M92 827q0 149 115.5 230.5t327.5 81.5q202 0 393 -88l-92 -220q-84 36 -157 59t-149 23q-135 0 -135 -73q0 -41 43.5 -71t190.5 -89q131 -53 192 -99t90 -106t29 -143q0 -172 -119.5 -262t-357.5 -90q-122 0 -208 16.5t-161 48.5v252q85 -40 191.5 -67t187.5 -27 q166 0 166 96q0 36 -22 58.5t-76 51t-144 66.5q-129 54 -189.5 100t-88 105.5t-27.5 146.5z" />
+<glyph unicode="t" horiz-adv-x="889" d="M47 889v129l168 102l88 236h195v-238h313v-229h-313v-539q0 -65 36.5 -96t96.5 -31q80 0 192 35v-227q-114 -51 -280 -51q-183 0 -266.5 92.5t-83.5 277.5v539h-146z" />
+<glyph unicode="u" horiz-adv-x="1346" d="M154 389v729h305v-653q0 -121 43 -181.5t137 -60.5q128 0 185 85.5t57 283.5v526h305v-1118h-234l-41 143h-16q-49 -78 -139 -120.5t-205 -42.5q-197 0 -297 105.5t-100 303.5z" />
+<glyph unicode="v" horiz-adv-x="1165" d="M0 1118h319l216 -637q36 -121 45 -229h6q5 96 45 229l215 637h319l-426 -1118h-313z" />
+<glyph unicode="w" horiz-adv-x="1753" d="M20 1118h304l129 -495q31 -133 63 -367h6q4 76 35 241l16 85l138 536h336l131 -536q4 -22 12.5 -65t16.5 -91.5t14.5 -95t7.5 -74.5h6q9 72 32 197.5t33 169.5l134 495h299l-322 -1118h-332l-86 391l-116 494h-7l-204 -885h-328z" />
+<glyph unicode="x" horiz-adv-x="1184" d="M10 0l379 571l-360 547h346l217 -356l219 356h346l-364 -547l381 -571h-347l-235 383l-236 -383h-346z" />
+<glyph unicode="y" horiz-adv-x="1165" d="M0 1118h334l211 -629q27 -82 37 -194h6q11 103 43 194l207 629h327l-473 -1261q-65 -175 -185.5 -262t-281.5 -87q-79 0 -155 17v242q55 -13 120 -13q81 0 141.5 49.5t94.5 149.5l18 55z" />
+<glyph unicode="z" horiz-adv-x="999" d="M55 0v180l518 705h-487v233h834v-198l-504 -687h522v-233h-883z" />
+<glyph unicode="{" horiz-adv-x="807" d="M31 449v239q126 0 191 44t65 126v8v318q0 153 97 215.5t341 62.5v-225q-99 -3 -136.5 -38t-37.5 -103v-299q-6 -188 -234 -222v-12q234 -35 234 -212v-9v-299q0 -68 37 -103t137 -38v-226q-244 0 -341 62.5t-97 216.5v315q0 87 -65.5 133t-190.5 46z" />
+<glyph unicode="|" horiz-adv-x="1128" d="M455 -465v2015h219v-2015h-219z" />
+<glyph unicode="}" horiz-adv-x="807" d="M82 -98q99 2 136.5 36t37.5 105v299v11q0 86 59 139.5t174 70.5v12q-227 34 -233 222v299q0 70 -37 104t-137 37v225q167 0 262 -26.5t135.5 -84t40.5 -167.5v-318v-10q0 -84 61.5 -126t194.5 -42v-239q-125 0 -190.5 -41t-65.5 -138v-315q0 -112 -41 -169t-135.5 -83.5 t-261.5 -26.5v226z" />
+<glyph unicode="~" d="M88 551v231q103 109 256 109q73 0 137.5 -16t139.5 -48q129 -55 227 -55q53 0 116 32t117 89v-231q-101 -109 -256 -109q-66 0 -126 13t-150 50q-131 56 -227 56q-55 0 -117.5 -33.5t-116.5 -87.5z" />
+<glyph unicode="&#xa2;" d="M143 741q0 261 104.5 403t315.5 173v166h178v-158q166 -9 299 -74l-90 -235q-72 29 -134 47t-124 18q-121 0 -179 -83.5t-58 -254.5q0 -327 237 -327q82 0 148 15.5t166 60.5v-254q-127 -61 -265 -70v-188h-178v196q-420 59 -420 565z" />
+<glyph unicode="&#xa3;" d="M82 0v248q103 44 141.5 101t38.5 157v145h-178v219h178v195q0 201 114.5 309.5t323.5 108.5q195 0 390 -82l-93 -230q-157 64 -272 64q-78 0 -120 -44.5t-42 -127.5v-193h375v-219h-375v-143q0 -170 -151 -248h718v-260h-1048z" />
+<glyph unicode="&#xa5;" d="M6 1462h316l262 -602l264 602h313l-383 -747h195v-178h-246v-138h246v-178h-246v-221h-287v221h-247v178h247v138h-247v178h190z" />
+<glyph unicode="&#xa9;" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM242 731q0 -164 82 -305.5t224 -223t304 -81.5q164 0 305.5 82t223 224t81.5 304q0 164 -82 305.5t-224 223 t-304 81.5q-164 0 -305.5 -82t-223 -224t-81.5 -304zM461 733q0 220 110.5 342.5t309.5 122.5q149 0 305 -78l-74 -168q-113 58 -217 58q-97 0 -150 -74t-53 -205q0 -280 203 -280q57 0 123 15t123 44v-191q-120 -57 -252 -57q-204 0 -316 125t-112 346z" />
+<glyph unicode="&#xad;" horiz-adv-x="659" d="M61 424v250h537v-250h-537z" />
+<glyph unicode="&#xae;" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM242 731q0 -164 82 -305.5t224 -223t304 -81.5q164 0 305.5 82t223 224t81.5 304q0 164 -82 305.5t-224 223 t-304 81.5q-164 0 -305.5 -82t-223 -224t-81.5 -304zM543 272v916h264q181 0 265.5 -70t84.5 -213q0 -170 -143 -233l237 -400h-254l-178 338h-47v-338h-229zM772 778h31q66 0 94.5 28.5t28.5 94.5q0 65 -28 92t-97 27h-29v-242z" />
+<glyph unicode="&#xb4;" horiz-adv-x="1243" d="M332 1241v27q172 200 235 301h342v-21q-52 -52 -177.5 -154.5t-196.5 -152.5h-203z" />
+<glyph unicode="&#x2000;" horiz-adv-x="784" />
+<glyph unicode="&#x2001;" horiz-adv-x="1569" />
+<glyph unicode="&#x2002;" horiz-adv-x="784" />
+<glyph unicode="&#x2003;" horiz-adv-x="1569" />
+<glyph unicode="&#x2004;" horiz-adv-x="523" />
+<glyph unicode="&#x2005;" horiz-adv-x="392" />
+<glyph unicode="&#x2006;" horiz-adv-x="261" />
+<glyph unicode="&#x2007;" horiz-adv-x="261" />
+<glyph unicode="&#x2008;" horiz-adv-x="196" />
+<glyph unicode="&#x2009;" horiz-adv-x="313" />
+<glyph unicode="&#x200a;" horiz-adv-x="87" />
+<glyph unicode="&#x2010;" horiz-adv-x="659" d="M61 424v250h537v-250h-537z" />
+<glyph unicode="&#x2011;" horiz-adv-x="659" d="M61 424v250h537v-250h-537z" />
+<glyph unicode="&#x2012;" horiz-adv-x="659" d="M61 424v250h537v-250h-537z" />
+<glyph unicode="&#x2013;" horiz-adv-x="1024" d="M82 436v230h860v-230h-860z" />
+<glyph unicode="&#x2014;" horiz-adv-x="2048" d="M82 436v230h1884v-230h-1884z" />
+<glyph unicode="&#x2018;" horiz-adv-x="444" d="M25 983q22 91 72.5 228.5t103.5 250.5h219q-66 -267 -101 -501h-280z" />
+<glyph unicode="&#x2019;" horiz-adv-x="444" d="M25 961q69 296 100 501h281l14 -22q-50 -197 -176 -479h-219z" />
+<glyph unicode="&#x201c;" horiz-adv-x="911" d="M25 983q22 91 72.5 228.5t103.5 250.5h219q-66 -267 -101 -501h-280zM492 983q22 91 72.5 228.5t103.5 250.5h219q-66 -267 -101 -501h-280z" />
+<glyph unicode="&#x201d;" horiz-adv-x="911" d="M25 961q69 296 100 501h281l14 -22q-50 -197 -176 -479h-219zM492 961q69 296 100 501h280l15 -22q-50 -197 -176 -479h-219z" />
+<glyph unicode="&#x2022;" horiz-adv-x="770" d="M98 748q0 154 74 235.5t213 81.5q137 0 212 -82t75 -235q0 -152 -75.5 -235t-211.5 -83q-138 0 -212.5 83t-74.5 235z" />
+<glyph unicode="&#x2026;" horiz-adv-x="1751" d="M117 143q0 84 45 127t131 43q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5zM700 143q0 84 45 127t132 43q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-85 0 -131 44.5t-46 125.5zM1284 143q0 84 45 127t131 43 q83 0 128.5 -44t45.5 -126q0 -79 -46 -124.5t-128 -45.5q-84 0 -130 44.5t-46 125.5z" />
+<glyph unicode="&#x202f;" horiz-adv-x="313" />
+<glyph unicode="&#x205f;" horiz-adv-x="392" />
+<glyph unicode="&#x20ac;" d="M66 481v178h118q-4 23 -4 62l2 53h-116v176h133q37 242 199 382.5t405 140.5q188 0 352 -82l-98 -232q-69 31 -129 48.5t-125 17.5q-122 0 -201 -70.5t-102 -204.5h403v-176h-418l-2 -35v-47l2 -33h355v-178h-338q51 -243 321 -243q143 0 275 57v-256q-116 -59 -293 -59 q-245 0 -403 133t-199 368h-137z" />
+<glyph unicode="&#x2122;" horiz-adv-x="1534" d="M16 1313v149h564v-149h-199v-572h-168v572h-197zM625 741v721h247l160 -510l170 510h240v-721h-168v408l4 121h-6l-174 -529h-142l-165 529h-7l4 -111v-418h-163z" />
+<glyph unicode="&#xe000;" horiz-adv-x="1120" d="M0 1120h1120v-1120h-1120v1120z" />
+</font>
+</defs></svg> \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.ttf b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.ttf
new file mode 100644
index 0000000000..2d94f0629d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.ttf
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.woff b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.woff
new file mode 100644
index 0000000000..cd86852d0a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Bold.woff
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.eot b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.eot
new file mode 100644
index 0000000000..277c1899cd
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.eot
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.svg b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.svg
new file mode 100644
index 0000000000..29c7497fed
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.svg
@@ -0,0 +1,146 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG webfont generated by Font Squirrel.
+Copyright : Digitized data copyright 20102011 Google Corporation
+Foundry : Ascender Corporation
+Foundry URL : httpwwwascendercorpcom
+</metadata>
+<defs>
+<font id="OpenSansItalic" horiz-adv-x="1128" >
+<font-face units-per-em="2048" ascent="1638" descent="-410" />
+<missing-glyph horiz-adv-x="532" />
+<glyph unicode=" " horiz-adv-x="532" />
+<glyph unicode="&#x09;" horiz-adv-x="532" />
+<glyph unicode="&#xa0;" horiz-adv-x="532" />
+<glyph unicode="!" horiz-adv-x="530" d="M43 78q0 76 39.5 120t107.5 44q45 0 73 -27.5t28 -81.5q0 -68 -39 -115t-105 -47q-49 0 -76.5 28t-27.5 79zM172 403q49 307 176 1059h207l-274 -1059h-109z" />
+<glyph unicode="&#x22;" horiz-adv-x="791" d="M225 934l72 528h188l-153 -528h-107zM573 934l72 528h189l-154 -528h-107z" />
+<glyph unicode="#" horiz-adv-x="1323" d="M63 430l13 129h284l101 340h-277l13 127h301l123 436h139l-125 -436h305l127 436h133l-125 -436h264l-12 -127h-291l-98 -340h285l-13 -129h-309l-125 -430h-139l129 430h-303l-127 -430h-133l121 430h-261zM500 559h303l96 340h-303z" />
+<glyph unicode="$" d="M72 176v154q82 -41 175.5 -63.5t166.5 -22.5l98 452q-139 49 -201.5 123.5t-62.5 188.5q0 159 108 255t299 113l39 176h133l-39 -178q159 -12 283 -76l-63 -135q-121 63 -248 72l-94 -440q149 -55 212.5 -125t63.5 -178q0 -162 -112.5 -263t-309.5 -123l-49 -225h-133 l49 223q-195 14 -315 72zM401 1010q0 -53 34.5 -97.5t107.5 -70.5l84 393q-108 -11 -167 -69t-59 -156zM549 250q107 13 170 75t63 154q0 54 -33 96t-114 74z" />
+<glyph unicode="%" horiz-adv-x="1624" d="M168 860q0 166 50.5 318.5t136.5 228.5t200 76q116 0 176 -72t60 -205q0 -108 -32 -237.5t-82.5 -217.5t-120.5 -137t-157 -49q-109 0 -170 75t-61 220zM231 0l1086 1462h151l-1085 -1462h-152zM307 864q0 -172 107 -172q52 0 94 39.5t73.5 114t50.5 175t19 171.5 q0 166 -108 166q-66 0 -119 -63t-85 -187.5t-32 -243.5zM909 274q0 166 50.5 318.5t136.5 228.5t200 76q116 0 176 -71.5t60 -204.5q0 -107 -31.5 -236t-82 -217.5t-121 -138t-156.5 -49.5q-110 0 -171 74.5t-61 219.5zM1049 279q0 -173 106 -173q65 0 117 65t86.5 198.5 t34.5 236.5q0 166 -109 166q-67 0 -119.5 -64.5t-84 -188.5t-31.5 -240z" />
+<glyph unicode="&#x26;" horiz-adv-x="1372" d="M66 342q0 148 90 257.5t303 211.5q-103 165 -103 309q0 164 106 264.5t281 100.5q149 0 236.5 -79t87.5 -212q0 -78 -32.5 -137t-87.5 -108t-127.5 -90t-153.5 -83l278 -389q127 110 199 295h168q-101 -236 -283 -412l203 -270h-201l-117 166q-120 -100 -230 -143 t-247 -43q-168 0 -269 96t-101 266zM229 354q0 -106 66.5 -170.5t175.5 -64.5q87 0 168 33t195 124l-306 433q-128 -67 -184 -116t-85.5 -107.5t-29.5 -131.5zM516 1118q0 -120 82 -235q139 71 191 110t83 85t31 104q0 77 -42.5 121.5t-123.5 44.5q-105 0 -163 -60t-58 -170 z" />
+<glyph unicode="'" horiz-adv-x="444" d="M225 934l72 528h188l-153 -528h-107z" />
+<glyph unicode="(" horiz-adv-x="584" d="M82 272q0 339 120 627t384 563h157q-246 -270 -371.5 -570t-125.5 -618q0 -339 114 -598h-131q-147 266 -147 596z" />
+<glyph unicode=")" horiz-adv-x="584" d="M-160 -324q496 551 496 1188q0 341 -113 598h131q146 -269 146 -598q0 -341 -121.5 -629.5t-382.5 -558.5h-156z" />
+<glyph unicode="*" horiz-adv-x="1130" d="M215 1194l55 154l371 -185l41 400l172 -35l-123 -383l422 18l-8 -157l-393 47l180 -383l-166 -52l-113 406l-258 -344l-116 121l309 284z" />
+<glyph unicode="+" d="M127 651v142h389v391h141v-391h390v-142h-390v-387h-141v387h-389z" />
+<glyph unicode="," horiz-adv-x="492" d="M-100 -264q126 286 204 502h187l8 -23q-113 -235 -270 -479h-129z" />
+<glyph unicode="-" horiz-adv-x="639" d="M55 469l35 158h479l-34 -158h-480z" />
+<glyph unicode="." horiz-adv-x="518" d="M43 74q0 77 40.5 122.5t111.5 45.5q43 0 69.5 -26t26.5 -79q0 -71 -40 -118.5t-108 -47.5q-46 0 -73 26t-27 77z" />
+<glyph unicode="/" horiz-adv-x="717" d="M-94 0l813 1462h174l-813 -1462h-174z" />
+<glyph unicode="0" d="M121 477q0 270 82 514.5t216.5 369t307.5 124.5q365 0 365 -471q0 -295 -78.5 -539t-214 -369.5t-314.5 -125.5q-176 0 -270 127.5t-94 369.5zM293 479q0 -172 50 -264t161 -92q115 0 209 114t150.5 328t56.5 453q0 323 -203 323q-113 0 -209 -115.5t-155.5 -323 t-59.5 -423.5z" />
+<glyph unicode="1" d="M303 1178l449 284h149l-313 -1462h-172l196 913q59 261 88 359q-50 -53 -139 -111l-178 -110z" />
+<glyph unicode="2" d="M12 0l31 147l465 420q102 93 176.5 163.5t123 133t72 124t23.5 136.5q0 99 -60 157t-163 58q-77 0 -150.5 -28.5t-162.5 -96.5l-82 115q191 154 413 154q176 0 278.5 -88.5t102.5 -243.5q0 -111 -39.5 -204t-131 -197t-294.5 -281l-352 -307v-8h678l-29 -154h-899z" />
+<glyph unicode="3" d="M47 59v164q94 -49 199 -75.5t190 -26.5q162 0 252 79.5t90 217.5q0 131 -79 198.5t-220 67.5h-131l31 143h139q165 0 274 87t109 227q0 92 -58 146t-157 54q-80 0 -157 -27t-175 -93l-80 118q195 144 424 144q179 0 277 -87t98 -237q0 -156 -101 -264.5t-280 -140.5v-9 q124 -23 195 -106.5t71 -208.5q0 -133 -62 -234.5t-181 -158.5t-283 -57q-210 0 -385 79z" />
+<glyph unicode="4" d="M16 334l29 158l834 978h196l-207 -983h232l-33 -153h-233l-72 -334h-164l74 334h-656zM219 487h486q46 220 78 373t116 445h-8q-17 -29 -66.5 -96.5t-72.5 -96.5z" />
+<glyph unicode="5" d="M80 59v164q164 -102 334 -102q191 0 298 96t107 268q0 126 -73.5 199.5t-204.5 73.5q-48 0 -97 -6.5t-139 -30.5l-74 57l197 684h668l-33 -153h-522l-127 -439q87 23 184 23q182 0 289.5 -104.5t107.5 -282.5q0 -161 -73 -283t-204 -182.5t-308 -60.5q-193 0 -330 79z " />
+<glyph unicode="6" d="M133 424q0 209 60.5 415t163.5 351.5t246 219t327 73.5q111 0 184 -23l-35 -145q-68 22 -170 22q-212 0 -356.5 -149t-212.5 -443h8q59 79 146.5 126t193.5 47q154 0 244 -98.5t90 -270.5q0 -161 -66.5 -294.5t-180.5 -204t-261 -70.5q-182 0 -281.5 115t-99.5 329z M299 416q0 -137 60.5 -216t172.5 -79q94 0 167.5 54t114 149t40.5 208q0 248 -221 248q-66 0 -128 -28.5t-110 -76t-72 -104.5t-24 -155z" />
+<glyph unicode="7" d="M174 0l768 1313h-719l31 149h891l-27 -139l-764 -1323h-180z" />
+<glyph unicode="8" d="M96 346q0 148 95 256t296 184q-95 69 -135.5 144.5t-40.5 171.5q0 111 54.5 198.5t153.5 136t222 48.5q174 0 271.5 -86.5t97.5 -235.5q0 -129 -78 -225t-266 -176q127 -78 180 -165t53 -202q0 -122 -60 -217.5t-172.5 -146.5t-264.5 -51q-190 0 -298 98.5t-108 267.5z M270 354q0 -107 69 -170t181 -63q139 0 222 74t83 196q0 99 -52 174t-165 135q-185 -60 -261.5 -143.5t-76.5 -202.5zM479 1100q0 -82 39 -144t127 -116q161 60 228 131.5t67 173.5q0 90 -57.5 143t-153.5 53q-114 0 -182 -65.5t-68 -175.5z" />
+<glyph unicode="9" d="M98 14v158q134 -47 246 -47q202 0 327 141t189 441h-10q-51 -75 -132.5 -118.5t-180.5 -43.5q-169 0 -261 98.5t-92 288.5q0 153 64.5 280.5t180 199t259.5 71.5q180 0 279.5 -114.5t99.5 -334.5q0 -194 -56 -406.5t-147.5 -360t-221.5 -217.5t-302 -70q-136 0 -242 34z M350 938q0 -124 54.5 -190t162.5 -66q76 0 140 28.5t108.5 81.5t65 114t20.5 151q0 131 -59 207.5t-160 76.5q-150 0 -241 -113t-91 -290z" />
+<glyph unicode=":" horiz-adv-x="518" d="M43 74q0 77 40.5 122.5t111.5 45.5q43 0 69.5 -26t26.5 -79q0 -71 -40 -118.5t-108 -47.5q-46 0 -73 26t-27 77zM203 956q0 77 40 122.5t111 45.5q97 0 97 -104q0 -73 -41.5 -119.5t-106.5 -46.5q-46 0 -73 26.5t-27 75.5z" />
+<glyph unicode=";" horiz-adv-x="518" d="M-100 -264q126 286 204 502h187l8 -23q-113 -235 -270 -479h-129zM203 956q0 77 40 122.5t111 45.5q97 0 97 -104q0 -73 -41.5 -119.5t-106.5 -46.5q-46 0 -73 26.5t-27 75.5z" />
+<glyph unicode="&#x3c;" d="M121 664v98l919 479v-149l-747 -371l747 -328v-151z" />
+<glyph unicode="=" d="M127 444v142h920v-142h-920zM127 858v139h920v-139h-920z" />
+<glyph unicode="&#x3e;" d="M121 242v151l745 328l-745 371v149l919 -479v-98z" />
+<glyph unicode="?" horiz-adv-x="874" d="M158 74q0 77 40 122.5t111 45.5q44 0 70.5 -26t26.5 -79q0 -73 -41.5 -119.5t-106.5 -46.5q-46 0 -73 26t-27 77zM197 1382q92 51 192 76t182 25q167 0 259 -84t92 -238q0 -123 -65.5 -226.5t-225.5 -223.5q-125 -91 -169 -147.5t-67 -160.5h-135q22 130 72.5 213.5 t165.5 174.5q128 100 168 144t63 94t23 112q0 93 -51.5 143.5t-147.5 50.5q-81 0 -155 -25.5t-140 -56.5z" />
+<glyph unicode="@" horiz-adv-x="1735" d="M111 504q0 261 126.5 485.5t343.5 347.5t486 123q191 0 329 -75.5t210.5 -213.5t72.5 -319q0 -179 -55 -324t-155 -227t-222 -82q-197 0 -213 184h-8q-111 -184 -291 -184q-115 0 -180.5 75.5t-65.5 209.5q0 157 68 284t188.5 199t260.5 72q65 0 127.5 -12t150.5 -48 q-64 -242 -98 -368t-31 -172q0 -117 102 -117q78 0 141.5 67t100.5 183.5t37 243.5q0 239 -128 367t-370 128q-228 0 -406.5 -107t-277 -295.5t-98.5 -416.5q0 -270 143.5 -418.5t409.5 -148.5q197 0 420 86v-127q-219 -90 -443 -90q-314 0 -494.5 184.5t-180.5 505.5z M639 518q0 -93 33 -134.5t98 -41.5q187 0 272 315l70 258q-63 23 -127 23q-94 0 -174 -55t-126 -153t-46 -212z" />
+<glyph unicode="A" horiz-adv-x="1137" d="M-117 0l799 1462h174l184 -1462h-170l-57 465h-496l-245 -465h-189zM401 621h394l-35 299q-24 179 -29 350q-37 -88 -80.5 -175t-249.5 -474z" />
+<glyph unicode="B" horiz-adv-x="1225" d="M86 0l309 1462h375q432 0 432 -336q0 -141 -87 -238t-245 -126v-10q115 -32 176.5 -110.5t61.5 -188.5q0 -212 -152 -332.5t-407 -120.5h-463zM287 145h266q181 0 278 80.5t97 227.5q0 116 -74.5 177.5t-214.5 61.5h-236zM434 836h248q156 0 249 73t93 199 q0 104 -66.5 155.5t-209.5 51.5h-211z" />
+<glyph unicode="C" horiz-adv-x="1198" d="M150 537q0 261 105.5 485.5t283.5 342.5t403 118q197 0 348 -80l-69 -141q-138 69 -279 69q-174 0 -311.5 -97t-218 -284.5t-80.5 -408.5q0 -187 97.5 -298.5t268.5 -111.5q139 0 322 57v-149q-86 -31 -164 -45t-188 -14q-242 0 -380 149.5t-138 407.5z" />
+<glyph unicode="D" horiz-adv-x="1364" d="M86 0l309 1462h342q276 0 419.5 -149.5t143.5 -435.5q0 -261 -105 -461t-300 -308t-457 -108h-352zM287 147h162q202 0 355 91.5t234.5 258.5t81.5 382t-103 325.5t-302 110.5h-178z" />
+<glyph unicode="E" horiz-adv-x="1047" d="M86 0l309 1462h735l-32 -153h-566l-98 -469h527l-29 -152h-529l-114 -536h565l-33 -152h-735z" />
+<glyph unicode="F" horiz-adv-x="967" d="M86 0l309 1462h735l-30 -153h-568l-110 -533h528l-32 -153h-529l-131 -623h-172z" />
+<glyph unicode="G" horiz-adv-x="1386" d="M150 528q0 269 101.5 489.5t281.5 343t399 122.5q117 0 219.5 -20t206.5 -64l-66 -152q-77 34 -165.5 59t-194.5 25q-169 0 -307.5 -101.5t-215.5 -283.5t-77 -407q0 -190 102.5 -299t286.5 -109q154 0 260 39l96 444h-289l33 152h459l-154 -711q-216 -75 -419 -75 q-264 0 -410.5 144.5t-146.5 403.5z" />
+<glyph unicode="H" horiz-adv-x="1389" d="M86 0l309 1462h170l-131 -622h660l133 622h168l-310 -1462h-167l143 688h-660l-145 -688h-170z" />
+<glyph unicode="I" horiz-adv-x="559" d="M86 0l311 1462h168l-311 -1462h-168z" />
+<glyph unicode="J" horiz-adv-x="547" d="M-319 -360l6 147q69 -20 145 -20q100 0 165.5 62.5t90.5 182.5l307 1450h170l-309 -1468q-79 -379 -422 -379q-105 0 -153 25z" />
+<glyph unicode="K" horiz-adv-x="1141" d="M86 0l309 1462h170l-151 -710l700 710h209l-639 -637l350 -825h-186q-72 181 -146.5 359.5t-146.5 361.5l-174 -131l-125 -590h-170z" />
+<glyph unicode="L" horiz-adv-x="971" d="M86 0l309 1462h170l-276 -1308h565l-33 -154h-735z" />
+<glyph unicode="M" horiz-adv-x="1714" d="M84 0l309 1462h244l149 -1204h9l659 1204h266l-303 -1462h-174q126 590 193 905.5t94 392.5h-6l-717 -1298h-131l-166 1296h-8q-7 -72 -28.5 -197.5t-37.5 -199.5l-190 -899h-162z" />
+<glyph unicode="N" horiz-adv-x="1438" d="M84 0l309 1462h180l459 -1220h6q30 224 72 405l174 815h164l-309 -1462h-181l-460 1223h-6q-32 -221 -74 -418l-172 -805h-162z" />
+<glyph unicode="O" horiz-adv-x="1475" d="M150 549q0 264 96 482t263.5 336t377.5 118q244 0 384 -154t140 -424q0 -269 -88 -481.5t-252 -329t-379 -116.5q-256 0 -399 149.5t-143 419.5zM332 553q0 -199 98 -310.5t266 -111.5q152 0 272.5 97.5t190.5 279.5t70 403q0 199 -94 310.5t-261 111.5q-157 0 -281 -101 t-192.5 -281t-68.5 -398z" />
+<glyph unicode="P" horiz-adv-x="1159" d="M86 0l309 1462h330q214 0 324 -94.5t110 -282.5q0 -248 -164 -379t-481 -131h-135l-123 -575h-170zM410 721h133q216 0 328 91t112 267q0 125 -69.5 180.5t-213.5 55.5h-163z" />
+<glyph unicode="Q" horiz-adv-x="1475" d="M150 549q0 264 96 482t263.5 336t377.5 118q244 0 384 -154t140 -424q0 -333 -139 -576t-375 -321l274 -358h-219l-227 330l-17 -2h-16q-256 0 -399 149.5t-143 419.5zM332 553q0 -199 98 -310.5t266 -111.5q158 0 279 100t187.5 280.5t66.5 399.5q0 199 -94 310.5 t-261 111.5q-157 0 -281 -101t-192.5 -281t-68.5 -398z" />
+<glyph unicode="R" horiz-adv-x="1165" d="M86 0l309 1462h320q446 0 446 -366q0 -348 -368 -449l239 -647h-186l-209 608h-252l-129 -608h-170zM416 754h168q193 0 297 85t104 244q0 121 -67.5 175.5t-219.5 54.5h-166q-102 -494 -116 -559z" />
+<glyph unicode="S" horiz-adv-x="1028" d="M39 43v170q162 -84 340 -84q162 0 257 75.5t95 207.5q0 78 -52.5 137.5t-195.5 140.5q-151 85 -209.5 170t-58.5 201q0 187 132 304.5t347 117.5q99 0 184.5 -19t180.5 -65l-66 -150q-66 38 -148 60t-151 22q-134 0 -215.5 -69.5t-81.5 -188.5q0 -54 17 -92.5t54 -72.5 t142 -95q147 -88 198.5 -138t78 -110.5t26.5 -140.5q0 -211 -140.5 -327.5t-395.5 -116.5q-106 0 -186.5 14.5t-151.5 48.5z" />
+<glyph unicode="T" horiz-adv-x="1020" d="M186 1311l33 151h985l-30 -151h-408l-279 -1311h-172l277 1311h-406z" />
+<glyph unicode="U" horiz-adv-x="1384" d="M164 383q0 81 24 201l189 878h170l-191 -891q-22 -106 -22 -188q0 -117 73 -184.5t218 -67.5q172 0 267.5 87.5t139.5 289.5l205 954h170l-205 -966q-55 -263 -197.5 -389.5t-388.5 -126.5q-230 0 -341 104t-111 299z" />
+<glyph unicode="V" horiz-adv-x="1122" d="M188 1462h170l97 -930q20 -196 20 -335h4q61 144 162 338l479 927h191l-781 -1462h-180z" />
+<glyph unicode="W" horiz-adv-x="1745" d="M223 1462h170l31 -901l2 -88q0 -98 -10 -258h6q89 243 156 383l405 864h178l43 -860q9 -153 9 -304l-1 -83h9q75 224 131 354l387 893h182l-664 -1462h-170l-49 965q-8 136 -8 282h-6q-25 -72 -61 -154.5t-504 -1092.5h-174z" />
+<glyph unicode="X" horiz-adv-x="1063" d="M-104 0l596 776l-263 686h172l203 -563l443 563h186l-555 -694l278 -768h-180l-213 641l-481 -641h-186z" />
+<glyph unicode="Y" horiz-adv-x="1030" d="M188 1462h170l179 -747l489 747h193l-627 -921l-113 -541h-172l119 549z" />
+<glyph unicode="Z" horiz-adv-x="1087" d="M-16 0l28 137l924 1170h-655l32 155h858l-26 -139l-924 -1169h697l-33 -154h-901z" />
+<glyph unicode="[" horiz-adv-x="586" d="M-16 -324l381 1786h387l-31 -141h-227l-318 -1503h227l-32 -142h-387z" />
+<glyph unicode="\" horiz-adv-x="717" d="M221 1462h154l217 -1462h-154z" />
+<glyph unicode="]" horiz-adv-x="586" d="M-150 -324l31 142h225l320 1503h-227l30 141h389l-380 -1786h-388z" />
+<glyph unicode="^" horiz-adv-x="1059" d="M53 553l598 920h109l266 -920h-145l-201 747l-467 -747h-160z" />
+<glyph unicode="_" horiz-adv-x="807" d="M-188 -324l30 140h811l-30 -140h-811z" />
+<glyph unicode="`" horiz-adv-x="1135" d="M575 1548v21h181q43 -136 147 -303v-25h-104q-61 61 -128.5 154t-95.5 153z" />
+<glyph unicode="a" horiz-adv-x="1157" d="M98 350q0 208 71 386t196 279t274 101q92 0 164 -49.5t112 -142.5h11l67 172h127l-233 -1096h-133l26 209h-8q-179 -229 -377 -229q-139 0 -218 99t-79 271zM270 346q0 -114 47 -170.5t132 -56.5q97 0 193 92.5t156 241t60 297.5q0 103 -56 164t-147 61 q-104 0 -193.5 -86t-140.5 -233t-51 -310z" />
+<glyph unicode="b" horiz-adv-x="1182" d="M59 0l330 1556h168q-51 -242 -78.5 -370.5t-75.5 -300.5h9q93 118 183.5 173.5t186.5 55.5q141 0 220 -99t79 -272q0 -209 -68.5 -386.5t-191 -277t-276.5 -99.5q-97 0 -170.5 51t-110.5 139h-10l-70 -170h-125zM319 346q0 -110 55.5 -168.5t160.5 -58.5q99 0 184.5 81 t137.5 230.5t52 317.5q0 227 -178 227q-96 0 -195.5 -95t-158 -239t-58.5 -295z" />
+<glyph unicode="c" horiz-adv-x="922" d="M98 389q0 200 74 369t204.5 263.5t293.5 94.5q137 0 268 -51l-47 -141q-120 51 -219 51q-112 0 -204.5 -76.5t-145 -213t-52.5 -296.5q0 -128 66.5 -199t183.5 -71q72 0 136 20t126 47v-143q-124 -63 -276 -63q-194 0 -301 107t-107 302z" />
+<glyph unicode="d" horiz-adv-x="1182" d="M98 350q0 214 72 392t194.5 275t274.5 97q194 0 281 -190h10q17 155 45 274l78 358h166l-330 -1556h-139l22 209h-8q-101 -125 -189 -177t-182 -52q-139 0 -217 98t-78 272zM270 346q0 -227 179 -227q94 0 194 93.5t158.5 239t58.5 296.5q0 111 -54 169t-157 58 q-101 0 -187.5 -82.5t-139 -232t-52.5 -314.5z" />
+<glyph unicode="e" horiz-adv-x="1010" d="M98 391q0 188 74.5 360.5t197.5 268.5t271 96q153 0 230 -66.5t77 -185.5q0 -180 -166 -282.5t-475 -102.5h-33l-4 -80q0 -131 61.5 -204.5t190.5 -73.5q63 0 129.5 18t165.5 66v-146q-94 -44 -166 -61.5t-159 -17.5q-184 0 -289 109t-105 302zM299 618h12 q228 0 349.5 59.5t121.5 172.5q0 53 -36.5 88t-114.5 35q-103 0 -193.5 -94t-138.5 -261z" />
+<glyph unicode="f" horiz-adv-x="641" d="M-229 -330q64 -22 112 -22q76 0 117 62t66 177l227 1082h-193l13 67l206 66l23 100q46 200 127.5 282.5t241.5 82.5q40 0 98 -11.5t90 -25.5l-43 -129q-76 29 -137 29q-87 0 -133.5 -48.5t-75.5 -177.5l-25 -108h238l-25 -127h-237l-232 -1098q-39 -189 -120 -276 t-213 -87q-69 0 -125 21v141z" />
+<glyph unicode="g" horiz-adv-x="1026" d="M-127 -211q0 105 72 182t233 131q-78 41 -78 121q0 69 51 118.5t142 92.5q-63 32 -103 94.5t-40 145.5q0 194 119.5 318t305.5 124q78 0 154 -20h371l-25 -107l-211 -24q41 -62 41 -158q0 -191 -116.5 -304.5t-311.5 -113.5q-55 0 -84 8q-139 -53 -139 -131 q0 -41 33 -54.5t96 -21.5l117 -14q181 -22 262.5 -88t81.5 -194q0 -184 -146 -285t-411 -101q-194 0 -304 73.5t-110 207.5zM35 -195q0 -77 65 -122t193 -45q182 0 284.5 63.5t102.5 179.5q0 62 -54 98t-184 50l-159 16q-120 -25 -184 -88t-64 -152zM313 680 q0 -85 45 -129.5t125 -44.5q79 0 138 42t90.5 115.5t31.5 159.5q0 82 -44 125t-126 43q-78 0 -136.5 -40.5t-91 -113t-32.5 -157.5z" />
+<glyph unicode="h" horiz-adv-x="1182" d="M59 0l330 1556h168q-18 -82 -34.5 -159t-34 -156.5t-38 -166.5t-47.5 -189h11q94 123 185.5 176t191.5 53q131 0 202.5 -72t71.5 -204q0 -62 -23 -166q-39 -193 -145 -672h-168l148 692q18 94 18 135q0 148 -147 148q-89 0 -173.5 -59t-149 -171.5t-97.5 -271.5 l-101 -473h-168z" />
+<glyph unicode="i" horiz-adv-x="520" d="M59 0l234 1096h168l-234 -1096h-168zM340 1376q0 56 32 91.5t83 35.5q88 0 88 -90q0 -55 -33.5 -93t-77.5 -38q-40 0 -66 24.5t-26 69.5z" />
+<glyph unicode="j" horiz-adv-x="520" d="M-258 -330q61 -22 119 -22q125 0 168 205l264 1243h166l-266 -1258q-36 -171 -114.5 -250.5t-213.5 -79.5q-69 0 -123 21v141zM340 1376q0 56 32 91.5t83 35.5q86 0 86 -90q0 -55 -33.5 -93t-77.5 -38q-38 0 -64 24.5t-26 69.5z" />
+<glyph unicode="k" horiz-adv-x="999" d="M57 0l330 1556h170l-129 -602q-57 -266 -102 -395h4l526 537h201l-469 -467l295 -629h-187l-235 524l-152 -123l-82 -401h-170z" />
+<glyph unicode="l" horiz-adv-x="520" d="M57 0l332 1556h168l-332 -1556h-168z" />
+<glyph unicode="m" horiz-adv-x="1786" d="M59 0l234 1096h139l-22 -203h10q87 119 173.5 171t178.5 52q113 0 174 -65t72 -181h8q86 125 183 185.5t196 60.5q127 0 196.5 -68t69.5 -198q0 -68 -22 -178l-144 -672h-170l148 692q20 104 20 146q0 62 -34.5 99.5t-108.5 37.5q-81 0 -160 -58t-138.5 -164.5 t-90.5 -252.5l-107 -500h-168l148 692q18 94 18 135q0 70 -31 109t-106 39q-84 0 -163.5 -60t-140 -171.5t-93.5 -268.5l-101 -475h-168z" />
+<glyph unicode="n" horiz-adv-x="1182" d="M59 0l234 1096h139l-22 -203h10q96 122 185.5 172.5t185.5 50.5q127 0 200.5 -69.5t73.5 -194.5q0 -79 -23 -180l-143 -672h-170l148 692q20 104 20 144q0 63 -35.5 101t-113.5 38q-89 0 -173.5 -60t-149 -171t-97.5 -269l-101 -475h-168z" />
+<glyph unicode="o" horiz-adv-x="1149" d="M98 406q0 190 73 357.5t197 257t275 89.5q190 0 300 -112.5t110 -309.5q0 -188 -72 -355t-195 -258t-278 -91q-192 0 -301 113t-109 309zM270 397q0 -131 63.5 -202.5t182.5 -71.5q104 0 187 73t129.5 207.5t46.5 307.5q0 115 -62.5 186.5t-169.5 71.5q-109 0 -195.5 -74 t-134 -205.5t-47.5 -292.5z" />
+<glyph unicode="p" horiz-adv-x="1182" d="M-43 -492l336 1588h139l-26 -209h8q179 227 372 227q137 0 216 -97.5t79 -273.5q0 -212 -69 -389t-191 -275.5t-276 -98.5q-97 0 -170 50t-113 140h-10l-4 -38q-3 -25 -10.5 -70t-114.5 -554h-166zM319 346q0 -110 55.5 -168.5t160.5 -58.5q99 0 184.5 81t137.5 230.5 t52 317.5q0 227 -178 227q-96 0 -195.5 -95t-158 -239t-58.5 -295z" />
+<glyph unicode="q" horiz-adv-x="1182" d="M98 350q0 212 72.5 392t196 277t274.5 97q94 0 165.5 -50.5t108.5 -141.5h13l67 172h125l-336 -1588h-166l101 480q9 45 57 221h-8q-95 -121 -185 -175t-186 -54q-140 0 -219.5 97.5t-79.5 272.5zM270 346q0 -227 179 -227q92 0 190 92t158.5 237t60.5 300 q0 105 -54.5 166t-152.5 61q-101 0 -189 -84.5t-140 -233t-52 -311.5z" />
+<glyph unicode="r" horiz-adv-x="811" d="M59 0l234 1096h139l-22 -203h10q72 95 119 136.5t98.5 64t114.5 22.5q69 0 120 -14l-36 -150q-53 13 -105 13q-91 0 -170.5 -60t-139 -166.5t-87.5 -236.5l-107 -502h-168z" />
+<glyph unicode="s" horiz-adv-x="877" d="M8 49v158q70 -42 151 -65t150 -23q126 0 190 50t64 128q0 57 -35 96t-151 107q-130 73 -184 143t-54 166q0 138 101 222.5t266 84.5q171 0 330 -74l-54 -137l-56 25q-101 43 -220 43q-93 0 -146 -43.5t-53 -112.5q0 -56 35.5 -96t146.5 -103q107 -60 153.5 -103 t69.5 -92.5t23 -111.5q0 -156 -110.5 -243.5t-311.5 -87.5q-169 0 -305 69z" />
+<glyph unicode="t" horiz-adv-x="664" d="M90 969l14 73l185 78l125 228h98l-55 -252h274l-26 -127h-273l-129 -604q-18 -87 -18 -132q0 -56 29 -86t81 -30q55 0 144 26v-129q-34 -14 -84 -24t-80 -10q-125 0 -191.5 59.5t-66.5 177.5q0 66 18 150l127 602h-172z" />
+<glyph unicode="u" horiz-adv-x="1182" d="M113 248q0 62 22 172l146 676h170l-150 -695q-18 -89 -18 -139q0 -143 147 -143q88 0 173 60t150 172t99 270l100 475h166l-231 -1096h-139l22 203h-12q-98 -125 -187 -174t-184 -49q-128 0 -201 69.5t-73 198.5z" />
+<glyph unicode="v" horiz-adv-x="946" d="M98 1096h168l64 -613q24 -258 24 -362h6q127 275 179 371l325 604h178l-591 -1096h-228z" />
+<glyph unicode="w" horiz-adv-x="1468" d="M117 1096h164l18 -594v-88q0 -147 -8 -269h6q47 124 137 322l295 629h182l37 -594q6 -168 6 -262v-53l-2 -42h6q28 86 83 218.5t323 732.5h178l-506 -1096h-205l-32 602q-4 94 -4 172v156h-9l-50 -118l-83 -189l-291 -623h-202z" />
+<glyph unicode="x" horiz-adv-x="979" d="M-74 0l475 565l-239 531h170l174 -412l330 412h194l-455 -539l252 -557h-168l-192 434l-346 -434h-195z" />
+<glyph unicode="y" horiz-adv-x="946" d="M-197 -336q63 -18 131 -18q82 0 140.5 50.5t113.5 149.5l76 136l-166 1114h168l74 -545q10 -69 19.5 -203.5t9.5 -216.5h6q35 87 87 200t77 156l325 609h178l-696 -1282q-93 -172 -184 -239t-219 -67q-72 0 -140 21v135z" />
+<glyph unicode="z" horiz-adv-x="909" d="M-29 0l23 117l694 854h-479l27 125h657l-29 -140l-680 -831h531l-25 -125h-719z" />
+<glyph unicode="{" horiz-adv-x="715" d="M27 514l32 143q118 0 189.5 43.5t93.5 147.5l68 326q34 160 117.5 224t254.5 64h33l-31 -141q-105 0 -151 -36.5t-66 -123.5l-71 -321q-28 -123 -91 -184t-167 -78v-5q151 -41 151 -213q0 -59 -18 -131l-47 -211q-15 -58 -15 -98q0 -53 36.5 -77.5t119.5 -24.5v-142h-23 q-141 0 -216.5 52.5t-75.5 171.5q0 52 20 141q33 146 51.5 227.5t14.5 102.5q0 143 -209 143z" />
+<glyph unicode="|" d="M541 -496v2052h139v-2052h-139z" />
+<glyph unicode="}" horiz-adv-x="715" d="M-74 -182q115 0 167 36t71 123l72 322q25 117 88 179.5t170 80.5v6q-150 42 -150 211q0 59 18 131l50 213q14 65 14 99q0 53 -40.5 77.5t-139.5 24.5l28 141h11q144 0 220.5 -52.5t76.5 -170.5q0 -48 -21 -141l-49 -219q-16 -68 -16 -111q0 -143 209 -143l-33 -144 q-119 0 -190 -43t-93 -147l-67 -326q-36 -164 -119 -226.5t-264 -62.5h-13v142z" />
+<glyph unicode="~" d="M115 592v151q98 109 243 109q69 0 127 -14.5t144 -51.5q64 -27 112.5 -41t98.5 -14q55 0 119.5 33t115.5 88v-150q-100 -110 -244 -110q-72 0 -135 16.5t-135 48.5q-75 32 -120 44t-93 12q-54 0 -118.5 -34.5t-114.5 -86.5z" />
+<glyph unicode="&#xa2;" d="M225 590q0 185 63.5 344t178.5 258.5t260 120.5l35 170h123l-37 -168q119 -9 217 -49l-47 -142q-109 52 -219 52q-112 0 -204.5 -76.5t-145 -213t-52.5 -296.5q0 -125 66 -198t184 -73q72 0 136 20t126 48v-143q-123 -62 -286 -66l-41 -198h-125l43 215 q-132 34 -203.5 137.5t-71.5 257.5z" />
+<glyph unicode="&#xa3;" d="M-23 0l27 141q205 46 258 289l47 221h-200l26 127h201l76 350q75 353 430 353q184 0 336 -86l-66 -133q-146 79 -278 79q-213 0 -263 -237l-69 -326h370l-26 -127h-371l-47 -219q-22 -98 -66 -166.5t-124 -111.5h725l-33 -154h-953z" />
+<glyph unicode="&#xa5;" d="M127 266l29 133h290l33 160h-291l29 133h225l-202 770h163l179 -747l491 747h187l-533 -770h231l-28 -133h-297l-33 -160h297l-29 -133h-295l-57 -266h-154l56 266h-291z" />
+<glyph unicode="&#xa9;" horiz-adv-x="1704" d="M139 731q0 200 100 375t275 276t377 101q197 0 370 -97t277 -272t104 -383q0 -204 -100.5 -376.5t-273 -273.5t-377.5 -101q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM244 731q0 -173 87 -323.5t237.5 -237t322.5 -86.5q174 0 323 87t236.5 235.5t87.5 324.5 q0 174 -87 323t-235.5 236.5t-324.5 87.5q-174 0 -323 -87t-236.5 -235.5t-87.5 -324.5zM520 733q0 208 110 330.5t300 122.5q130 0 248 -60l-60 -120q-106 53 -190 53q-125 0 -191.5 -87t-66.5 -241q0 -169 65 -249.5t193 -80.5q82 0 211 43v-122q-66 -28 -113 -38 t-104 -10q-192 0 -297 119.5t-105 339.5z" />
+<glyph unicode="&#xad;" horiz-adv-x="639" d="M55 469l35 158h479l-34 -158h-480z" />
+<glyph unicode="&#xae;" horiz-adv-x="1704" d="M139 731q0 200 100 375t275 276t377 101q197 0 370 -97t277 -272t104 -383q0 -204 -100.5 -376.5t-273 -273.5t-377.5 -101q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM244 731q0 -173 87 -323.5t237.5 -237t322.5 -86.5q174 0 323 87t236.5 235.5t87.5 324.5 q0 174 -87 323t-235.5 236.5t-324.5 87.5q-174 0 -323 -87t-236.5 -235.5t-87.5 -324.5zM645 291v880h229q163 0 241.5 -63t78.5 -193q0 -78 -47.5 -141t-132.5 -98l227 -385h-149l-207 352h-113v-352h-127zM772 762h92q195 0 195 149q0 76 -47.5 107t-149.5 31h-90v-287z " />
+<glyph unicode="&#xb4;" horiz-adv-x="1135" d="M532 1241v27q56 60 125.5 151.5t106.5 149.5h190v-21q-38 -49 -140 -151t-177 -156h-105z" />
+<glyph unicode="&#x2000;" horiz-adv-x="784" />
+<glyph unicode="&#x2001;" horiz-adv-x="1569" />
+<glyph unicode="&#x2002;" horiz-adv-x="784" />
+<glyph unicode="&#x2003;" horiz-adv-x="1569" />
+<glyph unicode="&#x2004;" horiz-adv-x="523" />
+<glyph unicode="&#x2005;" horiz-adv-x="392" />
+<glyph unicode="&#x2006;" horiz-adv-x="261" />
+<glyph unicode="&#x2007;" horiz-adv-x="261" />
+<glyph unicode="&#x2008;" horiz-adv-x="196" />
+<glyph unicode="&#x2009;" horiz-adv-x="313" />
+<glyph unicode="&#x200a;" horiz-adv-x="87" />
+<glyph unicode="&#x2010;" horiz-adv-x="639" d="M55 469l35 158h479l-34 -158h-480z" />
+<glyph unicode="&#x2011;" horiz-adv-x="639" d="M55 469l35 158h479l-34 -158h-480z" />
+<glyph unicode="&#x2012;" horiz-adv-x="639" d="M55 469l35 158h479l-34 -158h-480z" />
+<glyph unicode="&#x2013;" horiz-adv-x="983" d="M55 469l35 160h823l-34 -160h-824z" />
+<glyph unicode="&#x2014;" horiz-adv-x="1966" d="M55 469l35 160h1806l-34 -160h-1807z" />
+<glyph unicode="&#x2018;" horiz-adv-x="348" d="M123 983q98 211 270 479h127q-147 -345 -203 -501h-188z" />
+<glyph unicode="&#x2019;" horiz-adv-x="348" d="M125 961q134 298 203 501h188l8 -22q-40 -91 -111 -218.5t-159 -260.5h-129z" />
+<glyph unicode="&#x201c;" horiz-adv-x="719" d="M123 983q98 211 270 479h127q-147 -345 -203 -501h-188zM492 983q80 181 272 479h127q-162 -379 -203 -501h-188z" />
+<glyph unicode="&#x201d;" horiz-adv-x="719" d="M125 961q134 298 203 501h188l8 -22q-40 -91 -111 -218.5t-159 -260.5h-129zM494 961q57 126 115.5 272.5t86.5 228.5h189l10 -22q-94 -206 -274 -479h-127z" />
+<glyph unicode="&#x2022;" horiz-adv-x="774" d="M199 684q0 145 73.5 231t198.5 86q92 0 139 -49t47 -141q0 -141 -74 -230t-202 -89q-89 0 -135.5 49.5t-46.5 142.5z" />
+<glyph unicode="&#x2026;" horiz-adv-x="1563" d="M563 74q0 77 40.5 122.5t111.5 45.5q43 0 69.5 -26t26.5 -79q0 -71 -40 -118.5t-108 -47.5q-46 0 -73 26t-27 77zM1085 74q0 77 40.5 122.5t111.5 45.5q43 0 69.5 -26t26.5 -79q0 -71 -40 -118.5t-108 -47.5q-46 0 -73 26t-27 77zM43 74q0 77 40.5 122.5t111.5 45.5 q43 0 69.5 -26t26.5 -79q0 -71 -40 -118.5t-108 -47.5q-46 0 -73 26t-27 77z" />
+<glyph unicode="&#x202f;" horiz-adv-x="313" />
+<glyph unicode="&#x205f;" horiz-adv-x="392" />
+<glyph unicode="&#x20ac;" d="M63 504l27 131h154q8 80 30 164h-151l27 133h159q97 267 259.5 408t369.5 141q89 0 160 -21.5t141 -70.5l-80 -138q-113 78 -231 78q-140 0 -254 -99t-189 -298h426l-26 -133h-441q-21 -65 -32 -164h381l-29 -131h-361q0 -373 297 -373q123 0 256 55v-147 q-127 -59 -278 -59q-212 0 -328.5 133.5t-116.5 378.5v12h-170z" />
+<glyph unicode="&#x2122;" horiz-adv-x="1534" d="M121 1358v104h516v-104h-199v-617h-121v617h-196zM705 741v721h180l182 -557l193 557h170v-721h-121v430q0 73 4 121h-6l-197 -551h-96l-189 551h-6q4 -52 4 -121v-430h-118z" />
+<glyph unicode="&#xe000;" horiz-adv-x="1095" d="M0 1095h1095v-1095h-1095v1095z" />
+</font>
+</defs></svg> \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.ttf b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.ttf
new file mode 100644
index 0000000000..63f187e984
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.ttf
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.woff b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.woff
new file mode 100644
index 0000000000..469a29bbfb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Italic.woff
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.eot b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.eot
new file mode 100644
index 0000000000..dd6fd2cb3a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.eot
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.svg b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.svg
new file mode 100644
index 0000000000..01038bb1c7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.svg
@@ -0,0 +1,146 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG webfont generated by Font Squirrel.
+Copyright : Digitized data copyright 20102011 Google Corporation
+Foundry : Ascender Corporation
+Foundry URL : httpwwwascendercorpcom
+</metadata>
+<defs>
+<font id="OpenSansRegular" horiz-adv-x="1171" >
+<font-face units-per-em="2048" ascent="1638" descent="-410" />
+<missing-glyph horiz-adv-x="532" />
+<glyph unicode=" " horiz-adv-x="532" />
+<glyph unicode="&#x09;" horiz-adv-x="532" />
+<glyph unicode="&#xa0;" horiz-adv-x="532" />
+<glyph unicode="!" horiz-adv-x="547" d="M152 106q0 136 120 136q58 0 89.5 -35t31.5 -101q0 -64 -32 -99.5t-89 -35.5q-52 0 -86 31.5t-34 103.5zM170 1462h207l-51 -1059h-105z" />
+<glyph unicode="&#x22;" horiz-adv-x="821" d="M133 1462h186l-40 -528h-105zM502 1462h186l-41 -528h-104z" />
+<glyph unicode="#" horiz-adv-x="1323" d="M51 430v129h287l68 340h-277v127h299l82 436h139l-82 -436h305l84 436h134l-84 -436h264v-127h-289l-66 -340h283v-129h-307l-84 -430h-137l84 430h-303l-82 -430h-136l80 430h-262zM475 559h303l66 340h-303z" />
+<glyph unicode="$" d="M131 170v156q83 -37 191.5 -60.5t197.5 -23.5v440q-205 65 -287.5 151t-82.5 222q0 131 101.5 215t268.5 102v182h129v-180q184 -5 355 -74l-52 -131q-149 59 -303 70v-434q157 -50 235 -97.5t115 -109t37 -149.5q0 -136 -102 -224.5t-285 -111.5v-232h-129v223 q-112 0 -217 17.5t-172 48.5zM319 1057q0 -76 45 -122t156 -87v387q-99 -16 -150 -62.5t-51 -115.5zM649 252q217 30 217 184q0 72 -44.5 116.5t-172.5 88.5v-389z" />
+<glyph unicode="%" horiz-adv-x="1686" d="M104 1026q0 227 74.5 342t220.5 115q145 0 223 -119t78 -338q0 -228 -76.5 -344.5t-224.5 -116.5q-140 0 -217.5 119t-77.5 342zM242 1026q0 -170 37 -255t120 -85q164 0 164 340q0 338 -164 338q-83 0 -120 -84t-37 -254zM365 0l811 1462h147l-811 -1462h-147zM985 440 q0 227 74.5 342t220.5 115q142 0 221.5 -117.5t79.5 -339.5q0 -227 -76.5 -343.5t-224.5 -116.5q-142 0 -218.5 119t-76.5 341zM1122 440q0 -171 37 -255.5t121 -84.5t124 83.5t40 256.5q0 171 -40 253.5t-124 82.5t-121 -82.5t-37 -253.5z" />
+<glyph unicode="&#x26;" horiz-adv-x="1495" d="M113 379q0 130 69.5 230t249.5 202q-85 95 -115.5 144t-48.5 102t-18 110q0 150 98 234t273 84q162 0 255 -83.5t93 -232.5q0 -107 -68 -197.5t-225 -183.5l407 -391q56 62 89.5 145.5t56.5 182.5h168q-68 -286 -205 -434l299 -291h-229l-185 178q-118 -106 -240 -152 t-272 -46q-215 0 -333.5 106t-118.5 293zM285 383q0 -117 77.5 -185.5t206.5 -68.5q241 0 400 154l-437 424q-111 -68 -157 -112.5t-68 -95.5t-22 -116zM414 1171q0 -69 36 -131.5t123 -150.5q129 75 179.5 138.5t50.5 146.5q0 77 -51.5 125.5t-137.5 48.5q-89 0 -144.5 -48 t-55.5 -129z" />
+<glyph unicode="'" horiz-adv-x="453" d="M133 1462h186l-40 -528h-105z" />
+<glyph unicode="(" horiz-adv-x="606" d="M82 561q0 265 77.5 496t223.5 405h162q-144 -193 -216.5 -424t-72.5 -475q0 -240 74 -469t213 -418h-160q-147 170 -224 397t-77 488z" />
+<glyph unicode=")" horiz-adv-x="606" d="M61 1462h162q147 -175 224 -406.5t77 -494.5t-77.5 -490t-223.5 -395h-160q139 188 213 417.5t74 469.5q0 244 -72.5 475t-216.5 424z" />
+<glyph unicode="*" horiz-adv-x="1130" d="M86 1090l29 182l391 -111l-43 395h194l-43 -395l398 111l26 -182l-381 -31l248 -326l-172 -94l-176 362l-160 -362l-176 94l242 326z" />
+<glyph unicode="+" d="M104 653v138h410v428h139v-428h412v-138h-412v-426h-139v426h-410z" />
+<glyph unicode="," horiz-adv-x="502" d="M63 -264q27 104 59.5 257t45.5 245h182l15 -23q-26 -100 -75 -232.5t-102 -246.5h-125z" />
+<glyph unicode="-" horiz-adv-x="659" d="M84 473v152h491v-152h-491z" />
+<glyph unicode="." horiz-adv-x="545" d="M152 106q0 67 30.5 101.5t87.5 34.5q58 0 90.5 -34.5t32.5 -101.5q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5z" />
+<glyph unicode="/" horiz-adv-x="752" d="M20 0l545 1462h166l-545 -1462h-166z" />
+<glyph unicode="0" d="M102 733q0 382 119 567t363 185q238 0 361.5 -193t123.5 -559q0 -379 -119.5 -566t-365.5 -187q-236 0 -359 191.5t-123 561.5zM270 733q0 -319 75 -464.5t239 -145.5q166 0 240.5 147.5t74.5 462.5t-74.5 461.5t-240.5 146.5q-164 0 -239 -144.5t-75 -463.5z" />
+<glyph unicode="1" d="M188 1163l387 299h140v-1462h-162v1042q0 130 8 246q-21 -21 -47 -44t-238 -195z" />
+<glyph unicode="2" d="M100 0v143l385 387q176 178 232 254t84 148t28 155q0 117 -71 185.5t-197 68.5q-91 0 -172.5 -30t-181.5 -109l-88 113q202 168 440 168q206 0 323 -105.5t117 -283.5q0 -139 -78 -275t-292 -344l-320 -313v-8h752v-154h-961z" />
+<glyph unicode="3" d="M94 59v158q95 -47 202.5 -71.5t203.5 -24.5q379 0 379 297q0 266 -418 266h-144v143h146q171 0 271 75.5t100 209.5q0 107 -73.5 168t-199.5 61q-96 0 -181 -26t-194 -96l-84 112q90 71 207.5 111.5t247.5 40.5q213 0 331 -97.5t118 -267.5q0 -140 -78.5 -229 t-222.5 -119v-8q176 -22 261 -112t85 -236q0 -209 -145 -321.5t-412 -112.5q-116 0 -212.5 17.5t-187.5 61.5z" />
+<glyph unicode="4" d="M43 336v145l694 989h176v-983h217v-151h-217v-336h-159v336h-711zM209 487h545v486q0 143 10 323h-8q-48 -96 -90 -159z" />
+<glyph unicode="5" d="M133 59v160q70 -45 174 -70.5t205 -25.5q176 0 273.5 83t97.5 240q0 306 -375 306q-95 0 -254 -29l-86 55l55 684h727v-153h-585l-37 -439q115 23 229 23q231 0 363.5 -114.5t132.5 -313.5q0 -227 -144.5 -356t-398.5 -129q-247 0 -377 79z" />
+<glyph unicode="6" d="M117 625q0 431 167.5 644.5t495.5 213.5q113 0 178 -19v-143q-77 25 -176 25q-235 0 -359 -146.5t-136 -460.5h12q110 172 348 172q197 0 310.5 -119t113.5 -323q0 -228 -124.5 -358.5t-336.5 -130.5q-227 0 -360 170.5t-133 474.5zM287 506q0 -103 40 -192t113.5 -141 t167.5 -52q142 0 220.5 89.5t78.5 258.5q0 145 -73 228t-218 83q-90 0 -165 -37t-119.5 -102t-44.5 -135z" />
+<glyph unicode="7" d="M94 1309v153h973v-133l-598 -1329h-184l606 1309h-797z" />
+<glyph unicode="8" d="M104 373q0 251 306 391q-138 78 -198 168.5t-60 202.5q0 159 117.5 253.5t314.5 94.5q200 0 317 -93t117 -257q0 -108 -67 -197t-214 -162q178 -85 253 -178.5t75 -216.5q0 -182 -127 -290.5t-348 -108.5q-234 0 -360 102.5t-126 290.5zM268 369q0 -120 83.5 -187 t234.5 -67q149 0 232 70t83 192q0 97 -78 172.5t-272 146.5q-149 -64 -216 -141.5t-67 -185.5zM315 1128q0 -92 59 -158t218 -132q143 60 202.5 129t59.5 161q0 101 -72.5 160.5t-199.5 59.5q-125 0 -196 -60t-71 -160z" />
+<glyph unicode="9" d="M106 991q0 228 127.5 360t335.5 132q149 0 260.5 -76.5t171.5 -223t60 -345.5q0 -858 -664 -858q-116 0 -184 20v143q80 -26 182 -26q240 0 362.5 148.5t133.5 455.5h-12q-55 -83 -146 -126.5t-205 -43.5q-194 0 -308 116t-114 324zM270 993q0 -144 72 -226.5t219 -82.5 q91 0 167.5 37t120.5 101t44 134q0 105 -41 194t-114.5 140t-168.5 51q-143 0 -221 -92t-78 -256z" />
+<glyph unicode=":" horiz-adv-x="545" d="M152 106q0 67 30.5 101.5t87.5 34.5q58 0 90.5 -34.5t32.5 -101.5q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5zM152 989q0 135 118 135q123 0 123 -135q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5z" />
+<glyph unicode=";" horiz-adv-x="545" d="M63 -264q27 104 59.5 257t45.5 245h182l15 -23q-26 -100 -75 -232.5t-102 -246.5h-125zM147 989q0 135 119 135q123 0 123 -135q0 -65 -33 -100t-90 -35q-58 0 -88.5 35t-30.5 100z" />
+<glyph unicode="&#x3c;" d="M104 664v98l961 479v-149l-782 -371l782 -328v-151z" />
+<glyph unicode="=" d="M119 449v137h930v-137h-930zM119 858v137h930v-137h-930z" />
+<glyph unicode="&#x3e;" d="M104 242v151l783 326l-783 373v149l961 -479v-98z" />
+<glyph unicode="?" horiz-adv-x="879" d="M27 1384q189 99 395 99q191 0 297 -94t106 -265q0 -73 -19.5 -128.5t-57.5 -105t-164 -159.5q-101 -86 -133.5 -143t-32.5 -152v-33h-129v54q0 117 36 192.5t134 159.5q136 115 171.5 173t35.5 140q0 102 -65.5 157.5t-188.5 55.5q-79 0 -154 -18.5t-172 -67.5zM240 106 q0 136 120 136q58 0 89.5 -35t31.5 -101q0 -64 -32 -99.5t-89 -35.5q-52 0 -86 31.5t-34 103.5z" />
+<glyph unicode="@" horiz-adv-x="1841" d="M121 571q0 260 107 463t305 314.5t454 111.5q215 0 382.5 -90.5t259 -257t91.5 -383.5q0 -142 -44 -260t-124 -183t-184 -65q-86 0 -145 52t-70 133h-8q-40 -87 -114.5 -136t-176.5 -49q-150 0 -234.5 102.5t-84.5 278.5q0 204 118 331.5t310 127.5q68 0 154 -12.5 t155 -34.5l-25 -470v-22q0 -178 133 -178q91 0 148 107.5t57 279.5q0 181 -74 317t-210.5 209.5t-313.5 73.5q-223 0 -388 -92.5t-252 -264t-87 -396.5q0 -305 161 -469t464 -164q210 0 436 86v-133q-192 -84 -436 -84q-363 0 -563.5 199.5t-200.5 557.5zM686 598 q0 -254 195 -254q207 0 225 313l14 261q-72 20 -157 20q-130 0 -203.5 -90t-73.5 -250z" />
+<glyph unicode="A" horiz-adv-x="1296" d="M0 0l578 1468h143l575 -1468h-176l-182 465h-586l-180 -465h-172zM412 618h473l-170 453q-33 86 -68 211q-22 -96 -63 -211z" />
+<glyph unicode="B" horiz-adv-x="1327" d="M201 0v1462h413q291 0 421 -87t130 -275q0 -130 -72.5 -214.5t-211.5 -109.5v-10q333 -57 333 -350q0 -196 -132.5 -306t-370.5 -110h-510zM371 145h305q177 0 266.5 68.5t89.5 214.5q0 136 -91.5 200t-278.5 64h-291v-547zM371 836h280q180 0 259 56.5t79 190.5 q0 123 -88 177.5t-280 54.5h-250v-479z" />
+<glyph unicode="C" horiz-adv-x="1292" d="M125 733q0 226 84.5 396t244 262t375.5 92q230 0 402 -84l-72 -146q-166 78 -332 78q-241 0 -380.5 -160.5t-139.5 -439.5q0 -287 134.5 -443.5t383.5 -156.5q153 0 349 55v-149q-152 -57 -375 -57q-323 0 -498.5 196t-175.5 557z" />
+<glyph unicode="D" horiz-adv-x="1493" d="M201 0v1462h448q341 0 530 -189t189 -528q0 -362 -196.5 -553.5t-565.5 -191.5h-405zM371 147h207q304 0 457 149.5t153 442.5q0 286 -143.5 431t-426.5 145h-247v-1168z" />
+<glyph unicode="E" horiz-adv-x="1139" d="M201 0v1462h815v-151h-645v-471h606v-150h-606v-538h645v-152h-815z" />
+<glyph unicode="F" horiz-adv-x="1057" d="M201 0v1462h815v-151h-645v-535h606v-151h-606v-625h-170z" />
+<glyph unicode="G" horiz-adv-x="1491" d="M125 731q0 228 91.5 399.5t263.5 262t403 90.5q234 0 436 -86l-66 -150q-198 84 -381 84q-267 0 -417 -159t-150 -441q0 -296 144.5 -449t424.5 -153q152 0 297 35v450h-327v152h497v-711q-116 -37 -236 -56t-278 -19q-332 0 -517 197.5t-185 553.5z" />
+<glyph unicode="H" horiz-adv-x="1511" d="M201 0v1462h170v-622h770v622h170v-1462h-170v688h-770v-688h-170z" />
+<glyph unicode="I" horiz-adv-x="571" d="M201 0v1462h170v-1462h-170z" />
+<glyph unicode="J" horiz-adv-x="547" d="M-160 -213q71 -20 148 -20q99 0 150.5 60t51.5 173v1462h170v-1448q0 -190 -96 -294.5t-276 -104.5q-94 0 -148 27v145z" />
+<glyph unicode="K" horiz-adv-x="1257" d="M201 0v1462h170v-725l663 725h201l-588 -635l610 -827h-200l-533 709l-153 -136v-573h-170z" />
+<glyph unicode="L" horiz-adv-x="1063" d="M201 0v1462h170v-1308h645v-154h-815z" />
+<glyph unicode="M" horiz-adv-x="1849" d="M201 0v1462h256l463 -1206h8l467 1206h254v-1462h-170v942q0 162 14 352h-8l-500 -1294h-137l-496 1296h-8q14 -154 14 -366v-930h-157z" />
+<glyph unicode="N" horiz-adv-x="1544" d="M201 0v1462h192l797 -1222h8q-2 28 -9 174q-5 114 -5 177v32v839h159v-1462h-194l-799 1227h-8q16 -216 16 -396v-831h-157z" />
+<glyph unicode="O" horiz-adv-x="1595" d="M125 735q0 357 176 553.5t500 196.5q315 0 492 -200t177 -552q0 -351 -177.5 -552t-493.5 -201q-323 0 -498.5 197.5t-175.5 557.5zM305 733q0 -297 126.5 -450.5t367.5 -153.5q243 0 367 153t124 451q0 295 -123.5 447.5t-365.5 152.5q-243 0 -369.5 -153.5 t-126.5 -446.5z" />
+<glyph unicode="P" horiz-adv-x="1233" d="M201 0v1462h379q548 0 548 -426q0 -222 -151.5 -341.5t-433.5 -119.5h-172v-575h-170zM371 721h153q226 0 327 73t101 234q0 145 -95 216t-296 71h-190v-594z" />
+<glyph unicode="Q" horiz-adv-x="1595" d="M125 735q0 357 176 553.5t500 196.5q315 0 492 -200t177 -552q0 -281 -113 -467t-319 -252l348 -362h-247l-285 330l-55 -2q-323 0 -498.5 197.5t-175.5 557.5zM305 733q0 -297 126.5 -450.5t367.5 -153.5q243 0 367 153t124 451q0 295 -123.5 447.5t-365.5 152.5 q-243 0 -369.5 -153.5t-126.5 -446.5z" />
+<glyph unicode="R" horiz-adv-x="1266" d="M201 0v1462h401q269 0 397.5 -103t128.5 -310q0 -290 -294 -392l397 -657h-201l-354 608h-305v-608h-170zM371 754h233q180 0 264 71.5t84 214.5q0 145 -85.5 209t-274.5 64h-221v-559z" />
+<glyph unicode="S" horiz-adv-x="1124" d="M106 47v164q90 -38 196 -60t210 -22q170 0 256 64.5t86 179.5q0 76 -30.5 124.5t-102 89.5t-217.5 93q-204 73 -291.5 173t-87.5 261q0 169 127 269t336 100q218 0 401 -80l-53 -148q-181 76 -352 76q-135 0 -211 -58t-76 -161q0 -76 28 -124.5t94.5 -89t203.5 -89.5 q230 -82 316.5 -176t86.5 -244q0 -193 -140 -301t-380 -108q-260 0 -400 67z" />
+<glyph unicode="T" horiz-adv-x="1133" d="M18 1311v151h1096v-151h-463v-1311h-170v1311h-463z" />
+<glyph unicode="U" horiz-adv-x="1491" d="M186 520v942h170v-954q0 -183 100 -281t294 -98q185 0 285 98.5t100 282.5v952h170v-946q0 -250 -151 -393t-415 -143t-408.5 144t-144.5 396z" />
+<glyph unicode="V" horiz-adv-x="1219" d="M0 1462h180l336 -946q58 -163 92 -317q36 162 94 323l334 940h183l-527 -1462h-168z" />
+<glyph unicode="W" horiz-adv-x="1896" d="M27 1462h180l231 -903q48 -190 70 -344q27 183 80 358l262 889h180l275 -897q48 -155 81 -350q19 142 72 346l230 901h180l-391 -1462h-168l-295 979q-21 65 -47 164t-27 119q-22 -132 -70 -289l-286 -973h-168z" />
+<glyph unicode="X" horiz-adv-x="1182" d="M8 0l486 764l-453 698h188l363 -579l366 579h181l-453 -692l488 -770h-193l-393 643l-400 -643h-180z" />
+<glyph unicode="Y" horiz-adv-x="1147" d="M0 1462h186l387 -731l390 731h184l-488 -895v-567h-172v559z" />
+<glyph unicode="Z" horiz-adv-x="1169" d="M82 0v133l776 1176h-752v153h959v-133l-776 -1175h798v-154h-1005z" />
+<glyph unicode="[" horiz-adv-x="674" d="M166 -324v1786h457v-141h-289v-1503h289v-142h-457z" />
+<glyph unicode="\" horiz-adv-x="752" d="M23 1462h163l547 -1462h-166z" />
+<glyph unicode="]" horiz-adv-x="674" d="M51 -182h289v1503h-289v141h457v-1786h-457v142z" />
+<glyph unicode="^" horiz-adv-x="1110" d="M49 551l434 922h99l477 -922h-152l-372 745l-334 -745h-152z" />
+<glyph unicode="_" horiz-adv-x="918" d="M-4 -184h926v-131h-926v131z" />
+<glyph unicode="`" horiz-adv-x="1182" d="M393 1548v21h203q32 -69 89 -159.5t101 -143.5v-25h-110q-65 52 -154 148t-129 159z" />
+<glyph unicode="a" horiz-adv-x="1139" d="M94 303q0 332 531 348l186 6v68q0 129 -55.5 190.5t-177.5 61.5q-137 0 -310 -84l-51 127q81 44 177.5 69t193.5 25q196 0 290.5 -87t94.5 -279v-748h-123l-33 156h-8q-82 -103 -163.5 -139.5t-203.5 -36.5q-163 0 -255.5 84t-92.5 239zM268 301q0 -90 54.5 -137 t152.5 -47q155 0 243.5 85t88.5 238v99l-166 -7q-198 -7 -285.5 -61.5t-87.5 -169.5z" />
+<glyph unicode="b" horiz-adv-x="1255" d="M176 0v1556h166v-378q0 -127 -8 -228h8q116 164 344 164q216 0 335.5 -147.5t119.5 -417.5t-120.5 -419.5t-334.5 -149.5q-107 0 -195.5 39.5t-148.5 121.5h-12l-35 -141h-119zM342 549q0 -231 77 -330.5t247 -99.5q153 0 228 111.5t75 320.5q0 214 -75 319t-232 105 q-170 0 -245 -97.5t-75 -328.5z" />
+<glyph unicode="c" horiz-adv-x="975" d="M115 541q0 275 132.5 425t377.5 150q79 0 158 -17t124 -40l-51 -141q-55 22 -120 36.5t-115 14.5q-334 0 -334 -426q0 -202 81.5 -310t241.5 -108q137 0 281 59v-147q-110 -57 -277 -57q-238 0 -368.5 146.5t-130.5 414.5z" />
+<glyph unicode="d" horiz-adv-x="1255" d="M115 545q0 271 120 421t334 150q223 0 342 -162h13l-7 79l-4 77v446h166v-1556h-135l-22 147h-9q-115 -167 -344 -167q-215 0 -334.5 147t-119.5 418zM287 543q0 -210 77 -317t226 -107q170 0 246.5 92.5t76.5 298.5v35q0 233 -77.5 332.5t-247.5 99.5 q-146 0 -223.5 -113.5t-77.5 -320.5z" />
+<glyph unicode="e" horiz-adv-x="1149" d="M115 539q0 265 130.5 421t350.5 156q206 0 326 -135.5t120 -357.5v-105h-755q5 -193 97.5 -293t260.5 -100q177 0 350 74v-148q-88 -38 -166.5 -54.5t-189.5 -16.5q-243 0 -383.5 148t-140.5 411zM291 653h573q0 157 -70 240.5t-200 83.5q-132 0 -210.5 -86t-92.5 -238z " />
+<glyph unicode="f" horiz-adv-x="694" d="M29 967v75l196 60v61q0 404 353 404q87 0 204 -35l-43 -133q-96 31 -164 31q-94 0 -139 -62.5t-45 -200.5v-71h279v-129h-279v-967h-166v967h-196z" />
+<glyph unicode="g" horiz-adv-x="1122" d="M39 -186q0 100 64 173t180 99q-42 19 -70.5 59t-28.5 93q0 60 32 105t101 87q-85 35 -138.5 119t-53.5 192q0 180 108 277.5t306 97.5q86 0 155 -20h379v-105l-203 -24q28 -35 50 -91.5t22 -127.5q0 -161 -110 -257t-302 -96q-49 0 -92 8q-106 -56 -106 -141 q0 -45 37 -66.5t127 -21.5h194q178 0 273.5 -75t95.5 -218q0 -182 -146 -277.5t-426 -95.5q-215 0 -331.5 80t-116.5 226zM199 -184q0 -89 75 -135t215 -46q209 0 309.5 62.5t100.5 169.5q0 89 -55 123.5t-207 34.5h-199q-113 0 -176 -54t-63 -155zM289 745q0 -115 65 -174 t181 -59q243 0 243 236q0 247 -246 247q-117 0 -180 -63t-63 -187z" />
+<glyph unicode="h" horiz-adv-x="1257" d="M176 0v1556h166v-471q0 -85 -8 -141h10q49 79 139.5 124.5t206.5 45.5q201 0 301.5 -95.5t100.5 -303.5v-715h-166v709q0 134 -61 200t-191 66q-173 0 -252.5 -94t-79.5 -308v-573h-166z" />
+<glyph unicode="i" horiz-adv-x="518" d="M162 1393q0 57 28 83.5t70 26.5q40 0 69 -27t29 -83t-29 -83.5t-69 -27.5q-42 0 -70 27.5t-28 83.5zM176 0v1096h166v-1096h-166z" />
+<glyph unicode="j" horiz-adv-x="518" d="M-111 -332q69 -20 136 -20q78 0 114.5 42.5t36.5 129.5v1276h166v-1264q0 -324 -299 -324q-95 0 -154 25v135zM162 1393q0 57 28 83.5t70 26.5q40 0 69 -27t29 -83t-29 -83.5t-69 -27.5q-42 0 -70 27.5t-28 83.5z" />
+<glyph unicode="k" horiz-adv-x="1075" d="M176 0v1556h164v-825q0 -55 -8 -170h8q43 61 131 160l354 375h197l-444 -467l475 -629h-201l-387 518l-125 -108v-410h-164z" />
+<glyph unicode="l" horiz-adv-x="518" d="M176 0v1556h166v-1556h-166z" />
+<glyph unicode="m" horiz-adv-x="1905" d="M176 0v1096h135l27 -150h8q47 80 132.5 125t191.5 45q257 0 336 -186h8q49 86 142 136t212 50q186 0 278.5 -95.5t92.5 -305.5v-715h-166v713q0 131 -56 196.5t-174 65.5q-155 0 -229 -89t-74 -274v-612h-166v713q0 131 -56 196.5t-175 65.5q-156 0 -228.5 -93.5 t-72.5 -306.5v-575h-166z" />
+<glyph unicode="n" horiz-adv-x="1257" d="M176 0v1096h135l27 -150h8q51 81 143 125.5t205 44.5q198 0 298 -95.5t100 -305.5v-715h-166v709q0 134 -61 200t-191 66q-172 0 -252 -93t-80 -307v-575h-166z" />
+<glyph unicode="o" horiz-adv-x="1237" d="M115 549q0 268 134 417.5t372 149.5q230 0 365.5 -153t135.5 -414q0 -268 -135 -418.5t-373 -150.5q-147 0 -261 69t-176 198t-62 302zM287 549q0 -210 84 -320t247 -110t247.5 109.5t84.5 320.5q0 209 -84.5 317.5t-249.5 108.5q-163 0 -246 -107t-83 -319z" />
+<glyph unicode="p" horiz-adv-x="1255" d="M176 -492v1588h135l23 -150h8q64 90 149 130t195 40q218 0 336.5 -149t118.5 -418q0 -270 -120.5 -419.5t-334.5 -149.5q-107 0 -195.5 39.5t-148.5 121.5h-12q12 -96 12 -182v-451h-166zM342 549q0 -231 77 -330.5t247 -99.5q142 0 222.5 115t80.5 317 q0 205 -80.5 314.5t-226.5 109.5q-168 0 -243 -93t-77 -296v-37z" />
+<glyph unicode="q" horiz-adv-x="1255" d="M115 545q0 269 120 420t334 151q225 0 346 -170h9l24 150h131v-1588h-166v469q0 100 11 170h-13q-115 -167 -346 -167q-212 0 -331 149t-119 416zM287 543q0 -207 76.5 -315.5t226.5 -108.5q166 0 242 89t81 300v37q0 230 -78 331t-247 101q-146 0 -223.5 -113.5 t-77.5 -320.5z" />
+<glyph unicode="r" horiz-adv-x="836" d="M176 0v1096h137l19 -203h8q61 107 147 165t189 58q73 0 131 -12l-23 -154q-68 15 -120 15q-133 0 -227.5 -108t-94.5 -269v-588h-166z" />
+<glyph unicode="s" horiz-adv-x="977" d="M106 827q0 134 109 211.5t299 77.5q177 0 346 -72l-59 -135q-165 68 -299 68q-118 0 -178 -37t-60 -102q0 -44 22.5 -75t72.5 -59t192 -81q195 -71 263.5 -143t68.5 -181q0 -153 -114 -236t-320 -83q-218 0 -340 69v154q79 -40 169.5 -63t174.5 -23q130 0 200 41.5 t70 126.5q0 64 -55.5 109.5t-216.5 107.5q-153 57 -217.5 99.5t-96 96.5t-31.5 129z" />
+<glyph unicode="t" horiz-adv-x="723" d="M31 967v80l157 69l70 234h96v-254h318v-129h-318v-645q0 -99 47 -152t129 -53q44 0 85 6.5t65 13.5v-127q-27 -13 -79.5 -21.5t-94.5 -8.5q-318 0 -318 335v652h-157z" />
+<glyph unicode="u" horiz-adv-x="1257" d="M164 379v717h168v-711q0 -134 61 -200t191 -66q172 0 251.5 94t79.5 307v576h166v-1096h-137l-24 147h-9q-51 -81 -141.5 -124t-206.5 -43q-200 0 -299.5 95t-99.5 304z" />
+<glyph unicode="v" horiz-adv-x="1026" d="M0 1096h178l236 -650q80 -228 94 -296h8q11 53 69.5 219.5t262.5 726.5h178l-416 -1096h-194z" />
+<glyph unicode="w" horiz-adv-x="1593" d="M23 1096h174q106 -413 161.5 -629t63.5 -291h8q11 57 35.5 147.5t42.5 143.5l201 629h180l196 -629q56 -172 76 -289h8q4 36 21.5 111t208.5 807h172l-303 -1096h-197l-201 643q-19 59 -71 268h-8q-40 -175 -70 -270l-207 -641h-192z" />
+<glyph unicode="x" horiz-adv-x="1073" d="M39 0l401 561l-381 535h189l289 -420l288 420h187l-381 -535l401 -561h-188l-307 444l-310 -444h-188z" />
+<glyph unicode="y" horiz-adv-x="1032" d="M2 1096h178l240 -625q79 -214 98 -309h8q13 51 54.5 174.5t271.5 759.5h178l-471 -1248q-70 -185 -163.5 -262.5t-229.5 -77.5q-76 0 -150 17v133q55 -12 123 -12q171 0 244 192l61 156z" />
+<glyph unicode="z" horiz-adv-x="958" d="M82 0v113l598 854h-561v129h743v-129l-590 -838h605v-129h-795z" />
+<glyph unicode="{" horiz-adv-x="776" d="M61 498v141q130 2 188 48t58 142v306q0 155 108 241t290 86v-139q-230 -6 -230 -199v-295q0 -215 -223 -254v-12q223 -39 223 -254v-297q0 -102 58.5 -148t171.5 -48v-140q-190 2 -294 87t-104 239v303q0 104 -63 148.5t-183 44.5z" />
+<glyph unicode="|" horiz-adv-x="1128" d="M494 -496v2052h141v-2052h-141z" />
+<glyph unicode="}" horiz-adv-x="776" d="M72 -184q111 2 169 48t58 148v297q0 114 55 174t168 80v12q-223 39 -223 254v295q0 193 -227 199v139q184 0 289.5 -87t105.5 -240v-306q0 -97 59 -142.5t189 -47.5v-141q-122 0 -185 -44.5t-63 -148.5v-303q0 -153 -102.5 -238.5t-292.5 -87.5v140z" />
+<glyph unicode="~" d="M104 592v151q100 109 244 109q68 0 124.5 -14t145.5 -52q66 -28 115 -41.5t96 -13.5q54 0 118 32t118 89v-150q-102 -110 -244 -110q-72 0 -135 16.5t-135 48.5q-75 32 -120 44t-93 12q-53 0 -116.5 -33.5t-117.5 -87.5z" />
+<glyph unicode="&#xa2;" d="M190 741q0 508 396 570v172h135v-164q75 -3 146 -19.5t120 -39.5l-49 -140q-133 51 -242 51q-172 0 -253 -105.5t-81 -322.5q0 -212 79.5 -313.5t246.5 -101.5q141 0 283 59v-147q-105 -54 -252 -60v-200h-133v206q-203 32 -299.5 168.5t-96.5 386.5z" />
+<glyph unicode="&#xa3;" d="M63 0v141q205 47 205 291v223h-198v127h198v316q0 178 112 280.5t302 102.5t360 -84l-61 -133q-154 77 -297 77q-123 0 -185.5 -62t-62.5 -202v-295h422v-127h-422v-221q0 -100 -32.5 -168t-106.5 -112h795v-154h-1029z" />
+<glyph unicode="&#xa5;" d="M31 1462h178l375 -727l379 727h174l-416 -770h262v-127h-317v-170h317v-127h-317v-268h-164v268h-316v127h316v170h-316v127h256z" />
+<glyph unicode="&#xa9;" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM205 731q0 -173 87 -323.5t237.5 -237t322.5 -86.5q174 0 323 87t236.5 235.5t87.5 324.5q0 174 -87 323 t-235.5 236.5t-324.5 87.5q-174 0 -323 -87t-236.5 -235.5t-87.5 -324.5zM481 731q0 209 110.5 332t301.5 123q128 0 246 -60l-58 -118q-108 51 -188 51q-125 0 -192.5 -87t-67.5 -241q0 -168 63.5 -249t194.5 -81q86 0 211 45v-124q-48 -20 -98.5 -34t-120.5 -14 q-194 0 -298 120.5t-104 336.5z" />
+<glyph unicode="&#xad;" horiz-adv-x="659" d="M84 473v152h491v-152h-491z" />
+<glyph unicode="&#xae;" horiz-adv-x="1704" d="M100 731q0 200 100 375t275 276t377 101q200 0 375 -100t276 -275t101 -377q0 -197 -97 -370t-272 -277t-383 -104q-207 0 -382 103.5t-272.5 276.5t-97.5 371zM205 731q0 -173 87 -323.5t237.5 -237t322.5 -86.5q174 0 323 87t236.5 235.5t87.5 324.5q0 174 -87 323 t-235.5 236.5t-324.5 87.5q-174 0 -323 -87t-236.5 -235.5t-87.5 -324.5zM575 285v891h261q166 0 243.5 -65t77.5 -198q0 -80 -42.5 -141.5t-119.5 -91.5l238 -395h-168l-207 354h-135v-354h-148zM723 762h108q80 0 128.5 41.5t48.5 105.5q0 75 -43 107.5t-136 32.5h-106 v-287z" />
+<glyph unicode="&#xb4;" horiz-adv-x="1182" d="M393 1241v25q48 62 103.5 150t87.5 153h202v-21q-44 -65 -131 -160t-151 -147h-111z" />
+<glyph unicode="&#x2000;" horiz-adv-x="784" />
+<glyph unicode="&#x2001;" horiz-adv-x="1569" />
+<glyph unicode="&#x2002;" horiz-adv-x="784" />
+<glyph unicode="&#x2003;" horiz-adv-x="1569" />
+<glyph unicode="&#x2004;" horiz-adv-x="523" />
+<glyph unicode="&#x2005;" horiz-adv-x="392" />
+<glyph unicode="&#x2006;" horiz-adv-x="261" />
+<glyph unicode="&#x2007;" horiz-adv-x="261" />
+<glyph unicode="&#x2008;" horiz-adv-x="196" />
+<glyph unicode="&#x2009;" horiz-adv-x="313" />
+<glyph unicode="&#x200a;" horiz-adv-x="87" />
+<glyph unicode="&#x2010;" horiz-adv-x="659" d="M84 473v152h491v-152h-491z" />
+<glyph unicode="&#x2011;" horiz-adv-x="659" d="M84 473v152h491v-152h-491z" />
+<glyph unicode="&#x2012;" horiz-adv-x="659" d="M84 473v152h491v-152h-491z" />
+<glyph unicode="&#x2013;" horiz-adv-x="1024" d="M82 473v152h860v-152h-860z" />
+<glyph unicode="&#x2014;" horiz-adv-x="2048" d="M82 473v152h1884v-152h-1884z" />
+<glyph unicode="&#x2018;" horiz-adv-x="348" d="M25 983q22 90 71 224t105 255h123q-66 -254 -103 -501h-184z" />
+<glyph unicode="&#x2019;" horiz-adv-x="348" d="M25 961q70 285 102 501h182l15 -22q-26 -100 -75 -232.5t-102 -246.5h-122z" />
+<glyph unicode="&#x201c;" horiz-adv-x="717" d="M25 983q22 90 71 224t105 255h123q-66 -254 -103 -501h-184zM391 983q56 215 178 479h123q-30 -115 -59.5 -259.5t-42.5 -241.5h-184z" />
+<glyph unicode="&#x201d;" horiz-adv-x="717" d="M25 961q70 285 102 501h182l15 -22q-26 -100 -75 -232.5t-102 -246.5h-122zM391 961q26 100 59 254t46 247h182l14 -22q-24 -91 -72 -224t-104 -255h-125z" />
+<glyph unicode="&#x2022;" horiz-adv-x="770" d="M164 748q0 121 56.5 184t164.5 63q105 0 163 -62t58 -185q0 -119 -57.5 -183.5t-163.5 -64.5q-107 0 -164 65.5t-57 182.5z" />
+<glyph unicode="&#x2026;" horiz-adv-x="1606" d="M152 106q0 67 30.5 101.5t87.5 34.5q58 0 90.5 -34.5t32.5 -101.5q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5zM682 106q0 67 30.5 101.5t87.5 34.5q58 0 90.5 -34.5t32.5 -101.5q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5zM1213 106 q0 67 30.5 101.5t87.5 34.5q58 0 90.5 -34.5t32.5 -101.5q0 -65 -33 -100t-90 -35q-51 0 -84.5 31.5t-33.5 103.5z" />
+<glyph unicode="&#x202f;" horiz-adv-x="313" />
+<glyph unicode="&#x205f;" horiz-adv-x="392" />
+<glyph unicode="&#x20ac;" horiz-adv-x="1208" d="M63 506v129h152l-2 42v44l2 80h-152v129h164q39 261 185 407t383 146q201 0 366 -97l-71 -139q-166 86 -295 86q-319 0 -398 -403h510v-129h-524l-2 -57v-64l2 -45h463v-129h-447q37 -180 138.5 -278.5t271.5 -98.5q156 0 309 66v-150q-146 -65 -317 -65 q-237 0 -381.5 134.5t-190.5 391.5h-166z" />
+<glyph unicode="&#x2122;" horiz-adv-x="1589" d="M37 1356v106h543v-106h-211v-615h-123v615h-209zM647 741v721h187l196 -559l203 559h180v-721h-127v420l6 137h-8l-211 -557h-104l-201 559h-8l6 -129v-430h-119z" />
+<glyph unicode="&#xe000;" horiz-adv-x="1095" d="M0 1095h1095v-1095h-1095v1095z" />
+</font>
+</defs></svg> \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.ttf b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.ttf
new file mode 100644
index 0000000000..05951e7b36
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.ttf
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.woff b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.woff
new file mode 100644
index 0000000000..274664b28e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/fonts/OpenSans-Regular.woff
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/guardsquare.png b/third_party/java/proguard/proguard5.3.3/docs/guardsquare.png
new file mode 100644
index 0000000000..99ef62c73a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/guardsquare.png
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/index.html b/third_party/java/proguard/proguard5.3.3/docs/index.html
new file mode 100644
index 0000000000..da398c35af
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/index.html
@@ -0,0 +1,96 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-script-type" content="text/javascript">
+<meta http-equiv="content-style-type" content="text/css">
+<meta name="author" content="Eric Lafortune">
+<meta name="description" content="ProGuard: java shrinker, optimizer, obfuscator, and preverifier">
+<meta name="keywords" content="java obfuscator, optimizer, shrinker, preverfier">
+<link rel="stylesheet" type="text/css" href="style.css">
+<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
+<title>ProGuard</title>
+</head>
+
+<script type="text/javascript" language="JavaScript">
+//<!--
+ var destWindowHash = window.location.hash;
+ function mainFrameLoaded() {
+ if (destWindowHash.length > 1) {
+ var destFrameFile = destWindowHash.substring(1);
+ var currFrameFile = frames["main"].location.href.replace(window.location.href.replace(/index.html.*/, ""), "");
+ if (currFrameFile != destFrameFile) {
+ frames["main"].location.replace(destFrameFile);
+ if (destFrameFile.search("manual/") >= 0)
+ frames["sections"].location.replace("manual/sections.html");
+ }
+ destWindowHash = "";
+ }
+ }
+//-->
+</script>
+
+<frameset
+ rows="50,*"
+ framespacing="0"
+ frameborder="no">
+
+<frame
+ id="title"
+ name="title"
+ src="title.html"
+ scrolling="no"
+ marginwidth="0"
+ marginheight="0"
+ noresize="noresize" />
+
+<frameset
+ cols="120,*"
+ framespacing="0"
+ frameborder="no">
+
+<frame
+ id="sections"
+ name="sections"
+ src="sections.html"
+ scrolling="no"
+ marginwidth="0"
+ marginheight="0"
+ noresize="noresize" />
+
+<frame
+ id="main"
+ name="main"
+ src="main.html"
+ scrolling="auto"
+ marginwidth="10"
+ marginheight="10"
+ noresize="noresize"
+ onload="mainFrameLoaded()" />
+
+</frameset>
+</frameset>
+
+<noframes>
+<body>
+<p class="intro">
+<b>ProGuard</b> is a free Java class file shrinker, optimizer, obfuscator, and
+preverifier. It detects and removes unused classes, fields, methods, and
+attributes. It optimizes bytecode and removes unused instructions. It renames
+the remaining classes, fields, and methods using short meaningless names.
+Finally, it preverifies the processed code for Java 6 or for Java Micro
+Edition.
+</p>
+<p>
+Your browser doesn't support frames, but that's cool.
+<p>
+You can go straight to the <a href="main.html">main page</a>.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</noframes>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/license.html b/third_party/java/proguard/proguard5.3.3/docs/license.html
new file mode 100644
index 0000000000..c535a86ad7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/license.html
@@ -0,0 +1,58 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard License</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="index.html#license.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="index.html#license.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>License</h2>
+
+<b>ProGuard</b> is free. You can use it freely for processing your
+applications, commercial or not. Your code obviously remains yours after
+having been processed, and its license can remain unchanged.
+<p>
+
+The <b>ProGuard code</b> itself is copyrighted, but its distribution license
+provides you with some rights for modifying and redistributing its code and
+its documentation. More specifically, ProGuard is distributed under the terms
+of the <a href="GPL.html">GNU General Public License</a> (GPL), version 2, as
+published by the <a href="http://www.fsf.org/" target="other">Free Software
+Foundation</a> (FSF). In short, this means that you may freely redistribute
+the program, modified or as is, on the condition that you make the complete
+source code available as well. If you develop a program that is linked with
+ProGuard, the program as a whole has to be distributed at no charge under the
+GPL. I am granting a <a href="GPL_exception.html">special exception</a> to the
+latter clause (in wording suggested by the
+<a href="http://www.gnu.org/copyleft/gpl-faq.html#GPLIncompatibleLibs"
+target="other">FSF</a>), for combinations with the following stand-alone
+applications: Gradle, Apache Ant, Apache Maven, the Google Android SDK, the
+Eclipse ProGuardDT GUI, the EclipseME JME IDE, the Oracle NetBeans Java IDE,
+the Oracle JME Wireless Toolkit, and the Simple Build Tool for Scala.
+
+<p>
+The <b>ProGuard user documentation</b> is copyrighted as well. It may only be
+redistributed without changes, along with the unmodified version of the code.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/main.html b/third_party/java/proguard/proguard5.3.3/docs/main.html
new file mode 100644
index 0000000000..97a817d2af
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/main.html
@@ -0,0 +1,108 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<meta name="author" content="Eric Lafortune">
+<meta name="description" content="ProGuard: java shrinker, optimizer, obfuscator, and preverifier">
+<meta name="keywords" content="java obfuscator, optimizer, shrinker, preverfier">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Main</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="index.html#main.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="index.html#main.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Main</h2>
+
+<p class="intro">
+<b>ProGuard</b> is a free Java class file shrinker, optimizer, obfuscator, and
+preverifier. It detects and removes unused classes, fields, methods, and
+attributes. It optimizes bytecode and removes unused instructions. It renames
+the remaining classes, fields, and methods using short meaningless names.
+The resulting applications and libraries are smaller, faster, and a bit better
+hardened against reverse engineering.
+</p>
+Typical applications:
+<ul>
+
+<li>Reducing the size of Android apps for faster downloads from Google Play,
+ shorter startup times, and smaller memory footprints.</li>
+
+<li>Optimizing code for better performance on mobile devices.</li>
+
+<li>Protecting applications and libraries against reverse-engineering and
+ tampering.</li>
+
+</ul>
+<p>
+<b>ProGuard</b>'s main advantage compared to other Java obfuscators is
+probably its compact template-based configuration. A few intuitive command
+line options or a simple configuration file are usually sufficient.
+The user manual explains all available options and shows examples of this
+powerful configuration style.
+<p>
+<b>ProGuard</b> is fast. It only takes seconds to process programs and
+libraries of several megabytes. The results section presents actual figures
+for a number of applications.
+<p>
+<b>ProGuard</b> is a command-line tool with an optional graphical user
+interface. It also comes with plugins for Ant, for Gradle, and for the JME
+Wireless Toolkit. It is already part of Google's Android SDK, where it can be
+enabled with a simple flag.
+<p>
+<p class="intro">
+<a href="http://www.guardsquare.com/dexguard" target="_top">
+<img align="left" src="android_shades.png" width="64" height="64" /></a>
+<b>ProGuard</b> provides basic protection against reverse engineering and
+tampering, with basic name obfuscation.
+<a href="http://www.guardsquare.com/dexguard"
+target="_top"><b>DexGuard</b></a>, its specialized commercial extension for
+Android, focuses further on the protection of apps, additionally optimizing,
+obfuscating and encrypting strings, classes, resources, resource files, asset
+files, and native libraries. Professional developers should definitely
+consider it for security-sensitive apps.
+</p>
+The following sections provide more detailed information:
+<ul>
+<li><a href="main.html">Main</a>: this overview page.</li>
+<li><a href="results.html">Results</a>: some results obtained with
+ <b>ProGuard</b>, including timings and memory usage.</li>
+<li><a href="FAQ.html">FAQ</a>: answers to some Frequently Asked Questions.</li>
+<li><a href="manual/index.html">Manual</a>: the complete <b>ProGuard</b> user
+ manual, with examples and troubleshooting tips.</li>
+<li><a href="quality.html">Quality</a>: a discussion of the (excellent) quality
+ of <b>ProGuard</b>'s code.</li>
+<li><a href="screenshots.html">Screenshots</a>: some impressions of what <b>ProGuard</b> looks like.</li>
+<li><a href="testimonials.html">Testimonials</a>: what users think of
+ <b>ProGuard</b>.</li>
+<li><a href="license.html">License</a>: <b>ProGuard</b> is free, under a GPL
+ license.</li>
+<li><a href="downloads.html">Downloads</a>: download the <b>ProGuard</b>
+ package yourself.</li>
+<li><a href="feedback.html">Feedback</a>: tell me about your experiences, or
+ learn from others on our forums.</li>
+<li><a href="acknowledgements.html">Acknowledgements</a>: people who have been
+ helpful.</li>
+<li><a href="alternatives.html">Alternatives</a>: other Java obfuscators,
+ optimizers, and shrinkers.</li>
+</ul>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/android_small.png b/third_party/java/proguard/proguard5.3.3/docs/manual/android_small.png
new file mode 100644
index 0000000000..0313515a09
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/android_small.png
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/ant.html b/third_party/java/proguard/proguard5.3.3/docs/manual/ant.html
new file mode 100644
index 0000000000..9116640bcb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/ant.html
@@ -0,0 +1,661 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>Ant Task</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/ant.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/ant.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Ant Task</h2>
+
+<b>ProGuard</b> can be run as a task in the Java-based build tool Ant (version
+1.8 or higher).
+<p>
+
+Before you can use the <code>proguard</code> task, you have to tell Ant about
+this new task. The easiest way is to add the following line to your
+<code>build.xml</code> file:
+<p>
+
+<pre>
+&lt;taskdef resource="proguard/ant/task.properties"
+ classpath="/usr/local/java/proguard/lib/proguard.jar" /&gt;
+</pre>
+<p>
+
+Please make sure the class path is set correctly for your system.
+<p>
+
+There are three ways to configure the ProGuard task:
+<ol>
+<li>using an external configuration file,</li>
+<li>using embedded ProGuard configuration options, or</li>
+<li>using the equivalent XML configuration tags.</li>
+</ol>
+These three ways can be combined, depending on practical circumstances and
+personal preference.
+<p>
+
+<h3>1. An external ProGuard configuration file</h3>
+
+The simplest way to use the ProGuard task in an Ant build file is to keep your
+ProGuard configuration file, and include it from Ant. You can include your
+ProGuard configuration file by setting
+the <a href="#configuration_attribute"><code>configuration</code></a>
+attribute of your
+<code>proguard</code> task. Your ant build file will then look like this:
+<p>
+
+<pre>
+&lt;taskdef resource="proguard/ant/task.properties"
+ classpath="/usr/local/java/proguard/lib/proguard.jar" /&gt;
+&lt;proguard configuration="myconfigfile.pro"/&gt;
+</pre>
+<p>
+
+This is a convenient option if you prefer ProGuard's configuration style over
+XML, if you want to keep your build file small, or if you have to share your
+configuration with developers who don't use Ant.
+<p>
+
+<h3>2. Embedded ProGuard configuration options</h3>
+
+Instead of keeping an external ProGuard configuration file, you can also copy
+the contents of the file into the nested text of the <code>proguard</code> task
+(the PCDATA area). Your Ant build file will then look like this:
+<p>
+
+<pre>
+&lt;taskdef resource="proguard/ant/task.properties"
+ classpath="/usr/local/java/proguard/lib/proguard.jar" /&gt;
+&lt;proguard&gt;
+ -libraryjars ${java.home}/lib/rt.jar
+ -injars in.jar
+ -outjars out.jar
+
+ -keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+ }
+&lt;/proguard&gt;
+</pre>
+<p>
+
+Some minor syntactical changes are required in order to conform with the XML
+standard.
+<p>
+
+Firstly, the <code>#</code> character cannot be used for comments in an XML
+file. Comments must be enclosed by an opening <code>&lt;!--</code> and a
+closing <code>--&gt;</code>. All occurrences of the <code>#</code> character
+can be removed.
+<p>
+
+Secondly, the use of <code>&lt;</code> and <code>&gt;</code> characters would
+upset the structure of the XML build file. Environment variables can be
+specified with the usual Ant style <code>${...}</code>, instead of the ProGuard
+style <code>&lt;...&gt;</code>. Other occurrences of <code>&lt;</code> and
+<code>&gt;</code> have to be encoded as <code>&amp;lt;</code> and
+<code>&amp;gt;</code> respectively.
+<p>
+
+<h3>3. XML configuration tags</h3>
+
+If you really prefer a full-blown XML configuration, you can replace the
+ProGuard configuration options by XML configuration tags. The resulting
+configuration will be equivalent, but much more verbose and difficult to read,
+as XML goes. The remainder of this page presents the supported tags. For a
+more extensive discussion of their meaning, please consult the traditional <a
+href="usage.html">Usage</a> section. You can find some sample configuration
+files in the <code>examples/ant</code> directory of the ProGuard distribution.
+<p>
+
+<h2><a name="proguard">Task Attributes and Nested Elements</a></h2>
+
+The <code><b>&lt;proguard&gt;</b></code> task and the
+<code><b>&lt;proguardconfiguration&gt;</b></code> task can have the following
+attributes (only for <code>&lt;proguard&gt;</code>) and nested
+elements:
+
+<dl>
+
+<dt><a name="configuration_attribute"><code><b>configuration</b></code></a>
+ = "<i>filename</i>"</dt>
+<dd>Read and merge options from the given ProGuard-style configuration
+ file. Note: for reading multiple configuration files or XML-style
+ configurations, use the <a
+ href="#configuration_element"><code>configuration</code></a>
+ <i>element</i>.</dd>
+
+<dt><a href="usage.html#skipnonpubliclibraryclasses"><code><b>skipnonpubliclibraryclasses</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Ignore non-public library classes.</dd>
+
+<dt><a href="usage.html#dontskipnonpubliclibraryclassmembers"><code><b>skipnonpubliclibraryclassmembers</b></code></a>
+ = "<i>boolean</i>"
+ (default = true)</dt>
+<dd>Ignore package visible library class members.</dd>
+
+<dt><a href="usage.html#target"><code><b>target</b></code></a>
+ = "<i>version</i>"
+ (default = none)</dt>
+<dd>Set the given version number in the processed classes.</dd>
+
+<dt><a href="usage.html#forceprocessing"><code><b>forceprocessing</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Process the input, even if the output seems up to date.</dd>
+
+<dt><a href="usage.html#printseeds"><code><b>printseeds</b></code></a>
+ = "<i>boolean or filename</i>"
+ (default = false)</dt>
+<dd>List classes and class members matched by the various <code>keep</code>
+ commands, to the standard output or to the given file.</dd>
+
+<dt><a href="usage.html#dontshrink"><code><b>shrink</b></code></a>
+ = "<i>boolean</i>"
+ (default = true)</dt>
+<dd>Shrink the input class files.</dd>
+
+<dt><a href="usage.html#printusage"><code><b>printusage</b></code></a>
+ = "<i>boolean or filename</i>"
+ (default = false)</dt>
+<dd>List dead code of the input class files, to the standard output or to the
+ given file.</dd>
+
+<dt><a href="usage.html#dontoptimize"><code><b>optimize</b></code></a>
+ = "<i>boolean</i>"
+ (default = true)</dt>
+<dd>Optimize the input class files.</dd>
+
+<dt><a href="usage.html#optimizationpasses"><code><b>optimizationpasses</b></code></a>
+ = "<i>n</i>"
+ (default = 1)</dt>
+<dd>The number of optimization passes to be performed.</dd>
+
+<dt><a href="usage.html#allowaccessmodification"><code><b>allowaccessmodification</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Allow the access modifiers of classes and class members to be modified,
+ while optimizing.</dd>
+
+<dt><a href="usage.html#mergeinterfacesaggressively"><code><b>mergeinterfacesaggressively</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Allow any interfaces to be merged, while optimizing.</dd>
+
+<dt><a href="usage.html#dontobfuscate"><code><b>obfuscate</b></code></a>
+ = "<i>boolean</i>"
+ (default = true)</dt>
+<dd>Obfuscate the input class files.</dd>
+
+<dt><a href="usage.html#printmapping"><code><b>printmapping</b></code></a>
+ = "<i>boolean or filename</i>"
+ (default = false)</dt>
+<dd>Print the mapping from old names to new names for classes and class members
+ that have been renamed, to the standard output or to the given file.</dd>
+
+<dt><a href="usage.html#applymapping"><code><b>applymapping</b></code></a>
+ = "<i>filename</i>"
+ (default = none)</dt>
+<dd>Reuse the given mapping, for incremental obfuscation.</dd>
+
+<dt><a href="usage.html#obfuscationdictionary"><code><b>obfuscationdictionary</b></code></a>
+ = "<i>filename</i>"
+ (default = none)</dt>
+<dd>Use the words in the given text file as obfuscated field names and method
+ names.</dd>
+
+<dt><a href="usage.html#classobfuscationdictionary"><code><b>classobfuscationdictionary</b></code></a>
+ = "<i>filename</i>"
+ (default = none)</dt>
+<dd>Use the words in the given text file as obfuscated class names.</dd>
+
+<dt><a href="usage.html#packageobfuscationdictionary"><code><b>packageobfuscationdictionary</b></code></a>
+ = "<i>filename</i>"
+ (default = none)</dt>
+<dd>Use the words in the given text file as obfuscated package names.</dd>
+
+<dt><a href="usage.html#overloadaggressively"><code><b>overloadaggressively</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Apply aggressive overloading while obfuscating.</dd>
+
+<dt><a href="usage.html#useuniqueclassmembernames"><code><b>useuniqueclassmembernames</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Ensure uniform obfuscated class member names for subsequent incremental
+ obfuscation.</dd>
+
+<dt><a href="usage.html#dontusemixedcaseclassnames"><code><b>usemixedcaseclassnames</b></code></a>
+ = "<i>boolean</i>"
+ (default = true)</dt>
+<dd>Generate mixed-case class names while obfuscating.</dd>
+
+<dt><a href="usage.html#flattenpackagehierarchy"><code><b>flattenpackagehierarchy</b></code></a>
+ = "<i>package_name</i>"
+ (default = none)</dt>
+<dd>Repackage all packages that are renamed into the single given parent
+ package.</dd>
+
+<dt><a href="usage.html#repackageclasses"><code><b>repackageclasses</b></code></a>
+ = "<i>package_name</i>"
+ (default = none)</dt>
+<dd>Repackage all class files that are renamed into the single given
+ package.</dd>
+
+<dt><a href="usage.html#keepparameternames"><code><b>keepparameternames</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Keep the parameter names and types of methods that are kept.</dd>
+
+<dt><a href="usage.html#renamesourcefileattribute"><code><b>renamesourcefileattribute</b></code></a>
+ = "<i>string</i>"
+ (default = none)</dt>
+<dd>Put the given constant string in the <code>SourceFile</code>
+ attributes.</dd>
+
+<dt><a href="usage.html#dontpreverify"><code><b>preverify</b></code></a>
+ = "<i>boolean</i>"
+ (default = true)</dt>
+<dd>Preverify the processed class files if they are targeted at Java Micro
+ Edition or at Java 6 or higher.</dd>
+
+<dt><a href="usage.html#microedition"><code><b>microedition</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Target the processed class files at Java Micro Edition.</dd>
+
+<dt><a href="usage.html#verbose"><code><b>verbose</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Write out some more information during processing.</dd>
+
+<dt><a href="usage.html#dontnote"><code><b>note</b></code></a>
+ = "<i>boolean</i>"
+ (default = true)</dt>
+<dd>Print notes about potential mistakes or omissions in the configuration.
+ Use the nested element <a href="#dontnote">dontnote</a> for more
+ fine-grained control.</dd>
+
+<dt><a href="usage.html#dontwarn"><code><b>warn</b></code></a>
+ = "<i>boolean</i>"
+ (default = true)</dt>
+<dd>Print warnings about unresolved references. Use the nested
+ element <a href="#dontwarn">dontwarn</a> for more fine-grained
+ control. <i>Only use this option if you know what you're doing!</i></dd>
+
+<dt><a href="usage.html#ignorewarnings"><code><b>ignorewarnings</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Print warnings about unresolved references, but continue processing
+ anyhow. <i>Only use this option if you know what you're doing!</i></dd>
+
+<dt><a href="usage.html#printconfiguration"><code><b>printconfiguration</b></code></a>
+ = "<i>boolean or filename</i>"
+ (default = false)</dt>
+<dd>Write out the entire configuration in traditional ProGuard style, to the
+ standard output or to the given file. Useful to replace unreadable
+ XML configurations.</dd>
+
+<dt><a href="usage.html#dump"><code><b>dump</b></code></a>
+ = "<i>boolean or filename</i>"
+ (default = false)</dt>
+<dd>Write out the internal structure of the processed class files, to the
+ standard output or to the given file.</dd>
+
+<dt><a href="usage.html#injars"><code><b>&lt;injar</b></code></a>
+ <a href="#classpath"><i>class_path</i></a>
+ <code><b>/&gt;</b></code></dt>
+<dd>Specifies the program jars (or aars, wars, ears, zips, apks, or
+ directories).</dd>
+
+<dt><a href="usage.html#outjars"><code><b>&lt;outjar</b></code></a>
+ <a href="#classpath"><i>class_path</i></a>
+ <code><b>/&gt;</b></code></dt>
+<dd>Specifies the names of the output jars (or aars, wars, ears, zips, apks, or
+ directories).</dd>
+
+<dt><a href="usage.html#libraryjars"><code><b>&lt;libraryjar</b></code></a>
+ <a href="#classpath"><i>class_path</i></a>
+ <code><b>/&gt;</b></code></dt>
+<dd>Specifies the library jars (or aars, wars, ears, zips, apks, or
+ directories).</dd>
+
+<dt><a href="usage.html#keepdirectories"><code><b>&lt;keepdirectory name = </b></code></a>"<i>directory_name</i>"
+ <code><b>/&gt;</b></code><br/>
+ <a href="usage.html#keepdirectories"><code><b>&lt;keepdirectories filter = </b></code></a>"<a href="usage.html#filefilters"><i>directory_filter</i></a>"
+ <code><b>/&gt;</b></code></dt>
+<dd>Keep the specified directories in the output jars (or aars, wars, ears,
+ zips, apks, or directories).</dd>
+
+<dt><a href="usage.html#keep"><code><b>&lt;keep</b></code></a>
+ <a href="#keepmodifier"><i>modifiers</i></a>
+ <a href="#classspecification"><i>class_specification</i></a>
+ <code><b>&gt;</b></code>
+ <a href="#classmemberspecification"><i>class_member_specifications</i></a>
+ <code><b>&lt;/keep&gt;</b></code></dt>
+<dd>Preserve the specified classes <i>and</i> class members.</dd>
+
+<dt><a href="usage.html#keepclassmembers"><code><b>&lt;keepclassmembers</b></code></a>
+ <a href="#keepmodifier"><i>modifiers</i></a>
+ <a href="#classspecification"><i>class_specification</i></a>
+ <code><b>&gt;</b></code>
+ <a href="#classmemberspecification"><i>class_member_specifications</i></a>
+ <code><b>&lt;/keepclassmembers&gt;</b></code></dt>
+<dd>Preserve the specified class members, if their classes are preserved as
+ well.</dd>
+
+<dt><a href="usage.html#keepclasseswithmembers"><code><b>&lt;keepclasseswithmembers</b></code></a>
+ <a href="#keepmodifier"><i>modifiers</i></a>
+ <a href="#classspecification"><i>class_specification</i></a>
+ <code><b>&gt;</b></code>
+ <a href="#classmemberspecification"><i>class_member_specifications</i></a>
+ <code><b>&lt;/keepclasseswithmembers&gt;</b></code></dt>
+<dd>Preserve the specified classes <i>and</i> class members, if all of the
+ specified class members are present.</dd>
+
+<dt><a href="usage.html#keepnames"><code><b>&lt;keepnames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a>
+ <code><b>&gt;</b></code>
+ <a href="#classmemberspecification"><i>class_member_specifications</i></a>
+ <code><b>&lt;/keepnames&gt;</b></code></dt>
+<dd>Preserve the names of the specified classes <i>and</i> class members (if
+ they aren't removed in the shrinking step).</dd>
+
+<dt><a href="usage.html#keepclassmembernames"><code><b>&lt;keepclassmembernames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a>
+ <code><b>&gt;</b></code>
+ <a href="#classmemberspecification"><i>class_member_specifications</i></a>
+ <code><b>&lt;/keepclassmembernames&gt;</b></code></dt>
+<dd>Preserve the names of the specified class members (if they aren't removed
+ in the shrinking step).</dd>
+
+<dt><a href="usage.html#keepclasseswithmembernames"><code><b>&lt;keepclasseswithmembernames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a>
+ <code><b>&gt;</b></code>
+ <a href="#classmemberspecification"><i>class_member_specifications</i></a>
+ <code><b>&lt;/keepclasseswithmembernames&gt;</b></code></dt>
+<dd>Preserve the names of the specified classes <i>and</i> class members, if
+ all of the specified class members are present (after the shrinking
+ step).</dd>
+
+<dt><a href="usage.html#whyareyoukeeping"><code><b>&lt;whyareyoukeeping</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a>
+ <code><b>&gt;</b></code>
+ <a href="#classmemberspecification"><i>class_member_specifications</i></a>
+ <code><b>&lt;/whyareyoukeeping&gt;</b></code></dt>
+<dd>Print details on why the given classes and class members are being kept in
+ the shrinking step.</dd>
+
+<dt><a href="usage.html#assumenosideeffects"><code><b>&lt;assumenosideeffects</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a>
+ <code><b>&gt;</b></code>
+ <a href="#classmemberspecification"><i>class_member_specifications</i></a>
+ <code><b>&lt;/assumenosideeffects&gt;</b></code></dt>
+<dd>Assume that the specified methods don't have any side effects, while
+ optimizing. <i>Only use this option if you know what you're
+ doing!</i></dd>
+
+<dt><a href="usage.html#optimizations"><code><b>&lt;optimization name = </b></code></a>"<a href="optimizations.html"><i>optimization_name</i></a>"
+ <code><b>/&gt;</b></code><br/>
+ <a href="usage.html#optimizations"><code><b>&lt;optimizations filter = </b></code></a>""<a href="optimizations.html"><i>optimization_filter</i></a>"
+ <code><b>/&gt;</b></code></dt>
+<dd>Perform only the specified optimizations.</dd>
+
+<dt><a href="usage.html#keeppackagenames"><code><b>&lt;keeppackagename name = </b></code></a>"<i>package_name</i>"
+ <code><b>/&gt;</b></code><br/>
+ <a href="usage.html#keeppackagenames"><code><b>&lt;keeppackagenames filter = </b></code></a>"<a href="usage.html#filters"><i>package_filter</i></a>"
+ <code><b>/&gt;</b></code></dt>
+<dd>Keep the specified package names from being obfuscated. If no name is
+ given, all package names are preserved.</dd>
+
+<dt><a href="usage.html#keepattributes"><code><b>&lt;keepattribute name = </b></code></a>"<i>attribute_name</i>"
+ <code><b>/&gt;</b></code><br/>
+ <a href="usage.html#keepattributes"><code><b>&lt;keepattributes filter = </b></code></a>"<a href="usage.html#filters"><i>attribute_filter</i></a>"
+ <code><b>/&gt;</b></code></dt>
+<dd>Preserve the specified optional Java bytecode attributes, with optional
+ wildcards. If no name is given, all attributes are preserved.</dd>
+
+<dt><a href="usage.html#adaptclassstrings"><code><b>&lt;adaptclassstrings filter = </b></code></a>"<a href="usage.html#filters"><i>class_filter</i></a>"
+ <code><b>/&gt;</b></code></dt>
+<dd>Adapt string constants in the specified classes, based on the obfuscated
+ names of any corresponding classes.</dd>
+
+<dt><a href="usage.html#adaptresourcefilenames"><code><b>&lt;adaptresourcefilenames filter = </b></code></a>"<a href="usage.html#filefilters"><i>file_filter</i></a>"
+ <code><b>/&gt;</b></code></dt>
+<dd>Rename the specified resource files, based on the obfuscated names of the
+ corresponding class files.</dd>
+
+<dt><a href="usage.html#adaptresourcefilecontents"><code><b>&lt;adaptresourcefilecontents filter = </b></code></a>"<a href="usage.html#filefilters"><i>file_filter</i></a>"
+ <code><b>/&gt;</b></code></dt>
+<dd>Update the contents of the specified resource files, based on the
+ obfuscated names of the processed classes.</dd>
+
+<dt><a name="dontnote" />
+ <a href="usage.html#dontnote"><code><b>&lt;dontnote filter = </b></code></a>"<a href="usage.html#filters"><i>class_filter</i></a>"
+ <code><b>/&gt;</b></code></dt>
+<dd>Don't print notes about classes matching the specified class name
+ filter.</dd>
+
+<dt><a name="dontwarn" />
+ <a href="usage.html#dontwarn"><code><b>&lt;dontwarn filter = </b></code></a>"<a href="usage.html#filters"><i>class_filter</i></a>"
+ <code><b>/&gt;</b></code></dt>
+<dd>Don't print warnings about classes matching the specified class name
+ filter. <i>Only use this option if you know what you're doing!</i></dd>
+
+<dt><a name="configuration_element"><code><b>&lt;configuration refid = </b></code></a>"<i>ref_id</i>"
+ <code><b>/&gt;</b></code><br/>
+ <code><b>&lt;configuration file = </b></code>"<i>name</i>"
+ <code><b>/&gt;</b></code></dt>
+<dd>The first form includes the XML-style configuration specified in a
+ <code>&lt;proguardconfiguration&gt;</code> task (or
+ <code>&lt;proguard&gt;</code> task) with attribute <code>id</code> =
+ "<i>ref_id</i>". Only the nested elements of this configuration are
+ considered, not the attributes.
+ <p>
+ The second form includes the ProGuard-style configuration from the specified
+ file. The element is actually a <code>fileset</code> element and supports
+ all of its attributes and nested elements, including multiple files.
+ </dd>
+
+</dl>
+
+<h2><a name="classpath">Class Path Attributes and Nested Elements</a></h2>
+
+The jar elements are <code>path</code> elements, so they can have any of the
+standard <code>path</code> attributes and nested elements. The most common
+attributes are:
+
+<dl>
+
+<dt><code><b>path</b></code> = "<i>path</i>"</dt>
+<dd>The names of the jars (or aars, wars, ears, zips, apks, or directories),
+ separated by the path separator.</dd>
+
+<dt><code><b>location</b></code> = "<i>name</i>" (or <code><b>file</b></code>
+ = "<i>name</i>", or <code><b>dir</b></code> = "<i>name</i>", or
+ <code><b>name</b></code> = "<i>name</i>")</dt>
+<dd>Alternatively, the name of a single jar (or aar, war, ear, zip, or
+ directory).</dd>
+
+<dt><code><b>refid</b></code> = "<i>ref_id</i>"</dt>
+<dd>Alternatively, a reference to the path or file set with the attribute
+ <code>id</code> = "<i>ref_id</i>".</dd>
+
+</dl>
+
+In addition, the jar elements can have ProGuard-style filter attributes:
+
+<dl>
+
+<dt><code><b>filter</b></code> =
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
+<dd>An optional filter for all class file names and resource file names that
+ are encountered.</dd>
+
+<dt><code><b>apkfilter</b></code> =
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
+<dd>An optional filter for all apk names that are encountered.</dd>
+
+<dt><code><b>jarfilter</b></code> =
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
+<dd>An optional filter for all jar names that are encountered.</dd>
+
+<dt><code><b>aarfilter</b></code> =
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
+<dd>An optional filter for all aar names that are encountered.</dd>
+
+<dt><code><b>warfilter</b></code> =
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
+<dd>An optional filter for all war names that are encountered.</dd>
+
+<dt><code><b>earfilter</b></code> =
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
+<dd>An optional filter for all ear names that are encountered.</dd>
+
+<dt><code><b>zipfilter</b></code> =
+ "<a href="usage.html#filefilters"><i>file_filter</i></a>"</dt>
+<dd>An optional filter for all zip names that are encountered.</dd>
+
+</dl>
+
+<h2><a name="keepmodifier">Keep Modifier Attributes</a></h2>
+
+The keep tags can have the following <i>modifier</i> attributes:
+
+<dl>
+
+<dt><a href="usage.html#includedescriptorclasses"><code><b>includedescriptorclasses</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Specifies whether the classes of the fields and methods specified in the
+ keep tag must be kept as well.</dd>
+
+<dt><a href="usage.html#allowshrinking"><code><b>allowshrinking</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Specifies whether the entry points specified in the keep tag may be
+ shrunk.</dd>
+
+<dt><a href="usage.html#allowoptimization"><code><b>allowoptimization</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Specifies whether the entry points specified in the keep tag may be
+ optimized.</dd>
+
+<dt><a href="usage.html#allowobfuscation"><code><b>allowobfuscation</b></code></a>
+ = "<i>boolean</i>"
+ (default = false)</dt>
+<dd>Specifies whether the entry points specified in the keep tag may be
+ obfuscated.</dd>
+
+</dl>
+
+<h2><a name="classspecification">Class Specification Attributes and Nested Elements</a></h2>
+
+The keep tags can have the following <i>class_specification</i> attributes and
+<i>class_member_specifications</i> nested elements:
+
+<dl>
+
+<dt><code><b>access</b></code> = "<i>access_modifiers</i>"</dt>
+<dd>The optional access modifiers of the class. Any space-separated list of
+ "public", "final", and "abstract", with optional negators "!".</dd>
+
+<dt><code><b>annotation</b></code> = "<i>annotation_name</i>"</dt>
+<dd>The optional fully qualified name of an annotation of the class, with
+ optional wildcards.</dd>
+
+<dt><code><b>type</b></code> = "<i>type</i>"</dt>
+<dd>The optional type of the class: one of "class", "interface", or
+ "!interface".</dd>
+
+<dt><code><b>name</b></code> = "<i>class_name</i>"</dt>
+<dd>The optional fully qualified name of the class, with optional
+ wildcards.</dd>
+
+<dt><code><b>extendsannotation</b></code> = "<i>annotation_name</i>"</dt>
+<dd>The optional fully qualified name of an annotation of the the class that
+ the specified classes must extend, with optional wildcards.</dd>
+
+<dt><code><b>extends</b></code> = "<i>class_name</i>"</dt>
+<dd>The optional fully qualified name of the class the specified classes
+ must extend, with optional wildcards.</dd>
+
+<dt><code><b>implements</b></code> = "<i>class_name</i>"</dt>
+<dd>The optional fully qualified name of the class the specified classes
+ must implement, with optional wildcards.</dd>
+
+<dt><code><b>&lt;field</b></code>
+ <a href="#classmemberspecification"><i>class_member_specification</i></a>
+ <code><b>/&gt;</b></code></dt>
+<dd>Specifies a field.</dd>
+
+<dt><code><b>&lt;method</b></code>
+ <a href="#classmemberspecification"><i>class_member_specification</i></a>
+ <code><b>/&gt;</b></code></dt>
+<dd>Specifies a method.</dd>
+
+<dt><code><b>&lt;constructor</b></code>
+ <a href="#classmemberspecification"><i>class_member_specification</i></a>
+ <code><b>/&gt;</b></code></dt>
+<dd>Specifies a constructor.</dd>
+
+</dl>
+
+<h2><a name="classmemberspecification">Class Member Specification Attributes</a></h2>
+
+The class member tags can have the following <i>class_member_specification</i>
+attributes:
+
+<dl>
+
+<dt><code><b>access</b></code> = "<i>access_modifiers</i>"</dt>
+<dd>The optional access modifiers of the class. Any space-separated list of
+ "public", "protected", "private", "static", etc., with optional negators
+ "!".</dd>
+
+<dt><code><b>annotation</b></code> = "<i>annotation_name</i>"</dt>
+<dd>The optional fully qualified name of an annotation of the class member,
+ with optional wildcards.</dd>
+
+<dt><code><b>type</b></code> = "<i>type</i>"</dt>
+<dd>The optional fully qualified type of the class member, with optional
+ wildcards. Not applicable for constructors, but required for methods for
+ which the <code>parameters</code> attribute is specified.</dd>
+
+<dt><code><b>name</b></code> = "<i>name</i>"</dt>
+<dd>The optional name of the class member, with optional wildcards. Not
+ applicable for constructors.</dd>
+
+<dt><code><b>parameters</b></code> = "<i>parameters</i>"</dt>
+<dd>The optional comma-separated list of fully qualified method parameters,
+ with optional wildcards. Not applicable for fields, but required for
+ constructors, and for methods for which the <code>type</code> attribute is
+ specified.</dd>
+
+</dl>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/attention.gif b/third_party/java/proguard/proguard5.3.3/docs/manual/attention.gif
new file mode 100644
index 0000000000..1a0c712d60
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/attention.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/attributes.html b/third_party/java/proguard/proguard5.3.3/docs/manual/attributes.html
new file mode 100644
index 0000000000..7f237cb9b8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/attributes.html
@@ -0,0 +1,217 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>Attributes</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/attributes.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/attributes.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Attributes</h2>
+
+Class files essentially define classes, their fields, and their methods. A lot
+of essential and non-essential data are attached to these classes, fields, and
+methods as <i>attributes</i>. For instance, attributes can contain bytecode,
+source file names, line number tables, etc.
+<p>
+
+ProGuard's obfuscation step removes attributes that are generally not
+necessary for executing the code. With
+the <a href="usage.html#keepattributes"><code>-keepattributes</code></a>
+option, you can specify a filter for attributes that you do want to keep, for
+instance, if your code accesses them through reflection or if you want to
+preserve some compilation or debugging information. The filter works like
+any <a href="usage.html#filters">filter</a> in ProGuard.
+<p>
+
+The following wildcards are supported:
+
+<table cellspacing="10">
+<tr><td valign="top"><code><b>?</b></code></td>
+ <td>matches any single character in an attribute name.</td></tr>
+<tr><td valign="top"><code><b>*</b></code></td>
+ <td>matches any part of an attribute name.</td></tr>
+</table>
+
+An attribute name that is preceded by an exclamation mark '<b>!</b>' is
+<i>excluded</i> from further attempts to match with <i>subsequent</i>
+attribute names in the filter. Make sure to specify filters correctly, since
+they are not checked for potential typos.
+<p>
+
+For example, the following setting preserves the optional attributes that are
+typically necessary when processing code that is intended to be used as a
+library:
+<pre>
+-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
+ SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
+</pre>
+<p>
+
+The Java bytecode specifications currently specify the following list of
+attributes.
+
+<h3>Optional attributes</h3>
+
+ProGuard's obfuscation step by default discards the following optional
+attributes. You can keep them with
+the <a href="usage.html#keepattributes"><code>-keepattributes</code></a>
+option.
+
+<dl>
+<dt><code><b>SourceFile</b></code></dt>
+<dd>Specifies the name of the source file from which the class file was
+ compiled. If present, this name is reported in stack traces.</dd>
+
+<dt><div>(J++ extension)</div>
+ <code><b>SourceDir</b></code></dt>
+<dd>Specifies the name of the source directory from which the class file was
+ compiled.</dd>
+
+<dt><code><b>InnerClasses</b></code></dt>
+<dd>Specifies the relationship between a class and its inner classes and outer
+ classes. Other than this and the naming convention with a '$' separator
+ between the names of inner classes and outer classes, inner classes are
+ just like ordinary classes. Compilers may need this information to find
+ classes referenced in a compiled library. Code may access this information
+ by reflection, for instance to derive the simple name of the class.</dd>
+
+<dt><div>(Java 5 or higher)</div>
+ <code><b>EnclosingMethod</b></code></dt>
+<dd>Specifies the method in which the class was defined. Compilers may need
+ this information to find classes referenced in a compiled library. Code
+ may access this information by reflection, for instance to derive the
+ simple name of the class.</dd>
+
+<dt><code><b>Deprecated</b></code></dt>
+<dd>Indicates that the class, field, or method is deprecated.</dd>
+
+<dt><code><b>Synthetic</b></code></dt>
+<dd>Indicates that the class, field, or method was generated by the
+ compiler.</dd>
+
+<dt><div>(Java 5 or higher)</div>
+ <code><b>Signature</b></code></dt>
+<dd>Specifies the generic signature of the class, field, or method. Compilers
+ may need this information to properly compile classes that use generic
+ types from compiled libraries. Code may access this signature by
+ reflection.</dd>
+
+<dt><div>(Java 8 or higher)</div>
+ <code><b>MethodParameters</b></code></dt>
+<dd>Specifies the names and access flags of the parameters of the method. Code
+ may access this information by reflection.</dd>
+
+<dt><code><b>Exceptions</b></code></dt>
+<dd>Specifies the exceptions that a method may throw. Compilers may use this
+ information to enforce catching them.</dd>
+
+<dt><code><b>LineNumberTable</b></code></dt>
+<dd>Specifies the line numbers of the method. If present, these line numbers
+ are reported in stack traces.</dd>
+
+<dt><code><b>LocalVariableTable</b></code></dt>
+<dd>Specifies the names and types of local variables of the method. If present,
+ some IDEs may use this information for helping with auto-completion.</dd>
+
+<dt><div>(Java 5 or higher)</div>
+ <code><b>LocalVariableTypeTable</b></code></dt>
+<dd>Specifies the names and generic types of local variables of the method. If
+ present, some IDEs may use this information for helping with
+ auto-completion.</dd>
+
+<dt><div>(Java 5 or higher)</div>
+ <code><b>RuntimeVisibleAnnotations</b></code></dt>
+<dd>Specifies the annotations that are visible at run-time, for classes,
+ fields, and methods. Compilers and annotation processors may use these
+ annotations. Code may access them by reflection.</dd>
+
+<dt><div>(Java 5 or higher)</div>
+ <code><b>RuntimeInvisibleAnnotations</b></code></dt>
+<dd>Specifies the annotations that are visible at compile-time, for classes,
+ fields, and methods. Compilers and annotation processors may use these
+ annotations.</dd>
+
+<dt><div>(Java 5 or higher)</div>
+ <code><b>RuntimeVisibleParameterAnnotations</b></code></dt>
+<dd>Specifies the annotations that are visible at run-time, for method
+ parameters. Compilers and annotation processors may use these
+ annotations. Code may access them by reflection.</dd>
+
+<dt><div>(Java 5 or higher)</div>
+ <code><b>RuntimeInvisibleParameterAnnotations</b></code></dt>
+<dd>Specifies the annotations that are visible at compile-time, for method
+ parameters. Compilers and annotation processors may use these
+ annotations.</dd>
+
+<dt><div>(Java 8 or higher)</div>
+ <code><b>RuntimeVisibleTypeAnnotations</b></code></dt>
+<dd>Specifies the annotations that are visible at run-time, for generic types,
+ instructions, etc. Compilers and annotation processors may use these
+ annotations. Code may access them by reflection.</dd>
+
+<dt><div>(Java 8 or higher)</div>
+ <code><b>RuntimeInvisibleTypeAnnotations</b></code></dt>
+<dd>Specifies the annotations that are visible at compile-time, for generic
+ types, instructions, etc. Compilers and annotation processors may use
+ these annotations.</dd>
+
+<dt><div>(Java 5 or higher)</div>
+ <code><b>AnnotationDefault</b></code></dt>
+<dd>Specifies a default value for an annotation.</dd>
+
+</dl>
+<p>
+
+<h3>Essential attributes</h3>
+
+ProGuard automatically keeps the following essential attributes, processing
+them as necessary. We're listing them for the sake of completeness.
+
+<dl>
+<dt><code><b>ConstantValue</b></code></dt>
+<dd>Specifies a constant integer, float, class, string, etc.</dd>
+
+<dt><code><b>Code</b></code></dt>
+<dd>Specifies the actual bytecode of a method.</dd>
+
+<dt><div>(Java Micro Edition)</div>
+ <code><b>StackMap</b></code></dt>
+<dd>Provides preverification information. The Java Virtual Machine can use
+ this information to speed up the verification step when loading a
+ class.</dd>
+
+<dt><div>(Java 6 or higher)</div>
+ <code><b>StackMapTable</b></code></dt>
+<dd>Provides preverification information. The Java Virtual Machine can use
+ this information to speed up the verification step when loading a
+ class.</dd>
+
+<dt><div>(Java 7 or higher)</div>
+ <code><b>BootstrapMethods</b></code></dt>
+<dd>Specifies the methods to bootstrap dynamic method invocations.</dd>
+
+</dl>
+<p>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/examples.html b/third_party/java/proguard/proguard5.3.3/docs/manual/examples.html
new file mode 100644
index 0000000000..bb0b11a559
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/examples.html
@@ -0,0 +1,1693 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Examples</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/examples.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/examples.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Examples</h2>
+
+Some typical useful configurations:
+<ol>
+<li><a href="#application">A typical application</a></li>
+<li><a href="#applet">A typical applet</a></li>
+<li><a href="#midlet">A typical midlet</a></li>
+<li><a href="#jcapplet">A typical Java Card applet</a></li>
+<li><a href="#xlet">A typical xlet</a></li>
+<li><a href="#androidactivity">A simple Android activity</a></li>
+<li><a href="#androidapplication">A complete Android application</a></li>
+<li><a href="#library">A typical library</a></li>
+<li><a href="#applications">All possible applications in the input jars</a></li>
+<li><a href="#applets">All possible applets in the input jars</a></li>
+<li><a href="#midlets">All possible midlets in the input jars</a></li>
+<li><a href="#jcapplets">All possible Java Card applets in the input jars</a></li>
+<li><a href="#xlets">All possible xlets in the input jars</a></li>
+<li><a href="#servlets">All possible servlets in the input jars</a></li>
+<li><a href="#scala">Scala applications with the Scala runtime</a></li>
+<li><a href="#native">Processing native methods</a></li>
+<li><a href="#callback">Processing callback methods</a></li>
+<li><a href="#enumerations">Processing enumeration classes</a></li>
+<li><a href="#serializable">Processing serializable classes</a></li>
+<li><a href="#beans">Processing bean classes</a></li>
+<li><a href="#annotations">Processing annotations</a></li>
+<li><a href="#database">Processing database drivers</a></li>
+<li><a href="#componentui">Processing ComponentUI classes</a></li>
+<li><a href="#rmi">Processing RMI code</a></li>
+<li><a href="#injection">Processing dependency injection</a></li>
+<li><a href="#dagger">Processing Dagger code</a></li>
+<li><a href="#butterknife">Processing Butterknife code</a></li>
+<li><a href="#resourcefiles">Processing resource files</a></li>
+<li><a href="#manifestfiles">Processing manifest files</a></li>
+<li><a href="#stacktrace">Producing useful obfuscated stack traces</a></li>
+<li><a href="#repackaging">Obfuscating package names</a></li>
+<li><a href="#logging">Removing logging code</a></li>
+<li><a href="#restructuring">Restructuring the output archives</a></li>
+<li><a href="#filtering">Filtering the input and the output</a></li>
+<li><a href="#multiple">Processing multiple applications at once</a></li>
+<li><a href="#incremental">Incremental obfuscation</a></li>
+<li><a href="#microedition">Preverifying class files for Java Micro Edition</a></li>
+<li><a href="#upgrade">Upgrading class files to Java 6</a></li>
+<li><a href="#deadcode">Finding dead code</a></li>
+<li><a href="#structure">Printing out the internal structure of class files</a></li>
+<li><a href="#annotated">Using annotations to configure ProGuard</a></li>
+</ol>
+
+You can find some sample configuration files in the <code>examples</code>
+directory of the ProGuard distribution.
+
+<h3><a name="application">A typical application</a></h3>
+
+To shrink, optimize, and obfuscate a simple Java application, you typically
+create a configuration file like <code>myconfig.pro</code>, which can be used
+with
+<pre>
+bin/proguard @myconfig.pro
+</pre>
+<p>
+The configuration file specifies the input, the output, and the entry points
+of the application:
+<pre>
+-injars myapplication.jar
+-outjars myapplication_out.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+-printmapping myapplication.map
+
+-keep public class mypackage.MyMain {
+ public static void main(java.lang.String[]);
+}
+</pre>
+<p>
+Note the use of the <code>&lt;java.home&gt;</code> system property. ProGuard
+automatically replaces it when parsing the file.
+<p>
+The <a href="usage.html#keep"><code>-keep</code></a> option specifies the
+entry point of the application that has to be preserved.
+The access modifiers <code>public</code> and <code>static</code> are not
+really required in this case, since we know a priori that the specified class
+and method have the proper access flags. It just looks more familiar this way.
+<p>
+Note that all type names are fully specified:
+<code>mypackage.MyMain</code> and <code>java.lang.String[]</code>.
+<p>
+We're writing out an obfuscation mapping file with <a
+href="usage.html#printmapping"><code>-printmapping</code></a>, for
+de-obfuscating any stack traces later on, or for incremental obfuscation of
+extensions.
+<p>
+We can further improve the results with a few additional options:
+<pre>
+-optimizationpasses 3
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+</pre>
+These options are not required; they just shave off some extra bytes from the
+output jar, by performing up to 3 optimization passes, and by aggressively
+obfuscating class members and <a href="#repackaging">package names</a>.
+<p>
+In general, you might need a few additional options for processing <a
+href="#native">native methods</a>, <a href="#callback">callback methods</a>,
+<a href="#enumerations">enumerations</a>, <a href="#serializable">serializable
+classes</a>, <a href="#beans">bean classes</a>, <a
+href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
+files</a>.
+
+<h3><a name="applet">A typical applet</a></h3>
+
+These options shrink, optimize, and obfuscate the applet
+<code>mypackage.MyApplet</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+
+-keep public class mypackage.MyApplet
+</pre>
+<p>
+The typical applet methods will be preserved automatically, since
+<code>mypackage.MyApplet</code> is an extension of the <code>Applet</code>
+class in the library <code>rt.jar</code>.
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a>, <a href="#callback">callback methods</a>, <a
+href="#enumerations">enumerations</a>, <a href="#serializable">serializable
+classes</a>, <a href="#beans">bean classes</a>, <a
+href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
+files</a>.
+
+<h3><a name="midlet">A typical midlet</a></h3>
+
+These options shrink, optimize, obfuscate, and preverify the midlet
+<code>mypackage.MyMIDlet</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/midpapi20.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/cldcapi11.jar
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+-microedition
+
+-keep public class mypackage.MyMIDlet
+</pre>
+<p>
+Note how we're now targeting the Java Micro Edition run-time environment of
+<code>midpapi20.jar</code> and <code>cldcapi11.jar</code>, instead of the Java
+Standard Edition run-time environment <code>rt.jar</code>. You can target
+other JME environments by picking the appropriate jars.
+<p>
+The typical midlet methods will be preserved automatically, since
+<code>mypackage.MyMIDlet</code> is an extension of the <code>MIDlet</code>
+class in the library <code>midpapi20.jar</code>.
+<p>
+The <a href="usage.html#microedition"><code>-microedition</code></a> option
+makes sure the class files are preverified for Java Micro Edition, producing
+compact <code>StackMap</code> attributes. It is no longer necessary to run an
+external preverifier.
+<p>
+Be careful if you do use the external <code>preverify</code> tool on a platform
+with a case-insensitive filing system, such as Windows. Because this tool
+unpacks your processed jars, you should then use ProGuard's <a
+href="usage.html#dontusemixedcaseclassnames"><code>-dontusemixedcaseclassnames</code></a>
+option.
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a> and <a href="#resourcefiles">resource files</a>.
+<p>
+Note that you will still have to adapt the midlet jar size in the
+corresponding jad file; ProGuard doesn't do that for you.
+
+<h3><a name="jcapplet">A typical Java Card applet</a></h3>
+
+These options shrink, optimize, and obfuscate the Java Card applet
+<code>mypackage.MyApplet</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/javacard2.2.2/lib/api.jar
+-dontwarn java.lang.Class
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+
+-keep public class mypackage.MyApplet
+</pre>
+<p>
+The configuration is very similar to the configuration for midlets, except that
+it now targets the Java Card run-time environment. This environment doesn't
+have java.lang.Class, so we're telling ProGuard not to worry about it.
+
+<h3><a name="xlet">A typical xlet</a></h3>
+
+These options shrink, optimize, and obfuscate the xlet
+<code>mypackage.MyXlet</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/jtv1.1/javatv.jar
+-libraryjars /usr/local/java/cdc1.1/lib/cdc.jar
+-libraryjars /usr/local/java/cdc1.1/lib/btclasses.zip
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+
+-keep public class mypackage.MyXlet
+</pre>
+<p>
+The configuration is very similar to the configuration for midlets, except that
+it now targets the CDC run-time environment with the Java TV API.
+
+<h3><a name="androidactivity">A simple Android activity</a></h3>
+
+These options shrink, optimize, and obfuscate the single Android
+activity <code>mypackage.MyActivity</code>:
+<pre>
+-injars bin/classes
+-outjars bin/classes-processed.jar
+-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar
+
+-dontpreverify
+-repackageclasses ''
+-allowaccessmodification
+-optimizations !code/simplification/arithmetic
+
+-keep public class mypackage.MyActivity
+</pre>
+<p>
+We're targeting the Android run-time and keeping the activity as an entry
+point.
+<p>
+Preverification is irrelevant for the dex compiler and the Dalvik VM, so we
+can switch it off with the
+<a href="usage.html#dontpreverify"><code>-dontpreverify</code></a> option.
+<p>
+The <a href="usage.html#optimizations"><code>-optimizations</code></a> option
+disables some arithmetic simplifications that Dalvik 1.0 and 1.5 can't handle.
+Note that the Dalvik VM also can't
+handle <a href="usage.html#overloadaggressively">aggressive overloading</a>
+(of static fields).
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a>, <a href="#callback">callback methods</a>,
+<a href="#enumerations">enumerations</a>,
+<a href="#annotations">annotations</a>, and
+<a href="#resourcefiles">resource files</a>.
+
+<h3><a name="androidapplication">A complete Android application</a></h3>
+
+<img class="float" src="attention.gif" width="64" height="64" alt="attention"
+/> The standard build processes of the Android SDK (with Ant, Gradle, Android
+Studio, and Eclipse) already integrate ProGuard with all the proper settings.
+You only need to enable ProGuard by uncommenting the line
+"<code>proguard.config=.....</code>" in the
+file <code>project.properties</code> (created or updated by Android SDK
+revision 17 or higher) or by adapting your <code>build.gradle</code> file. You
+then <em>don't</em> need any of the configuration below.
+<p>
+Notes:
+<ul>
+<li>In case of problems, you may want to check if the configuration files that
+ are listed on this line (<code>proguard-project.txt</code>,...) contain
+ the necessary settings for your application.</li>
+<li>Android SDK revision 20 and higher have a different configuration file for
+ enabling optimization:
+ <code>${sdk.dir}/tools/proguard/proguard-android-optimize.txt</code>
+ instead of the default
+ <code>${sdk.dir}/tools/proguard/proguard-android.txt</code>.</li>
+<li>The build processes are already setting the necessary program jars,
+ library jars, and output jars for you &mdash; don't specify them again.</li>
+<li>If you get warnings about missing referenced classes: it's all too common
+ that libraries refer to missing classes.
+ See <a href="troubleshooting.html#unresolvedclass">"Warning: can't find
+ referenced class"</a> in the Troubleshooting section.</li>
+</ul>
+<p>
+For more information, you can consult the official <a target="other"
+href="http://developer.android.com/guide/developing/tools/proguard.html">Developer
+Guide</a> in the Android SDK.
+<p>
+If you're constructing a build process <em>from scratch</em>: these options
+shrink, optimize, and obfuscate all public activities, services, broadcast
+receivers, and content providers from the compiled classes and external
+libraries:
+<pre>
+-injars bin/classes
+-injars libs
+-outjars bin/classes-processed.jar
+-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar
+
+-dontpreverify
+-repackageclasses ''
+-allowaccessmodification
+-optimizations !code/simplification/arithmetic
+-keepattributes *Annotation*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+
+-keep public class * extends android.view.View {
+ public &lt;init&gt;(android.content.Context);
+ public &lt;init&gt;(android.content.Context, android.util.AttributeSet);
+ public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int);
+ public void set*(...);
+}
+
+-keepclasseswithmembers class * {
+ public &lt;init&gt;(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+ public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.content.Context {
+ public void *(android.view.View);
+ public void *(android.view.MenuItem);
+}
+
+-keepclassmembers class * implements android.os.Parcelable {
+ static ** CREATOR;
+}
+
+-keepclassmembers class **.R$* {
+ public static &lt;fields&gt;;
+}
+
+-keepclassmembers class * {
+ @android.webkit.JavascriptInterface &lt;methods&gt;;
+}
+</pre>
+<p>
+Most importantly, we're keeping all fundamental classes that may be referenced
+by the <code>AndroidManifest.xml</code> file of the application. If your
+manifest file contains other classes and methods, you may have to specify
+those as well.
+<p>
+We're keeping annotations, since they might be used by custom
+<code>RemoteViews</code>.
+<p>
+We're keeping any custom <code>View</code> extensions and other classes with
+typical constructors, since they might be referenced from XML layout files.
+<p>
+We're also keeping possible <code>onClick</code> handlers in
+custom <code>Context</code> extensions, since they might be referenced from
+XML layout files.
+<p>
+We're also keeping the required static fields in <code>Parcelable</code>
+implementations, since they are accessed by introspection.
+<p>
+We're keeping the static fields of referenced inner classes of auto-generated
+ <code>R</code> classes, just in case your code is accessing those fields by
+introspection. Note that the compiler already inlines primitive fields, so
+ProGuard can generally remove all these classes entirely anyway (because the
+classes are not referenced and therefore not required).
+<p>
+Finally, we're keeping annotated Javascript interface methods, so they can be
+exported and accessed by their original names. Javascript interface methods
+that are not annotated (in code targeted at Android versions older than 4.2)
+still need to be preserved manually.
+<p>
+If you're using additional Google APIs, you'll have to specify
+those as well, for instance:
+<pre>
+-libraryjars /usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar
+</pre>
+<p>
+If you're using Google's optional License Verification Library, you can
+obfuscate its code along with your own code. You do have to preserve
+its <code>ILicensingService</code> interface for the library to work:
+<pre>
+-keep public interface com.android.vending.licensing.ILicensingService
+</pre>
+<p>
+If you're using the Android Compatibility library, you should add the
+following line, to let ProGuard know it's ok that the library references some
+classes that are not available in all versions of the API:
+<pre>
+-dontwarn android.support.**
+</pre>
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a>, <a href="#callback">callback methods</a>,
+<a href="#enumerations">enumerations</a>,
+and <a href="#resourcefiles">resource files</a>. You may also want to add
+options for producing <a href="#stacktrace">useful stack traces</a> and
+to <a href="#logging">remove logging</a>. You can find a complete sample
+configuration in <code>examples/android.pro</code> in the ProGuard
+distribution.
+
+<h3><a name="library">A typical library</a></h3>
+
+These options shrink, optimize, and obfuscate an entire library, keeping all
+public and protected classes and class members, native method names, and
+serialization code. The processed version of the library can then still be
+used as such, for developing code based on its public API.
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+-printmapping out.map
+
+-keepparameternames
+-renamesourcefileattribute SourceFile
+-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
+ SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
+
+-keep public class * {
+ public protected *;
+}
+
+-keepclassmembernames class * {
+ java.lang.Class class$(java.lang.String);
+ java.lang.Class class$(java.lang.String, boolean);
+}
+
+-keepclasseswithmembernames,includedescriptorclasses class * {
+ native &lt;methods&gt;;
+}
+
+-keepclassmembers,allowoptimization enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ private static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+</pre>
+<p>
+This configuration should preserve everything we'll ever want to access in the
+library. Only if there are any other non-public classes or methods that are
+invoked dynamically, they should be specified using additional <a
+href="usage.html#keep"><code>-keep</code></a> options.
+<p>
+The <a
+href="usage.html#keepclassmembernames"><code>-keepclassmembernames</code></a>
+option for the <code>class$</code> methods is not strictly necessary. These
+methods are inserted by the <code>javac</code> compiler and the
+<code>jikes</code> compiler respectively, in JDK 1.2 and older, to implement
+the <code>.class</code> construct. ProGuard will automatically detect them and
+deal with them, even when their names have been obfuscated. However, other
+obfuscators may rely on the original method names. It may therefore be helpful
+to preserve them, in case these other obfuscators are ever used for further
+obfuscation of the library.
+<p>
+The "Exceptions" attribute has to be preserved, so the compiler knows which
+exceptions methods may throw.
+<p>
+The "InnerClasses" attribute (or more precisely, its source name part) has to
+be preserved too, for any inner classes that can be referenced from outside the
+library. The <code>javac</code> compiler would be unable to find the inner
+classes otherwise.
+<p>
+The "Signature" attribute is required to be able to access generic types when
+compiling in JDK 5.0 and higher.
+<p>
+The <a href="usage.html#keepparameternames"><code>-keepparameternames</code></a>
+option keeps the parameter names in the "LocalVariableTable" and
+"LocalVariableTypeTable" attributes of public library methods. Some IDEs can
+present these names to the developers who use the library.
+<p>
+Finally, we're keeping the "Deprecated" attribute and the attributes for
+producing <a href="#stacktrace">useful stack traces</a>.
+<p>
+We've also added some options for for processing <a href="#native">native
+methods</a>, <a href="#enumerations">enumerations</a>, <a
+href="#serializable">serializable classes</a>, and <a
+href="#annotations">annotations</a>, which are all discussed in their
+respective examples.
+
+<h3><a name="applications">All possible applications in the input jars</a></h3>
+
+These options shrink, optimize, and obfuscate all public applications in
+<code>in.jar</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+-printseeds
+
+-keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+}
+</pre>
+<p>
+Note the use of <a
+href="usage.html#keepclasseswithmembers"><code>-keepclasseswithmembers</code></a>.
+We don't want to preserve all classes, just all classes that have main
+methods, and those methods.
+<p>
+The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
+out which classes exactly will be preserved, so we know for sure we're getting
+what we want.
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a>, <a href="#callback">callback methods</a>, <a
+href="#enumerations">enumerations</a>, <a href="#serializable">serializable
+classes</a>, <a href="#beans">bean classes</a>, <a
+href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
+files</a>.
+
+<h3><a name="applets">All possible applets in the input jars</a></h3>
+
+These options shrink, optimize, and obfuscate all public applets in
+<code>in.jar</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+-printseeds
+
+-keep public class * extends java.applet.Applet
+</pre>
+<p>
+We're simply keeping all classes that extend the <code>Applet</code> class.
+<p>
+Again, the <a href="usage.html#printseeds"><code>-printseeds</code></a> option
+prints out which applets exactly will be preserved.
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a>, <a href="#callback">callback methods</a>, <a
+href="#enumerations">enumerations</a>, <a href="#serializable">serializable
+classes</a>, <a href="#beans">bean classes</a>, <a
+href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
+files</a>.
+
+<h3><a name="midlets">All possible midlets in the input jars</a></h3>
+
+These options shrink, optimize, obfuscate, and preverify all public midlets in
+<code>in.jar</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/midpapi20.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/cldcapi11.jar
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+-microedition
+-printseeds
+
+-keep public class * extends javax.microedition.midlet.MIDlet
+</pre>
+<p>
+We're simply keeping all classes that extend the <code>MIDlet</code> class.
+<p>
+The <a href="usage.html#microedition"><code>-microedition</code></a> option
+makes sure the class files are preverified for Java Micro Edition, producing
+compact <code>StackMap</code> attributes. It is no longer necessary to run an
+external preverifier.
+<p>
+Be careful if you do use the external <code>preverify</code> tool on a platform
+with a case-insensitive filing system, such as Windows. Because this tool
+unpacks your processed jars, you should then use ProGuard's <a
+href="usage.html#dontusemixedcaseclassnames"><code>-dontusemixedcaseclassnames</code></a>
+option.
+<p>
+The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
+out which midlets exactly will be preserved.
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a> and <a href="#resourcefiles">resource files</a>.
+<p>
+Note that you will still have to adapt the midlet jar size in the
+corresponding jad file; ProGuard doesn't do that for you.
+
+<h3><a name="jcapplets">All possible Java Card applets in the input jars</a></h3>
+
+These options shrink, optimize, and obfuscate all public Java Card applets in
+<code>in.jar</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/javacard2.2.2/lib/api.jar
+-dontwarn java.lang.Class
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+-printseeds
+
+-keep public class * implements javacard.framework.Applet
+</pre>
+<p>
+We're simply keeping all classes that implement the <code>Applet</code>
+interface.
+<p>
+The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
+out which applets exactly will be preserved.
+
+<h3><a name="xlets">All possible xlets in the input jars</a></h3>
+
+These options shrink, optimize, and obfuscate all public xlets in
+<code>in.jar</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/jtv1.1/javatv.jar
+-libraryjars /usr/local/java/cdc1.1/lib/cdc.jar
+-libraryjars /usr/local/java/cdc1.1/lib/btclasses.zip
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+-printseeds
+
+-keep public class * implements javax.tv.xlet.Xlet
+</pre>
+<p>
+We're simply keeping all classes that implement the <code>Xlet</code> interface.
+<p>
+The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
+out which xlets exactly will be preserved.
+
+<h3><a name="servlets">All possible servlets in the input jars</a></h3>
+
+These options shrink, optimize, and obfuscate all public servlets in
+<code>in.jar</code>:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+-libraryjars /usr/local/java/servlet/servlet.jar
+-printseeds
+
+-keep public class * implements javax.servlet.Servlet
+</pre>
+<p>
+Keeping all servlets is very similar to keeping all applets. The servlet API
+is not part of the standard run-time jar, so we're specifying it as a library.
+Don't forget to use the right path name.
+<p>
+We're then keeping all classes that implement the <code>Servlet</code>
+interface. We're using the <code>implements</code> keyword because it looks
+more familiar in this context, but it is equivalent to <code>extends</code>,
+as far as ProGuard is concerned.
+<p>
+The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
+out which servlets exactly will be preserved.
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a>, <a href="#callback">callback methods</a>, <a
+href="#enumerations">enumerations</a>, <a href="#serializable">serializable
+classes</a>, <a href="#beans">bean classes</a>, <a
+href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
+files</a>.
+
+<h3><a name="scala">Scala applications with the Scala runtime</a></h3>
+
+These options shrink, optimize, and obfuscate all public Scala applications in
+<code>in.jar</code>:
+<pre>
+-injars in.jar
+-injars /usr/local/java/scala-2.9.1/lib/scala-library.jar
+-outjars out.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+
+-dontwarn scala.**
+
+-keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+}
+
+-keep class * implements org.xml.sax.EntityResolver
+
+-keepclassmembers class * {
+ ** MODULE$;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinPool {
+ long eventCount;
+ int workerCounts;
+ int runControl;
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode syncStack;
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode spareStack;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinWorkerThread {
+ int base;
+ int sp;
+ int runState;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinTask {
+ int status;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.LinkedTransferQueue {
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference head;
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference tail;
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference cleanMe;
+}
+</pre>
+<p>
+The configuration is essentially the same as
+for <a href="#applications">processing applications</a>, because Scala is
+compiled to ordinary Java bytecode. However, the example processes the Scala
+runtime library as well. The processed jar can be an order of magnitude
+smaller and a few times faster than the original code (for the Scala code
+examples, for instance).
+<p>
+The <a href="usage.html#dontwarn"><code>-dontwarn</code></a> option tells
+ProGuard not to complain about some artefacts in the Scala runtime, the way it
+is compiled by the <code>scalac</code> compiler (at least in Scala 2.9.1 and
+older). Note that this option should always be used with care.
+<p>
+The additional <a href="usage.html#keepoverview"><code>-keep</code></a>
+options make sure that some classes and some fields that are accessed by means
+of introspection are not removed or renamed.
+<p>
+If applicable, you should add options for processing <a href="#native">native
+methods</a>, <a href="#callback">callback methods</a>, <a
+href="#enumerations">enumerations</a>, <a href="#serializable">serializable
+classes</a>, <a href="#beans">bean classes</a>, <a
+href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
+files</a>.
+<h3><a name="native">Processing native methods</a></h3>
+
+If your application, applet, servlet, library, etc., contains native methods,
+you'll want to preserve their names and their classes' names, so they can
+still be linked to the native library. The following additional option will
+ensure that:
+<pre>
+-keepclasseswithmembernames,includedescriptorclasses class * {
+ native &lt;methods&gt;;
+}
+</pre>
+<p>
+Note the use of
+<a href="usage.html#keepclasseswithmembernames"><code>-keepclasseswithmembernames</code></a>.
+We don't want to preserve all classes or all native methods; we just want to
+keep the relevant names from being obfuscated. The modifier
+<a href="usage.html#includedescriptorclasses">includedescriptorclasses</a>
+additionally makes sure that the return types and parameter types aren't
+renamed either, so the entire signatures remain compatible with the native
+libraries.
+<p>
+ProGuard doesn't look at your native code, so it won't automatically preserve
+the classes or class members that are invoked by the native code. These are
+entry points, which you'll have to specify explicitly. <a
+href="callback">Callback methods</a> are discussed below as a typical example.
+
+<h3><a name="callback">Processing callback methods</a></h3>
+
+If your application, applet, servlet, library, etc., contains callback
+methods, which are called from external code (native code, scripts,...),
+you'll want to preserve them, and probably their classes too. They are just
+entry points to your code, much like, say, the main method of an application.
+If they aren't preserved by other <code>-keep</code> options, something like
+the following option will keep the callback class and method:
+<pre>
+-keep class mypackage.MyCallbackClass {
+ void myCallbackMethod(java.lang.String);
+}
+</pre>
+<p>
+This will preserve the given class and method from being removed or renamed.
+
+<h3><a name="enumerations">Processing enumeration classes</a></h3>
+
+If your application, applet, servlet, library, etc., contains enumeration
+classes, you'll have to preserve some special methods. Enumerations were
+introduced in Java 5. The java compiler translates enumerations into classes
+with a special structure. Notably, the classes contain implementations of some
+static methods that the run-time environment accesses by introspection (Isn't
+that just grand? Introspection is the self-modifying code of a new
+generation). You have to specify these explicitly, to make sure they aren't
+removed or obfuscated:
+<pre>
+-keepclassmembers,allowoptimization enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+</pre>
+
+<h3><a name="serializable">Processing serializable classes</a></h3>
+
+More complex applications, applets, servlets, libraries, etc., may contain
+classes that are serialized. Depending on the way in which they are used, they
+may require special attention:
+<ul>
+
+<li>Often, serialization is simply a means of transporting data, without
+ long-term storage. Classes that are shrunk and obfuscated should then
+ continue to function fine with the following additional options:
+
+<pre>
+-keepclassmembers class * implements java.io.Serializable {
+ private static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+</pre>
+<p>
+
+ The <a
+ href="usage.html#keepclassmembers"><code>-keepclassmembers</code></a>
+ option makes sure that any serialization methods are kept. By using this
+ option instead of the basic <code>-keep</code> option, we're not
+ forcing preservation of <i>all</i> serializable classes, just preservation
+ of the listed members of classes that are actually used.</li>
+
+<li>Sometimes, the serialized data are stored, and read back later into newer
+ versions of the serializable classes. One then has to take care the classes
+ remain compatible with their unprocessed versions and with future
+ processed versions. In such cases, the relevant classes will most likely
+ have <code>serialVersionUID</code> fields. The following options should
+ then be sufficient to ensure compatibility over time:
+
+<pre>
+-keepnames class * implements java.io.Serializable
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ private static final java.io.ObjectStreamField[] serialPersistentFields;
+ !static !transient &lt;fields&gt;;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+</pre>
+<p>
+
+ The <code>serialVersionUID</code> and <code>serialPersistentFields</code>
+ lines makes sure those fields are preserved, if they are present.
+ The <code>&lt;fields&gt;</code> line preserves all non-static,
+ non-transient fields, with their original names. The introspection of the
+ serialization process and the de-serialization process will then find
+ consistent names.</li>
+
+<li>Occasionally, the serialized data have to remain compatible, but the
+ classes involved lack <code>serialVersionUID</code> fields. I imagine the
+ original code will then be hard to maintain, since the serial version UID
+ is then computed from a list of features the serializable class. Changing
+ the class ever so slightly may change the computed serial version UID. The
+ list of features is specified in the section on <a
+ href="http://docs.oracle.com/javase/8/docs/platform/serialization/spec/class.html#a4100">Stream
+ Unique Identifiers</a> of Sun's <a
+ href="http://docs.oracle.com/javase/8/docs/platform/serialization/spec/serialTOC.html">Java
+ Object Serialization Specification</a>. The following directives should at
+ least partially ensure compatibility with the original classes:
+
+<pre>
+-keepnames class * implements java.io.Serializable
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ private static final java.io.ObjectStreamField[] serialPersistentFields;
+ !static !transient &lt;fields&gt;;
+ !private &lt;fields&gt;;
+ !private &lt;methods&gt;;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+</pre>
+<p>
+
+ The new options force preservation of the elements involved in the UID
+ computation. In addition, the user will have to manually specify all
+ interfaces of the serializable classes (using something like "<code>-keep
+ interface MyInterface</code>"), since these names are also used when
+ computing the UID. A fast but sub-optimal alternative would be simply
+ keeping all interfaces with "<code>-keep interface *</code>".</li>
+
+<li>In the rare event that you are serializing lambda expressions in Java 8 or
+ higher, you need to preserve some methods and adapt the hard-coded names
+ of the classes in which they occur:
+
+<pre>
+-keepclassmembers class * {
+ private static synthetic java.lang.Object $deserializeLambda$(java.lang.invoke.SerializedLambda);
+}
+
+-keepclassmembernames class * {
+ private static synthetic *** lambda$*(...);
+}
+
+-adaptclassstrings com.example.Test
+</pre>
+<p>
+
+ This should satisfy the reflection in the deserialization code of the
+ Java run-time.
+
+</ul>
+<p>
+
+Note that the above options may preserve more classes and class members
+than strictly necessary. For instance, a large number of classes may implement
+the <code>Serialization</code> interface, yet only a small number may actually
+ever be serialized. Knowing your application and tuning the configuration
+often produces more compact results.
+
+<h3><a name="beans">Processing bean classes</a></h3>
+
+If your application, applet, servlet, library, etc., makes extensive use of
+introspection on bean classes to find bean editor classes, or getter and
+setter methods, then configuration may become painful. There's not much else
+you can do than making sure the bean class names, or the getter and setter
+names don't change. For instance:
+<pre>
+-keep public class mypackage.MyBean {
+ public void setMyProperty(int);
+ public int getMyProperty();
+}
+
+-keep public class mypackage.MyBeanEditor
+</pre>
+<p>
+If there are too many elements to list explicitly, wildcards in class names
+and method signatures might be helpful. This example preserves all possible
+setters and getters in classes in the package <code>mybeans</code>:
+<pre>
+-keep class mybeans.** {
+ void set*(***);
+ void set*(int, ***);
+
+ boolean is*();
+ boolean is*(int);
+
+ *** get*();
+ *** get*(int);
+}
+</pre>
+<p>
+The '<code>***</code>' wildcard matches any type (primitive or non-primitive,
+array or non-array). The methods with the '<code>int</code>' arguments matches
+properties that are lists.
+
+<h3><a name="annotations">Processing annotations</a></h3>
+
+If your application, applet, servlet, library, etc., uses annotations, you may
+want to preserve them in the processed output. Annotations are represented by
+attributes that have no direct effect on the execution of the code. However,
+their values can be retrieved through introspection, allowing developers to
+adapt the execution behavior accordingly. By default, ProGuard treats
+annotation attributes as optional, and removes them in the obfuscation step.
+If they are required, you'll have to specify this explicitly:
+<pre>
+-keepattributes *Annotation*
+</pre>
+<p>
+For brevity, we're specifying a wildcarded attribute name, which will match
+<code>RuntimeVisibleAnnotations</code>,
+<code>RuntimeInvisibleAnnotations</code>,
+<code>RuntimeVisibleParameterAnnotations</code>,
+<code>RuntimeInvisibleParameterAnnotations</code>, and
+<code>AnnotationDefault</code>. Depending on the purpose of the processed
+code, you could refine this selection, for instance not keeping the run-time
+invisible annotations (which are only used at compile-time).
+<p>
+Some code may make further use of introspection to figure out the enclosing
+methods of anonymous inner classes. In that case, the corresponding attribute
+has to be preserved as well:
+<pre>
+-keepattributes EnclosingMethod
+</pre>
+
+<h3><a name="database">Processing database drivers</a></h3>
+
+Database drivers are implementations of the <code>Driver</code> interface.
+Since they are often created dynamically, you may want to preserve any
+implementations that you are processing as entry points:
+<pre>
+-keep class * implements java.sql.Driver
+</pre>
+<p>
+This option also gets rid of the note that ProGuard prints out about
+<code>(java.sql.Driver)Class.forName</code> constructs, if you are
+instantiating a driver in your code (without necessarily implementing any
+drivers yourself).
+
+<h3><a name="componentui">Processing ComponentUI classes</a></h3>
+
+Swing UI look and feels are implemented as extensions of the
+<code>ComponentUI</code> class. For some reason, these have to contain a
+static method <code>createUI</code>, which the Swing API invokes using
+introspection. You should therefore always preserve the method as an entry
+point, for instance like this:
+<pre>
+-keep class * extends javax.swing.plaf.ComponentUI {
+ public static javax.swing.plaf.ComponentUI createUI(javax.swing.JComponent);
+}
+</pre>
+<p>
+This option also keeps the classes themselves.
+
+<h3><a name="rmi">Processing RMI code</a></h3>
+
+Reportedly, the easiest way to handle RMI code is to process the code with
+ProGuard first and then invoke the <code>rmic</code> tool. If that is not
+possible, you may want to try something like this:
+<pre>
+-keepattributes Exceptions
+
+-keep interface * extends java.rmi.Remote {
+ &lt;methods&gt;;
+}
+
+-keep class * implements java.rmi.Remote {
+ &lt;init&gt;(java.rmi.activation.ActivationID, java.rmi.MarshalledObject);
+}
+</pre>
+<p>
+The first <code>-keep</code> option keeps all your Remote interfaces and their
+methods. The second one keeps all the implementations, along with their
+particular RMI constructors, if any.
+<p>
+The <code>Exceptions</code> attribute has to be kept too, because the RMI
+handling code performs introspection to check whether the method signatures
+are compatible.
+
+<h3><a name="injection">Processing dependency injection</a></h3>
+
+If your application is using JEE-style dependency injection, the application
+container will automatically assign instances of resource classes to fields and
+methods that are annotated with <code>@Resource</code>. The container applies
+introspection, even accessing private class members directly. It typically
+constructs a resource name based on the type name and the class member name.
+We then have to avoid that such class members are removed or renamed:
+<pre>
+-keepclassmembers class * {
+ @javax.annotation.Resource *;
+}
+</pre>
+<p>
+The Spring framework has another similar annotation <code>@Autowired</code>:
+<pre>
+-keepclassmembers class * {
+ @org.springframework.beans.factory.annotation.Autowired *;
+}
+</pre>
+
+<h3><a name="dagger">Processing Dagger code</a></h3>
+
+If your Android application includes Dagger for dependency injection, you need
+a few lines of configuration, since Dagger heavily relies on reflection to tie
+together the code at runtime. You need to preserve the annotated class
+members, the generated classes, and a utility class:
+<pre>
+-keepclassmembers,allowobfuscation class * {
+ @dagger.** *;
+}
+
+-keep class **$$ModuleAdapter
+-keep class **$$InjectAdapter
+-keep class **$$StaticInjection
+
+-keepnames class dagger.Lazy
+</pre>
+<p>
+Unfortunately, you still need to explicitly preserve the corresponding base
+classes from your project. For example, for a generated class like
+<code>com.example.SomeClass$$ModuleAdapter</code>, you still need to specify:
+<pre>
+-keep class com.example.SomeClass
+</pre>
+<p>
+Dagger can then still combine the corresponding pairs of classes, based on
+their names. You can figure out the base classes by listing the generated
+classes in the <code>gen</code> directory of your project (e.g.
+<code>com/examples/SomeClass$$ModuleAdapter.class</code>).
+<p>
+Dagger 2 no longer relies on reflection with these naming conventions, which
+makes life a lot easier.
+
+<h3><a name="butterknife">Processing Butterknife code</a></h3>
+
+If your Android application includes Butterknife to inject views, you also
+need a few lines of configuration, since Butterknife relies on reflection to
+tie together the code at runtime:
+<pre>
+-keep @interface butterknife.*
+
+-keepclasseswithmembers class * {
+ @butterknife.* &lt;fields&gt;;
+}
+
+-keepclasseswithmembers class * {
+ @butterknife.* &lt;methods&gt;;
+}
+
+-keepclasseswithmembers class * {
+ @butterknife.On* &lt;methods&gt;;
+}
+
+-keep class **$$ViewInjector {
+ public static void inject(...);
+ public static void reset(...);
+}
+
+-keep class **$$ViewBinder {
+ public static void bind(...);
+ public static void unbind(...);
+}
+</pre>
+<p>
+These settings preserve the Butterknife annotations, the annotated fields and
+methods, and the generated classes and methods that Butterknife accesses by
+reflection.
+
+<h3><a name="resourcefiles">Processing resource files</a></h3>
+
+If your application, applet, servlet, library, etc., contains resource files,
+it may be necessary to adapt their names and/or their contents when the
+application is obfuscated. The following two options can achieve this
+automatically:
+<pre>
+-adaptresourcefilenames **.properties,**.gif,**.jpg
+-adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF
+</pre>
+<p>
+The <a href="usage.html#adaptresourcefilenames">-adaptresourcefilenames</a>
+option in this case renames properties files and image files in the processed
+output, based on the obfuscated names of their corresponding class files (if
+any). The <a
+href="usage.html#adaptresourcefilecontents">-adaptresourcefilecontents</a>
+option looks for class names in properties files and in the manifest file, and
+replaces these names by the obfuscated names (if any). You'll probably want to
+adapt the filters to suit your application.
+
+<h3><a name="manifestfiles">Processing manifest files</a></h3>
+
+As illustrated in the previous section, manifest files can be treated like
+ordinary resource files. ProGuard can adapt obfuscated class names in the
+files, but it won't make any other changes. If you want anything else, you
+should apply an external tool. For instance, if a manifest file contains
+signing information, you should sign the jar again after it has been
+processed.
+<p>
+If you're merging several input jars into a single output jar, you'll have to
+pick one, typically by specifying <a href="usage.html#filters">filters</a>:
+<pre>
+-injars in1.jar
+-injars in2.jar(!META-INF/MANIFEST.MF)
+-injars in3.jar(!META-INF/MANIFEST.MF)
+-outjars out.jar
+</pre>
+<p>
+The filters will let ProGuard copy the manifest file from the first jar and
+ignore any manifest files in the second and third input jars. Note that
+ProGuard will leave the order of the files in the jars unchanged; manifest
+files are not necessarily put first.
+
+<h3><a name="stacktrace">Producing useful obfuscated stack traces</a></h3>
+
+These options let obfuscated applications or libraries produce stack traces
+that can still be deciphered later on:
+<pre>
+-printmapping out.map
+
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
+</pre>
+<p>
+We're keeping all source file attributes, but we're replacing their values by
+the string "SourceFile". We could use any string. This string is already
+present in all class files, so it doesn't take up any extra space. If you're
+working with J++, you'll want to keep the "SourceDir" attribute as well.
+<p>
+We're also keeping the line number tables of all methods.
+<p>
+Whenever both of these attributes are present, the Java run-time environment
+will include line number information when printing out exception stack traces.
+<p>
+The information will only be useful if we can map the obfuscated names back to
+their original names, so we're saving the mapping to a file
+<code>out.map</code>. The information can then be used by the <a
+href="retrace/index.html">ReTrace</a> tool to restore the original stack trace.
+
+<h3><a name="repackaging">Obfuscating package names</a></h3>
+
+Package names can be obfuscated in various ways, with increasing levels of
+obfuscation and compactness. For example, consider the following classes:
+<pre>
+mycompany.myapplication.MyMain
+mycompany.myapplication.Foo
+mycompany.myapplication.Bar
+mycompany.myapplication.extra.FirstExtra
+mycompany.myapplication.extra.SecondExtra
+mycompany.util.FirstUtil
+mycompany.util.SecondUtil
+</pre>
+<p>
+Let's assume the class name <code>mycompany.myapplication.MyMain</code> is the
+main application class that is kept by the configuration. All other class names
+can be obfuscated.
+<p>
+By default, packages that contain classes that can't be renamed aren't renamed
+either, and the package hierarchy is preserved. This results in obfuscated
+class names like these:
+<pre>
+mycompany.myapplication.MyMain
+mycompany.myapplication.a
+mycompany.myapplication.b
+mycompany.myapplication.a.a
+mycompany.myapplication.a.b
+mycompany.a.a
+mycompany.a.b
+</pre>
+<p>
+The <a
+href="usage.html#flattenpackagehierarchy"><code>-flattenpackagehierarchy</code></a>
+option obfuscates the package names further, by flattening the package
+hierarchy of obfuscated packages:
+<pre>
+-flattenpackagehierarchy 'myobfuscated'
+</pre>
+<p>
+The obfuscated class names then look as follows:
+<pre>
+mycompany.myapplication.MyMain
+mycompany.myapplication.a
+mycompany.myapplication.b
+myobfuscated.a.a
+myobfuscated.a.b
+myobfuscated.b.a
+myobfuscated.b.b
+</pre>
+<p>
+Alternatively, the <a
+href="usage.html#repackageclasses"><code>-repackageclasses</code></a> option
+obfuscates the entire packaging, by combining obfuscated classes into a single
+package:
+<pre>
+-repackageclasses 'myobfuscated'
+</pre>
+The obfuscated class names then look as follows:
+<pre>
+mycompany.myapplication.MyMain
+mycompany.myapplication.a
+mycompany.myapplication.b
+myobfuscated.a
+myobfuscated.b
+myobfuscated.c
+myobfuscated.d
+</pre>
+<p>
+Additionally specifying the <a
+href="usage.html#allowaccessmodification"><code>-allowaccessmodification</code></a>
+option allows access permissions of classes and class members to
+be broadened, opening up the opportunity to repackage all obfuscated classes:
+<pre>
+-repackageclasses 'myobfuscated'
+-allowaccessmodification
+</pre>
+The obfuscated class names then look as follows:
+<pre>
+mycompany.myapplication.MyMain
+myobfuscated.a
+myobfuscated.b
+myobfuscated.c
+myobfuscated.d
+myobfuscated.e
+myobfuscated.f
+</pre>
+<p>
+The specified target package can always be the root package. For instance:
+<pre>
+-repackageclasses ''
+-allowaccessmodification
+</pre>
+The obfuscated class names are then the shortest possible names:
+<pre>
+mycompany.myapplication.MyMain
+a
+b
+c
+d
+e
+f
+</pre>
+<p>
+Note that not all levels of obfuscation of package names may be acceptable for
+all code. Notably, you may have to take into account that your application may
+contain <a href="#resourcefiles">resource files</a> that have to be adapted.
+
+<h3><a name="logging">Removing logging code</a></h3>
+
+You can let ProGuard remove logging code. The trick is to specify that the
+logging methods don't have side-effects &mdash; even though they actually do,
+since they write to the console or to a log file. ProGuard will take your word
+for it and remove the invocations (in the optimization step) and if possible
+the logging classes and methods themselves (in the shrinking step).
+<p>
+For example, this configuration removes invocations of the Android logging
+methods:
+<pre>
+-assumenosideeffects class android.util.Log {
+ public static boolean isLoggable(java.lang.String, int);
+ public static int v(...);
+ public static int i(...);
+ public static int w(...);
+ public static int d(...);
+ public static int e(...);
+}
+</pre>
+<p>
+The wildcards are a shortcut to match all versions of the methods. Be careful
+not to use a <code>*</code> wildcard to match all methods, because it would
+also match methods like <code>wait()</code>, higher up the hierarchy. Removing
+those invocations will generally break your code.
+<p>
+Note that you generally can't remove logging code that uses
+<code>System.out.println</code>, since you would be removing all invocations
+of <code>java.io.PrintStream#println</code>, which could break your
+application. You can work around it by creating your own logging methods and
+let ProGuard remove those.
+
+<h3><a name="restructuring">Restructuring the output archives</a></h3>
+
+In simple applications, all output classes and resources files are merged into
+a single jar. For example:
+<pre>
+-injars classes
+-injars in1.jar
+-injars in2.jar
+-injars in3.jar
+-outjars out.jar
+</pre>
+<p>
+This configuration merges the processed versions of the files in the
+<code>classes</code> directory and the three jars into a single output jar
+<code>out.jar</code>.
+<p>
+If you want to preserve the structure of your input jars (and/or wars, ears,
+zips, or directories), you can specify an output directory (or a war, an ear,
+or a zip). For example:
+<pre>
+-injars in1.jar
+-injars in2.jar
+-injars in3.jar
+-outjars out
+</pre>
+<p>
+The input jars will then be reconstructed in the directory <code>out</code>,
+with their original names.
+<p>
+You can also combine archives into higher level archives. For example:
+<pre>
+-injars in1.jar
+-injars in2.jar
+-injars in3.jar
+-outjars out.war
+</pre>
+<p>
+The other way around, you can flatten the archives inside higher level
+archives into simple archives:
+<pre>
+-injars in.war
+-outjars out.jar
+</pre>
+<p>
+This configuration puts the processed contents of all jars inside
+<code>in.war</code> (plus any other contents of <code>in.war</code>) into
+<code>out.jar</code>.
+<p>
+If you want to combine input jars (and/or wars, ears, zips, or directories)
+into output jars (and/or wars, ears, zips, or directories), you can group the
+<a href="usage.html#injars"><code>-injars</code></a> and <a
+href="usage.html#outjars"><code>-outjars</code></a> options. For example:
+<pre>
+-injars base_in1.jar
+-injars base_in2.jar
+-injars base_in3.jar
+-outjars base_out.jar
+
+-injars extra_in.jar
+-outjars extra_out.jar
+</pre>
+<p>
+This configuration puts the processed results of all <code>base_in*.jar</code>
+jars into <code>base_out.jar</code>, and the processed results of the
+<code>extra_in.jar</code> into <code>extra_out.jar</code>. Note that only the
+order of the options matters; the additional whitespace is just for clarity.
+<p>
+This grouping, archiving, and flattening can be arbitrarily complex. ProGuard
+always tries to package output archives in a sensible way, reconstructing the
+input entries as much as required.
+
+<h3><a name="filtering">Filtering the input and the output</a></h3>
+
+If you want even greater control, you can add
+<a href="usage.html#filters">filters</a> to the input and the output,
+filtering out zips, ears, wars, jars, and/or ordinary files. For example, if
+you want to disregard certain files from an input jar:
+<pre>
+-injars in.jar(!images/**)
+-outjars out.jar
+</pre>
+<p>
+This configuration removes any files in the <code>images</code> directory and
+its subdirectories.
+<p>
+Such filters can be convenient for avoiding warnings about duplicate files in
+the output. For example, only keeping the manifest file from a first input jar:
+<pre>
+-injars in1.jar
+-injars in2.jar(!META-INF/MANIFEST.MF)
+-injars in3.jar(!META-INF/MANIFEST.MF)
+-outjars out.jar
+</pre>
+<p>
+Another useful application is speeding up the processing by ProGuard, by
+disregarding a large number of irrelevant classes in the runtime library jar:
+<pre>
+-libraryjars &lt;java.home&gt;/lib/rt.jar(java/**,javax/**)
+</pre>
+<p>
+The filter makes ProGuard disregard <code>com.sun.**</code> classes, for
+instance , which don't affect the processing of ordinary applications.
+<p>
+It is also possible to filter the jars (and/or wars, ears, zips) themselves,
+based on their names. For example:
+<pre>
+-injars in(**/acme_*.jar;)
+-outjars out.jar
+</pre>
+<p>
+Note the semi-colon in the filter; the filter in front of it applies to jar
+names. In this case, only <code>acme_*.jar</code> jars are read from the
+directory <code>in</code> and its subdirectories. Filters for war names, ear
+names, and zip names can be prefixed with additional semi-colons. All types of
+filters can be combined. They are orthogonal.
+<p>
+On the other hand, you can also filter the output, in order to control what
+content goes where. For example:
+<pre>
+-injars in.jar
+-outjars code_out.jar(**.class)
+-outjars resources_out.jar
+</pre>
+<p>
+This configuration splits the processed output, sending <code>**.class</code>
+files to <code>code_out.jar</code>, and all remaining files to
+<code>resources_out.jar</code>.
+<p>
+Again, the filtering can be arbitrarily complex, especially when combined with
+grouping input and output.
+
+<h3><a name="multiple">Processing multiple applications at once</a></h3>
+
+You can process several dependent or independent applications (or applets,
+midlets,...) in one go, in order to save time and effort. ProGuard's input and
+output handling offers various ways to keep the output nicely structured.
+<p>
+The easiest way is to specify your input jars (and/or wars, ears, zips, and
+directories) and a single output directory. ProGuard will then reconstruct the
+input in this directory, using the original jar names. For example, showing
+just the input and output options:
+<pre>
+-injars application1.jar
+-injars application2.jar
+-injars application3.jar
+-outjars processed_applications
+</pre>
+<p>
+After processing, the directory <code>processed_applications</code> will
+contain processed versions of application jars, with their original names.
+
+<h3><a name="incremental">Incremental obfuscation</a></h3>
+
+After having <a href="#application">processed an application</a>, e.g.
+ProGuard itself, you can still incrementally add other pieces of code that
+depend on it, e.g. the ProGuard GUI:
+<pre>
+-injars proguardgui.jar
+-outjars proguardgui_out.jar
+-injars proguard.jar
+-outjars proguard_out.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+-applymapping proguard.map
+
+-keep public class proguard.gui.ProGuardGUI {
+ public static void main(java.lang.String[]);
+}
+</pre>
+<p>
+We're reading both unprocessed jars as input. Their processed contents will go
+to the respective output jars. The <a
+href="usage.html#applymapping"><code>-applymapping</code></a> option then
+makes sure the ProGuard part of the code gets the previously produced
+obfuscation mapping. The final application will consist of the obfuscated
+ProGuard jar and the additional obfuscated GUI jar.
+<p>
+The added code in this example is straightforward; it doesn't affect the
+original code. The <code>proguard_out.jar</code> will be identical to the one
+produced in the initial processing step. If you foresee adding more complex
+extensions to your code, you should specify the options <a
+href="usage.html#useuniqueclassmembernames"><code>-useuniqueclassmembernames</code></a>,
+<a href="usage.html#dontshrink"><code>-dontshrink</code></a>, and <a
+href="usage.html#dontoptimize"><code>-dontoptimize</code></a> <i>in the
+original processing step</i>. These options ensure that the obfuscated base
+jar will always remain usable without changes. You can then specify the base
+jar as a library jar:
+<pre>
+-injars proguardgui.jar
+-outjars proguardgui_out.jar
+-libraryjars proguard.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+-applymapping proguard.map
+
+-keep public class proguard.gui.ProGuardGUI {
+ public static void main(java.lang.String[]);
+}
+</pre>
+
+<h3><a name="microedition">Preverifying class files for Java Micro Edition</a></h3>
+
+Even if you're not interested in shrinking, optimizing, and obfuscating your
+midlets, as shown in the <a href="#midlets">midlets example</a>, you can still
+use ProGuard to preverify the class files for Java Micro Edition. ProGuard
+produces slightly more compact results than the traditional external
+preverifier.
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/midpapi20.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/cldcapi11.jar
+
+-dontshrink
+-dontoptimize
+-dontobfuscate
+
+-microedition
+</pre>
+<p>
+We're not processing the input, just making sure the class files are
+preverified by targeting them at Java Micro Edition with the <a
+href="usage.html#microedition"><code>-microedition</code></a> option. Note
+that we don't need any <code>-keep</code> options to specify entry points; all
+class files are simply preverified.
+
+<h3><a name="upgrade">Upgrading class files to Java 6</a></h3>
+
+The following options upgrade class files to Java 6, by updating their
+internal version numbers and preverifying them. The class files can then be
+loaded more efficiently by the Java 6 Virtual Machine.
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+
+-dontshrink
+-dontoptimize
+-dontobfuscate
+
+-target 1.6
+</pre>
+<p>
+We're not processing the input, just retargeting the class files with the <a
+href="usage.html#target"><code>-target</code></a> option. They will
+automatically be preverified for Java 6 as a result. Note that we don't need
+any <code>-keep</code> options to specify entry points; all class files are
+simply updated and preverified.
+
+<h3><a name="deadcode">Finding dead code</a></h3>
+
+These options list unused classes, fields, and methods in the application
+<code>mypackage.MyApplication</code>:
+<pre>
+-injars in.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+
+-dontoptimize
+-dontobfuscate
+-dontpreverify
+-printusage
+
+-keep public class mypackage.MyApplication {
+ public static void main(java.lang.String[]);
+}
+</pre>
+<p>
+We're not specifying an output jar, just printing out some results. We're
+saving some processing time by skipping the other processing steps.
+<p>
+The java compiler inlines primitive constants and String constants
+(<code>static final</code> fields). ProGuard would therefore list such fields
+as not being used in the class files that it analyzes, even if they <i>are</i>
+used in the source files. We can add a <a
+href="usage.html#keepclassmembers"><code>-keepclassmembers</code></a> option
+that keeps those fields a priori, in order to avoid having them listed:
+<pre>
+-keepclassmembers class * {
+ static final % *;
+ static final java.lang.String *;
+}
+</pre>
+
+<h3><a name="structure">Printing out the internal structure of class files</a></h3>
+
+These options print out the internal structure of all class files in the input
+jar:
+<pre>
+-injars in.jar
+
+-dontshrink
+-dontoptimize
+-dontobfuscate
+-dontpreverify
+
+-dump
+</pre>
+<p>
+Note how we don't need to specify the Java run-time jar, because we're not
+processing the input jar at all.
+
+<h3><a name="annotated">Using annotations to configure ProGuard</a></h3>
+
+The traditional ProGuard configuration allows to keep a clean separation
+between the code and the configuration for shrinking, optimization, and
+obfuscation. However, it is also possible to define specific annotations,
+and then annotate the code to configure the processing.
+<p>
+You can find a set of such predefined annotations in the directory
+<code>examples/annotations/lib</code> in the ProGuard distribution.
+The annotation classes are defined in <code>annotations.jar</code>. The
+corresponding ProGuard configuration (or meta-configuration, if you prefer)
+is specified in <code>annotations.pro</code>. With these files, you can start
+annotating your code. For instance, a java source file
+<code>Application.java</code> can be annotated as follows:
+<pre>
+@KeepApplication
+public class Application {
+ ....
+}
+</pre>
+<p>
+The ProGuard configuration file for the application can then be simplified by
+leveraging off these annotations:
+<pre>
+-injars in.jar
+-outjars out.jar
+-libraryjars &lt;java.home&gt;/lib/rt.jar
+
+-include lib/annotations.pro
+</pre>
+<p>
+The annotations are effectively replacing the application-dependent
+<code>-keep</code> options. You may still wish to add traditional
+<code>-keep</code> options for processing <a href="#native">native
+methods</a>, <a href="#enumerations">enumerations</a>, <a
+href="#serializable">serializable classes</a>, and <a
+href="#annotations">annotations</a>.
+<p>
+The directory <code>examples/annotations</code> contains more examples that
+illustrate some of the possibilities.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/gradle.html b/third_party/java/proguard/proguard5.3.3/docs/manual/gradle.html
new file mode 100644
index 0000000000..55b00027af
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/gradle.html
@@ -0,0 +1,561 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>Gradle Task</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/gradle.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/gradle.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Gradle Task</h2>
+
+<b>ProGuard</b> can be run as a task in the Java-based build tool Gradle
+(version 2.1 or higher).
+<p>
+
+Before you can use the <code>proguard</code> task, you have to make sure
+Gradle can find it in its class path at build time. One way is to add the
+following line to your <code>build.gradle</code> file:
+<p>
+
+<pre>
+buildscript {
+ repositories {
+ flatDir dirs: '/usr/local/java/proguard/lib'
+ }
+ dependencies {
+ classpath ':proguard:'
+ }
+}
+</pre>
+<p>
+
+Please make sure the class path is set correctly for your system.
+<p>
+
+You can then define a task:
+<p>
+<pre>
+task myProguardTask(type: proguard.gradle.ProGuardTask) {
+ .....
+}
+</pre>
+<p>
+
+The embedded configuration is much like a standard ProGuard configuration.
+Notable similarities and differences:
+<ul>
+<li>Like in ProGuard-style configurations, we're using all lower-case names
+ for the settings.</li>
+<li>The options don't have a dash as prefix.</li>
+<li>Arguments typically have quotes.</li>
+<li>Some settings are specified as named arguments.</li>
+</ul>
+<p>
+You can find some sample build files in the <code>examples/gradle</code>
+directory of the ProGuard distribution.
+<p>
+If you prefer a more verbose configuration derived from the Ant task, you can
+import the Ant task as a <a href="#anttask">Gradle task</a>.
+
+<h2><a name="proguard">Settings</a></h2>
+
+The ProGuard task supports the following settings in its closure:
+
+<dl>
+
+<dt><a name="configuration_attribute"><code><b>configuration</b></code></a>
+ <a href="#file"><i>files</i></a></dt>
+<dd>Read and merge options from the given ProGuard-style configuration
+ files. The files are resolved and parsed lazily, during the execution
+ phase.</dd>
+
+<dt><a href="usage.html#injars"><code><b>injars</b></code></a>
+ <a href="#classpath"><i>class_path</i></a></dt>
+<dd>Specifies the program jars (or aars, wars, ears, zips, apks, or
+ directories). The files are resolved and read lazily, during the execution
+ phase.</dd>
+
+<dt><a href="usage.html#outjars"><code><b>outjars</b></code></a>
+ <a href="#classpath"><i>class_path</i></a></dt>
+<dd>Specifies the names of the output jars (or aars, wars, ears, zips, apks, or
+ directories). The files are resolved and written lazily, during the
+ execution phase.</dd>
+
+<dt><a href="usage.html#libraryjars"><code><b>libraryjars</b></code></a>
+ <a href="#classpath"><i>class_path</i></a></dt>
+<dd>Specifies the library jars (or aars, wars, ears, zips, apks, or
+ directories). The files are resolved and read lazily, during the execution
+ phase.</dd>
+
+<dt><a href="usage.html#skipnonpubliclibraryclasses"><code><b>skipnonpubliclibraryclasses</b></code></a></dt>
+<dd>Ignore non-public library classes.</dd>
+
+<dt><a href="usage.html#dontskipnonpubliclibraryclassmembers"><code><b>dontskipnonpubliclibraryclassmembers</b></code></a></dt>
+<dd>Don't ignore package visible library class members.</dd>
+
+<dt><a href="usage.html#keepdirectories"><code><b>keepdirectories</b></code></a>
+ ['<a href="usage.html#filefilters"><i>directory_filter</i></a>']</dt>
+<dd>Keep the specified directories in the output jars (or aars, wars, ears,
+ zips, apks, or directories).</dd>
+
+<dt><a href="usage.html#target"><code><b>target</b></code></a>
+ '<i>version</i>'</dt>
+<dd>Set the given version number in the processed classes.</dd>
+
+<dt><a href="usage.html#forceprocessing"><code><b>forceprocessing</b></code></a></dt>
+<dd>Process the input, even if the output seems up to date.</dd>
+
+<dt><a href="usage.html#keep"><code><b>keep</b></code></a>
+ [<a href="#keepmodifier"><i>modifier</i>,...</a>]
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the specified classes <i>and</i> class members.</dd>
+
+<dt><a href="usage.html#keepclassmembers"><code><b>keepclassmembers</b></code></a>
+ [<a href="#keepmodifier"><i>modifier</i>,...</a>]
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the specified class members, if their classes are preserved as
+ well.</dd>
+
+<dt><a href="usage.html#keepclasseswithmembers"><code><b>keepclasseswithmembers</b></code></a>
+ [<a href="#keepmodifier"><i>modifier</i>,...</a>]
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the specified classes <i>and</i> class members, if all of the
+ specified class members are present.</dd>
+
+<dt><a href="usage.html#keepnames"><code><b>keepnames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the names of the specified classes <i>and</i> class members (if
+ they aren't removed in the shrinking step).</dd>
+
+<dt><a href="usage.html#keepclassmembernames"><code><b>keepclassmembernames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the names of the specified class members (if they aren't removed
+ in the shrinking step).</dd>
+
+<dt><a href="usage.html#keepclasseswithmembernames"><code><b>keepclasseswithmembernames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Preserve the names of the specified classes <i>and</i> class members, if
+ all of the specified class members are present (after the shrinking
+ step).</dd>
+
+<dt><a href="usage.html#printseeds"><code><b>printseeds</b></code></a>
+ [<a href="#file"><i>file</i></a>]</dt>
+<dd>List classes and class members matched by the various <code>keep</code>
+ commands, to the standard output or to the given file.</dd>
+
+<dt><a href="usage.html#dontshrink"><code><b>dontshrink</b></code></a></dt>
+<dd>Don't shrink the input class files.</dd>
+
+<dt><a href="usage.html#printusage"><code><b>printusage</b></code></a>
+ [<a href="#file"><i>file</i></a>]</dt>
+<dd>List dead code of the input class files, to the standard output or to the
+ given file.</dd>
+
+<dt><a href="usage.html#whyareyoukeeping"><code><b>whyareyoukeeping</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Print details on why the given classes and class members are being kept in
+ the shrinking step.</dd>
+
+<dt><a href="usage.html#dontoptimize"><code><b>dontoptimize</b></code></a></dt>
+<dd>Don't optimize the input class files.</dd>
+
+<dt><a href="usage.html#optimizations"><code><b>optimizations</b></code></a> '<a href="optimizations.html"><i>optimization_filter</i></a>'</dt>
+<dd>Perform only the specified optimizations.</dd>
+
+<dt><a href="usage.html#optimizationpasses"><code><b>optimizationpasses</b></code></a>
+ <i>n</i></dt>
+<dd>The number of optimization passes to be performed.</dd>
+
+<dt><a href="usage.html#assumenosideeffects"><code><b>assumenosideeffects</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+<dd>Assume that the specified methods don't have any side effects, while
+ optimizing. <i>Only use this option if you know what you're
+ doing!</i></dd>
+
+<dt><a href="usage.html#allowaccessmodification"><code><b>allowaccessmodification</b></code></a></dt>
+<dd>Allow the access modifiers of classes and class members to be modified,
+ while optimizing.</dd>
+
+<dt><a href="usage.html#mergeinterfacesaggressively"><code><b>mergeinterfacesaggressively</b></code></a></dt>
+<dd>Allow any interfaces to be merged, while optimizing.</dd>
+
+<dt><a href="usage.html#dontobfuscate"><code><b>dontobfuscate</b></code></a></dt>
+<dd>Don't obfuscate the input class files.</dd>
+
+<dt><a href="usage.html#printmapping"><code><b>printmapping</b></code></a>
+ [<a href="#file"><i>file</i></a>]</dt>
+<dd>Print the mapping from old names to new names for classes and class members
+ that have been renamed, to the standard output or to the given file.</dd>
+
+<dt><a href="usage.html#applymapping"><code><b>applymapping</b></code></a>
+ <a href="#file"><i>file</i></a></dt>
+<dd>Reuse the given mapping, for incremental obfuscation.</dd>
+
+<dt><a href="usage.html#obfuscationdictionary"><code><b>obfuscationdictionary</b></code></a>
+ <a href="#file"><i>file</i></a></dt>
+<dd>Use the words in the given text file as obfuscated field names and method
+ names.</dd>
+
+<dt><a href="usage.html#classobfuscationdictionary"><code><b>classobfuscationdictionary</b></code></a>
+ <a href="#file"><i>file</i></a></dt>
+<dd>Use the words in the given text file as obfuscated class names.</dd>
+
+<dt><a href="usage.html#packageobfuscationdictionary"><code><b>packageobfuscationdictionary</b></code></a>
+ <a href="#file"><i>file</i></a></dt>
+<dd>Use the words in the given text file as obfuscated package names.</dd>
+
+<dt><a href="usage.html#overloadaggressively"><code><b>overloadaggressively</b></code></a></dt>
+<dd>Apply aggressive overloading while obfuscating.</dd>
+
+<dt><a href="usage.html#useuniqueclassmembernames"><code><b>useuniqueclassmembernames</b></code></a></dt>
+<dd>Ensure uniform obfuscated class member names for subsequent incremental
+ obfuscation.</dd>
+
+<dt><a href="usage.html#dontusemixedcaseclassnames"><code><b>dontusemixedcaseclassnames</b></code></a></dt>
+<dd>Don't generate mixed-case class names while obfuscating.</dd>
+
+<dt><a href="usage.html#keeppackagenames"><code><b>keeppackagenames</b></code></a> ['<a href="usage.html#filters"><i>package_filter</i></a>']</dt>
+<dd>Keep the specified package names from being obfuscated. If no name is
+ given, all package names are preserved.</dd>
+
+<dt><a href="usage.html#flattenpackagehierarchy"><code><b>flattenpackagehierarchy</b></code></a>
+ '<i>package_name</i>'</dt>
+<dd>Repackage all packages that are renamed into the single given parent
+ package.</dd>
+
+<dt><a href="usage.html#repackageclasses"><code><b>repackageclasses</b></code></a>
+ ['<i>package_name</i>']</dt>
+<dd>Repackage all class files that are renamed into the single given
+ package.</dd>
+
+<dt><a href="usage.html#keepattributes"><code><b>keepattributes</b></code></a> ['<a href="usage.html#filters"><i>attribute_filter</i></a>']</dt>
+<dd>Preserve the specified optional Java bytecode attributes, with optional
+ wildcards. If no name is given, all attributes are preserved.</dd>
+
+<dt><a href="usage.html#keepparameternames"><code><b>keepparameternames</b></code></a></dt>
+<dd>Keep the parameter names and types of methods that are kept.</dd>
+
+<dt><a href="usage.html#renamesourcefileattribute"><code><b>renamesourcefileattribute</b></code></a>
+ ['<i>string</i>']</dt>
+<dd>Put the given constant string in the <code>SourceFile</code>
+ attributes.</dd>
+
+<dt><a href="usage.html#adaptclassstrings"><code><b>adaptclassstrings</b></code></a>
+ ['<a href="usage.html#filters"><i>class_filter</i></a>']</dt>
+<dd>Adapt string constants in the specified classes, based on the obfuscated
+ names of any corresponding classes.</dd>
+
+<dt><a href="usage.html#adaptresourcefilenames"><code><b>adaptresourcefilenames</b></code></a>
+ ['<a href="usage.html#filefilters"><i>file_filter</i></a>']</dt>
+<dd>Rename the specified resource files, based on the obfuscated names of the
+ corresponding class files.</dd>
+
+<dt><a href="usage.html#adaptresourcefilecontents"><code><b>adaptresourcefilecontents</b></code></a>
+ ['<a href="usage.html#filefilters"><i>file_filter</i></a>']</dt>
+<dd>Update the contents of the specified resource files, based on the
+ obfuscated names of the processed classes.</dd>
+
+<dt><a href="usage.html#dontpreverify"><code><b>dontpreverify</b></code></a></dt>
+<dd>Don't preverify the processed class files if they are targeted at Java Micro
+ Edition or at Java 6 or higher.</dd>
+
+<dt><a href="usage.html#microedition"><code><b>microedition</b></code></a></dt>
+<dd>Target the processed class files at Java Micro Edition.</dd>
+
+<dt><a href="usage.html#verbose"><code><b>verbose</b></code></a></dt>
+<dd>Write out some more information during processing.</dd>
+
+<dt><a href="usage.html#dontnote"><code><b>dontnote</b></code></a> '<a href="usage.html#filters"><i>class_filter</i></a>'</dt>
+<dd>Don't print notes about classes matching the specified class name
+ filter.</dd>
+
+<dt><a href="usage.html#dontwarn"><code><b>dontwarn</b></code></a> '<a href="usage.html#filters"><i>class_filter</i></a>'</dt>
+<dd>Don't print warnings about classes matching the specified class name
+ filter. <i>Only use this option if you know what you're doing!</i></dd>
+
+<dt><a href="usage.html#ignorewarnings"><code><b>ignorewarnings</b></code></a></dt>
+<dd>Print warnings about unresolved references, but continue processing
+ anyhow. <i>Only use this option if you know what you're doing!</i></dd>
+
+<dt><a href="usage.html#printconfiguration"><code><b>printconfiguration</b></code></a>
+ [<a href="#file"><i>file</i></a>]</dt>
+<dd>Write out the entire configuration in traditional ProGuard style, to the
+ standard output or to the given file. Useful to replace unreadable
+ XML configurations.</dd>
+
+<dt><a href="usage.html#dump"><code><b>dump</b></code></a>
+ [<a href="#file"><i>file</i></a>]</dt>
+<dd>Write out the internal structure of the processed class files, to the
+ standard output or to the given file.</dd>
+
+</dl>
+
+<h2><a name="classpath">Class Paths</a></h2>
+
+Class paths are specified as Gradle file collections, which means they can be
+specified as simple strings, with <code>files(Object)</code>, etc.
+<p>
+In addition, they can have ProGuard-style filters, specified as
+comma-separated named arguments after the file:
+
+<dl>
+
+<dt><code><b>filter:</b></code>
+ '<a href="usage.html#filefilters"><i>file_filter</i></a>'</dt>
+<dd>An optional filter for all class file names and resource file names that
+ are encountered.</dd>
+
+<dt><code><b>apkfilter:</b></code>
+ '<a href="usage.html#filefilters"><i>file_filter</i></a>'</dt>
+<dd>An optional filter for all apk names that are encountered.</dd>
+
+<dt><code><b>jarfilter:</b></code>
+ '<a href="usage.html#filefilters"><i>file_filter</i></a>'</dt>
+<dd>An optional filter for all jar names that are encountered.</dd>
+
+<dt><code><b>aarfilter:</b></code>
+ '<a href="usage.html#filefilters"><i>file_filter</i></a>'</dt>
+<dd>An optional filter for all aar names that are encountered.</dd>
+
+<dt><code><b>warfilter:</b></code>
+ '<a href="usage.html#filefilters"><i>file_filter</i></a>'</dt>
+<dd>An optional filter for all war names that are encountered.</dd>
+
+<dt><code><b>earfilter:</b></code>
+ '<a href="usage.html#filefilters"><i>file_filter</i></a>'</dt>
+<dd>An optional filter for all ear names that are encountered.</dd>
+
+<dt><code><b>zipfilter:</b></code>
+ '<a href="usage.html#filefilters"><i>file_filter</i></a>'</dt>
+<dd>An optional filter for all zip names that are encountered.</dd>
+
+</dl>
+
+<h2><a name="file">Files</a></h2>
+
+Files are specified as Gradle files, which means they can be specified
+as simple strings, as File instances, with <code>file(Object)</code>, etc.
+<p>
+In Gradle, file names (any strings really) in double quotes can contain
+properties or code inside <code>${...}</code>. These are automatically
+expanded.
+<p>
+For example, <code>"${System.getProperty('java.home')}/lib/rt.jar"</code> is
+expanded to something like <code>'/usr/local/java/jdk/jre/lib/rt.jar'</code>.
+Similarly, <code>System.getProperty('user.home')</code> is expanded to the
+user's home directory, and <code>System.getProperty('user.dir')</code> is
+expanded to the current working directory.
+
+<h2><a name="keepmodifier">Keep Modifiers</a></h2>
+
+The keep settings can have the following named arguments that modify their
+behaviors:
+
+<dl>
+
+<dt><a href="usage.html#includedescriptorclasses"><code><b>includedescriptorclasses:</b></code></a>
+ <i>boolean</i>
+ (default = false)</dt>
+<dd>Specifies whether the classes of the fields and methods specified in the
+ keep tag must be kept as well.</dd>
+
+<dt><a href="usage.html#allowshrinking"><code><b>allowshrinking:</b></code></a>
+ <i>boolean</i>
+ (default = false)</dt>
+<dd>Specifies whether the entry points specified in the keep tag may be
+ shrunk.</dd>
+
+<dt><a href="usage.html#allowoptimization"><code><b>allowoptimization:</b></code></a>
+ <i>boolean</i>
+ (default = false)</dt>
+<dd>Specifies whether the entry points specified in the keep tag may be
+ optimized.</dd>
+
+<dt><a href="usage.html#allowobfuscation"><code><b>allowobfuscation:</b></code></a>
+ <i>boolean</i>
+ (default = false)</dt>
+<dd>Specifies whether the entry points specified in the keep tag may be
+ obfuscated.</dd>
+
+</dl>
+
+Names arguments are comma-separated, as usual.
+
+<h2><a name="classspecification">Class Specifications</a></h2>
+
+A class specification is a template of classes and class members (fields and methods). There are two alternative ways to specify such a template:
+
+<ol>
+<li>As a string containing a ProGuard-style class specification. This is the
+ most compact and most readable way. The specification looks like a Java
+ declaration of a class with fields and methods. For example:
+<pre>
+keep 'public class mypackage.MyMainClass { \
+ public static void main(java.lang.String[]); \
+}'
+</pre></li>
+<li>As a Gradle-style setting: a method calls with named arguments and a
+ closure. This is more verbose, but it might be useful for programmatic
+ specifications. For example:
+<pre>
+keep access: 'public',
+ name: 'mypackage.MyMainClass', {
+ method access: 'public static',
+ type: 'void',
+ name: 'main',
+ parameters: 'java.lang.String[]'
+}
+</pre></li>
+</ol>
+<p>
+
+The <a href="usage.html#classspecification">ProGuard-style class
+specification</a> is described on the traditional Usage page.
+<p>
+A Gradle-style class specification can have the following named arguments:
+
+<dl>
+
+<dt><code><b>access:</b></code> '<i>access_modifiers</i>'</dt>
+<dd>The optional access modifiers of the class. Any space-separated list of
+ "public", "final", and "abstract", with optional negators "!".</dd>
+
+<dt><code><b>annotation:</b></code> '<i>annotation_name</i>'</dt>
+<dd>The optional fully qualified name of an annotation of the class, with
+ optional wildcards.</dd>
+
+<dt><code><b>type:</b></code> '<i>type</i>'</dt>
+<dd>The optional type of the class: one of "class", "interface", or
+ "!interface".</dd>
+
+<dt><code><b>name:</b></code> '<i>class_name</i>'</dt>
+<dd>The optional fully qualified name of the class, with optional
+ wildcards.</dd>
+
+<dt><code><b>extendsannotation:</b></code> '<i>annotation_name</i>'</dt>
+<dd>The optional fully qualified name of an annotation of the the class that
+ the specified classes must extend, with optional wildcards.</dd>
+
+<dt><code><b>'extends':</b></code> '<i>class_name</i>'</dt>
+<dd>The optional fully qualified name of the class the specified classes
+ must extend, with optional wildcards.</dd>
+
+<dt><code><b>'implements':</b></code> '<i>class_name</i>'</dt>
+<dd>The optional fully qualified name of the class the specified classes
+ must implement, with optional wildcards.</dd>
+
+</dl>
+
+The named arguments are optional. Without any arguments, there are no
+constraints, so the settings match all classes.
+<p>
+
+<h3><a name="classmemberspecification">Gradle-style Class Member Specifications</a></h3>
+
+The closure of a Gradle-style class specification can specify class members
+with these settings:
+
+<dl>
+
+<dt><code><b>field</b></code> <i>field_constraints</i></dt>
+<dd>Specifies a field.</dd>
+
+<dt><code><b>method</b></code> <i>method_constraints</i></dt>
+<dd>Specifies a method.</dd>
+
+<dt><code><b>constructor</b></code> <i>constructor_constraints</i></dt>
+<dd>Specifies a constructor.</dd>
+
+</dl>
+
+A class member setting can have the following named arguments to express
+constraints:
+
+<dl>
+
+<dt><code><b>access:</b></code> '<i>access_modifiers</i>'</dt>
+<dd>The optional access modifiers of the class. Any space-separated list of
+ "public", "protected", "private", "static", etc., with optional negators
+ "!".</dd>
+
+<dt><code><b>'annotation':</b></code> '<i>annotation_name</i>'</dt>
+<dd>The optional fully qualified name of an annotation of the class member,
+ with optional wildcards.</dd>
+
+<dt><code><b>type:</b></code> '<i>type</i>'</dt>
+<dd>The optional fully qualified type of the class member, with optional
+ wildcards. Not applicable for constructors, but required for methods for
+ which the <code>parameters</code> argument is specified.</dd>
+
+<dt><code><b>name:</b></code> '<i>name</i>'</dt>
+<dd>The optional name of the class member, with optional wildcards. Not
+ applicable for constructors.</dd>
+
+<dt><code><b>parameters:</b></code> '<i>parameters</i>'</dt>
+<dd>The optional comma-separated list of fully qualified method parameters,
+ with optional wildcards. Not applicable for fields, but required for
+ constructors, and for methods for which the <code>type</code> argument is
+ specified.</dd>
+
+</dl>
+
+The named arguments are optional. Without any arguments, there are no
+constraints, so the settings match all constructors, fields, or methods.
+<p>
+A class member setting doesn't have a closure.
+
+<h2><a name="anttask">Alternative: imported Ant task</a></h2>
+
+Instead of using the Gradle task, you could also integrate the Ant task in
+your Gradle build file:
+<p>
+<pre>
+ant.project.basedir = '../..'
+
+ant.taskdef(resource: 'proguard/ant/task.properties',
+ classpath: '/usr/local/java/proguard/lib/proguard.jar')
+</pre>
+<p>
+
+Gradle automatically converts the elements and attributes to Groovy methods,
+so converting the configuration is essentially mechanical. The one-on-one
+mapping can be useful, but the resulting configuration is more verbose. For
+instance:
+<pre>
+task proguard << {
+ ant.proguard(printmapping: 'proguard.map',
+ overloadaggressively: 'on',
+ repackageclasses: '',
+ renamesourcefileattribute: 'SourceFile') {
+
+ injar(file: 'application.jar')
+ injar(file: 'gui.jar', filter: '!META-INF/**')
+
+ .....
+ }
+}
+</pre>
+<p>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/gui.html b/third_party/java/proguard/proguard5.3.3/docs/manual/gui.html
new file mode 100644
index 0000000000..3831370dae
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/gui.html
@@ -0,0 +1,483 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard GUI</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/gui.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/gui.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Graphical User Interface</h2>
+
+You can find the ProGuard GUI jar in the <code>lib</code> directory of the
+ProGuard distribution. To run the ProGuard graphical user interface, just type:
+<p class="code">
+<code><b>java -jar proguardgui.jar</b> [-nosplash] </code>[<i>configuration_file</i>]
+</p>
+Alternatively, the <code>bin</code> directory contains some short Linux and
+Windows scripts containing this command. The GUI will pop up in a window. With
+the <code>-nosplash</code> option, you can switch off the short opening
+animation. If you have specified a ProGuard configuration file, it will be
+loaded. The GUI works like a wizard. You can edit the configuration and
+execute ProGuard through a few tabs:
+<p>
+
+<table cellspacing="5" cellpadding="5">
+<tr><td class="button"><a href="#proguard">ProGuard</a></td>
+ <td>Optionally load an existing configuration file.</td></tr>
+<tr><td class="button"><a href="#inputoutput">Input/Output</a></td>
+ <td>Specify the program jars and library jars.</td></tr>
+<tr><td class="button"><a href="#shrinking">Shrinking</a></td>
+ <td>Specify the shrinking options.</td></tr>
+<tr><td class="button"><a href="#obfuscation">Obfuscation</a></td>
+ <td>Specify the obfuscation options.</td></tr>
+<tr><td class="button"><a href="#optimization">Optimization</a></td>
+ <td>Specify the optimization options.</td></tr>
+<tr><td class="button"><a href="#information">Information</a></td>
+ <td>Specify some options to get information.</td></tr>
+<tr><td class="button"><a href="#process">Process</a></td>
+ <td>View and save the resulting configuration, and run ProGuard.</td></tr>
+</table>
+<p>
+
+In addition, there is a tab to execute ReTrace interactively:
+<p>
+
+<table cellspacing="5" cellpadding="5">
+<tr><td class="button"><a href="#retrace">ReTrace</a></td>
+ <td>Set up and run ReTrace, to de-obfuscate stack traces.</td></tr>
+</table>
+<p>
+
+You can freely toggle between the tabs by means of the buttons on the
+left-hand side of the window, or by means of the <b>Previous</b> and
+<b>Next</b> buttons at the bottom of the tabs. Tool tips briefly explain the
+purpose of the numerous options and text fields, although a basic
+understanding of the shrinking/optimization/obfuscation/preverification
+process is assumed. Please refer to the <a
+href="introduction.html">Introduction</a> of this manual.
+<p>
+
+<h2><a name="proguard">The ProGuard Tab</a></h2>
+
+The <i>ProGuard</i> tab presents a welcome message and one important button at
+the bottom:
+<p>
+
+<table cellspacing="5" cellpadding="5">
+<tr><td class="button">Load configuration...</td>
+ <td>opens a file chooser to load an existing ProGuard configuration
+ file.</td></tr>
+</table>
+<p>
+
+If you don't want to load an existing configuration, you can just continue
+creating a new configuration from scratch.
+<p>
+
+<h2><a name="inputoutput">The Input/Output Tab</a></h2>
+
+The <i>Input/Output</i> tab contains two lists, respectively to specify the
+program jars (or aars, wars, ears, zips, apks, or directories), and the
+library jars (or aars, wars, ears, zips, apks, or directories).
+
+<ul>
+<li>The list of program jars contains input entries and output entries. Input
+ entries contain the class files and resource files to be processed. Output
+ entries specify the destinations to which the processed results will be
+ written. They are preceded by arrows, to distinguish them from input
+ entries. The results of each consecutive list of input entries will be
+ written to the subsequent consecutive list of output entries.</li>
+
+<li>The library jars are not copied to the output jars; they contain class
+ files that are used by class files in the program jars and that are
+ necessary for correct processing. This list typically at least contains the
+ targeted Java runtime jar.</li>
+</ul>
+<p>
+
+Each of these lists can be edited by means of a couple of buttons on the
+right-hand side:
+<p>
+
+<table cellspacing="5" cellpadding="5">
+<tr><td class="button">Add input...</td> <td>opens a file chooser to add an
+ input entry to the list of program jars.</td></tr>
+<tr><td class="button">Add output...</td> <td>opens a file chooser to add an
+ output entry to the list of program jars.</td></tr>
+<tr><td class="button">Add...</td>
+ <td>opens a file chooser to add an entry to the list of library
+ jars.</td></tr>
+<tr><td class="button">Edit...</td>
+ <td>opens a file chooser to edit the selected entry in the list.</td></tr>
+<tr><td class="button">Filter...</td>
+ <td>opens a text entry field to add or edit the filters of the selected
+ entries in the list.</td></tr>
+<tr><td class="button">Remove</td>
+ <td>removes the selected entries from the list.</td></tr>
+<tr><td class="button">Move up</td>
+ <td>moves the selected entries one position up the list.</td></tr>
+<tr><td class="button">Move down</td>
+ <td>moves the selected entries one position down the list.</td></tr>
+<tr><td class="button">Move to libraries</td>
+ <td>moves the selected entries in the list of program jars to the list of
+ library jars.</td></tr>
+<tr><td class="button">Move to program</td>
+ <td>moves the selected entries in the list of library jars to the list of
+ program jars.</td></tr>
+</table>
+<p>
+
+Filters allow to filter files based on their names. You can specify filters
+for class file names and resource file names, for jar file names, for aar file
+names, for war file names, for ear file names, for zip file names, and for
+apk file names. Multiple entries in the program list only make sense when
+combined with filters; each output file is written to the first entry with a
+matching filter.
+<p>
+
+Input entries that are currently not readable are colored red.
+<p>
+
+The order of the entries in each list may matter, as the first occurrence of
+any duplicate entries gets precedence, just as in conventional class paths.
+<p>
+
+Corresponding configuration options:
+<ul type="none">
+<li>-<a href="usage.html#injars">injars</a></li>
+<li>-<a href="usage.html#outjars">outjars</a></li>
+<li>-<a href="usage.html#libraryjars">libraryjars</a></li>
+<li><a href="usage.html#classpath"><i>class_path</i></a></li>
+<li><a href="usage.html#filters"><i>filters</i></a></li>
+</ul>
+<p>
+
+<h2><a name="shrinking">The Shrinking Tab</a></h2>
+
+The <i>Shrinking</i> tab presents a number of options that affect the
+shrinking step. The basic options are followed by a few lists of classes and
+class members (fields and methods) that must be protected from shrinking (and
+implicitly from obfuscation as well).
+<p>
+
+The fixed lists contain predefined entries that are typically useful for many
+applications. Each of these entries can be toggled by means of a check box.
+The text field following each entry allows to constrain the applicable classes
+by means of a comma-separated list of wildcarded, fully-qualified class
+names. The default is "*", which means that all input classes of the
+corresponding type are considered.
+<p>
+
+For example, checking the <b>Applications</b> entry and filling in
+"myapplications.**" after it would mean: keep all classes that have main
+methods in the "myapplications" package and all of its subpackages.
+<p>
+
+The variable list at the bottom allows to define additional entries
+yourself. The list can be edited by means of a couple of buttons on the
+right-hand side:
+<p>
+
+<table cellspacing="5" cellpadding="5">
+<tr><td class="button">Add...</td>
+ <td>opens a window to add a new entry to the list.</td></tr>
+<tr><td class="button">Edit...</td>
+ <td>opens a window to edit the selected entry in the list.</td></tr>
+<tr><td class="button">Remove</td>
+ <td>removes the selected entries from the list.</td></tr>
+<tr><td class="button">Move up</td>
+ <td>moves the selected entries one position up the list.</td></tr>
+<tr><td class="button">Move down</td>
+ <td>moves the selected entries one position down the list.</td></tr>
+</table>
+<p>
+
+The interface windows allow to specify classes, fields, and methods. They
+contain text fields and check boxes to constrain these items. They have
+<b>Ok</b> and <b>Cancel</b> buttons to apply or to cancel the operation.
+<p>
+
+For example, your application may be creating some classes dynamically using
+<code>Class.forName</code>. You should then specify them here, so they are kept
+by their original names. Press the <b>Add...</b> button to open the class
+window. Fill out the fully-qualified class name in the <b>Code</b> text field,
+and press the <b>Ok</b> button. Repeat this for all required classes. Wildcards
+can be helpful to specify a large number of related classes in one go. If you
+want to specify all implementations of a certain interface, fill out the
+fully qualified interface name in the <b>Extends/implements class</b> instead.
+<p>
+
+For more advanced settings, it is advisable to become familiar with ProGuard's
+configuration options through the <a href="usage.html">Usage section</a> and
+the <a href="examples.html">Examples section</a>. We'll suffice with a brief
+overview of the three dialogs provided by the GUI.
+<p>
+
+The <i>keep class</i> dialog appears when adding or editing new special keep
+entries. It has text fields and selections for specifying and constraining
+classes and class members to keep. The <b>Advanced options</b> / <b>Basic
+options</b> button at the bottom of the dialog allows to toggle showing the
+advanced options.
+
+<ul>
+<li>The <b>Comments</b> text field allows to add optional comments to this
+ entry. The comments will identify the entry in the list and they will
+ appear as comments in the configuration file.</li>
+
+<li>The <b>Keep</b> selection allows to specify whether you want to protect
+ the specified classes and their specified class members, or just the
+ specified class members from the specified classes, or the specified
+ classes and the specified class members, if the class members are present.
+ Note that class members will only be protected if they are explicitly
+ specified, even if only by means of a wildcard.</li>
+
+<li>The <b>Allow</b> selection allows to specify whether you want to allow the
+ the specified classes and their specified class members to be shrunk,
+ optimized and/or obfuscated.</li>
+
+<li>The <b>Access</b> selections allows to specify constraints on the class or
+ classes, based on their access modifiers.</li>
+
+<li>The <b>Annotation</b> text field takes the fully-qualified name of an
+ annotation that is required for matching classes. The annotation name can
+ contain wildcards. This is an advanced option for defining <i>keep</i>
+ annotations.</li>
+
+<li>The <b>Class</b> text field takes the fully-qualified name of the class or
+ classes. The class name can contain wildcards.</li>
+
+<li>The <b>Annotation</b> text field takes the fully-qualified name of an
+ annotation that is required for the class or interface that the above
+ class must extend. The annotation name can contain wildcards. This is an
+ advanced option for defining <i>keep</i> annotations.</li>
+
+<li>The <b>Extends/implements class</b> text field takes the fully-qualified
+ name of the class or interface that the above classes must extend.</li>
+
+<li>The <b>Class members</b> list allows to specify a list of fields and
+ methods to keep. It can be edited by means of a list of buttons on the
+ right-hand side.</li>
+</ul>
+<p>
+
+The <i>keep field</i> dialog appears when adding or editing fields within the
+above dialog. It has text fields and selections for specifying and
+constraining fields to keep. Again, the <b>Advanced options</b> / <b>Basic
+options</b> button at the bottom of the dialog allows to toggle showing the
+advanced options.
+
+<ul>
+<li>The <b>Access</b> selections allows to specify constraints on the field or
+ fields, based on their access modifiers.</li>
+
+<li>The <b>Annotation</b> text field takes the fully-qualified name of an
+ annotation that is required for matching fields. The annotation name can
+ contain wildcards. This is an advanced option for defining <i>keep</i>
+ annotations.</li>
+
+<li>The <b>Return type</b> text field takes the fully-qualified type of the
+ field or fields. The type can contain wildcards.</li>
+
+<li>The <b>Name</b> text field takes the name of the field or fields. The field
+ name can contain wildcards.</li>
+</ul>
+<p>
+
+Similarly, the <i>keep method</i> dialog appears when adding or editing
+methods within the keep class dialog. It has text fields and selections for
+specifying and constraining methods to keep. Again, the <b>Advanced
+options</b> / <b>Basic options</b> button at the bottom of the dialog allows
+to toggle showing the advanced options.
+
+<ul>
+<li>The <b>Access</b> selections allows to specify constraints on the method or
+ methods, based on their access modifiers.</li>
+
+<li>The <b>Annotation</b> text field takes the fully-qualified name of an
+ annotation that is required for matching methods. The annotation name can
+ contain wildcards. This is an advanced option for defining <i>keep</i>
+ annotations.</li>
+
+<li>The <b>Return type</b> text field takes the fully-qualified type of the method or methods. The type can contain wildcards.</li>
+
+<li>The <b>Name</b> text field takes the name of the method or methods. The
+ method name can contain wildcards.</li>
+
+<li>The <b>Arguments</b> text field takes the comma-separated list of
+ fully-qualified method arguments. Each of these arguments can contain
+ wildcards.</li>
+</ul>
+<p>
+
+Corresponding configuration options:
+<ul type="none">
+<li>-<a href="usage.html#dontshrink">dontshrink</a></li>
+<li>-<a href="usage.html#printusage">printusage</a></li>
+<li>-<a href="usage.html#keep">keep</a></li>
+<li>-<a href="usage.html#keepclassmembers">keepclassmembers</a></li>
+<li>-<a href="usage.html#keepclasseswithmembers">keepclasseswithmembers</a></li>
+</ul>
+<p>
+
+<h2><a name="obfuscation">The Obfuscation Tab</a></h2>
+
+The <i>Obfuscation</i> tab presents a number of options that affect the
+obfuscation step. The basic options are followed by a few lists of classes and
+class members (fields and methods) that must be protected from obfuscation
+(but not necessarily from shrinking).
+<p>
+
+The lists are manipulated in the same way as in the <a
+href="#shrinking">Shrinking Tab</a>.
+<p>
+
+Corresponding configuration options:
+<ul type="none">
+<li>-<a href="usage.html#dontobfuscate">dontobfuscate</a></li>
+<li>-<a href="usage.html#printmapping">printmapping</a></li>
+<li>-<a href="usage.html#applymapping">applymapping</a></li>
+<li>-<a href="usage.html#obfuscationdictionary">obfuscationdictionary</a></li>
+<li>-<a href="usage.html#classobfuscationdictionary">classobfuscationdictionary</a></li>
+<li>-<a href="usage.html#packageobfuscationdictionary">packageobfuscationdictionary</a></li>
+<li>-<a href="usage.html#overloadaggressively">overloadaggressively</a></li>
+<li>-<a href="usage.html#useuniqueclassmembernames">useuniqueclassmembernames</a></li>
+<li>-<a href="usage.html#dontusemixedcaseclassnames">dontusemixedcaseclassnames</a></li>
+<li>-<a href="usage.html#keeppackagenames">keeppackagenames</a></li>
+<li>-<a href="usage.html#flattenpackagehierarchy">flattenpackagehierarchy</a></li>
+<li>-<a href="usage.html#repackageclasses">repackageclasses</a></li>
+<li>-<a href="usage.html#keepattributes">keepattributes</a></li>
+<li>-<a href="usage.html#keepparameternames">keepparameternames</a></li>
+<li>-<a href="usage.html#renamesourcefileattribute">renamesourcefileattribute</a></li>
+<li>-<a href="usage.html#adaptclassstrings">adaptclassstrings</a></li>
+<li>-<a href="usage.html#adaptresourcefilenames">adaptresourcefilenames</a></li>
+<li>-<a href="usage.html#adaptresourcefilecontents">adaptresourcefilecontents</a></li>
+<li>-<a href="usage.html#keepnames">keepnames</a></li>
+<li>-<a href="usage.html#keepclassmembernames">keepclassmembernames</a></li>
+<li>-<a href="usage.html#keepclasseswithmembernames">keepclasseswithmembernames</a></li>
+<li><a href="usage.html#classspecification"><i>class_specification</i></a></li>
+</ul>
+<p>
+
+<h2><a name="optimization">The Optimization Tab</a></h2>
+
+The <i>Optimization</i> tab presents a number of options that affect the
+optimization step. The basic options are followed by a few lists of class
+method calls that can be removed if ProGuard can determine that their results
+are not being used.
+<p>
+
+The lists are manipulated in much the same way as in the <a
+href="#shrinking">Shrinking Tab</a>.
+<p>
+
+Corresponding configuration options:
+<ul type="none">
+<li>-<a href="usage.html#dontoptimize">dontoptimize</a></li>
+<li>-<a href="usage.html#optimizations">optimizations</a></li>
+<li>-<a href="usage.html#optimizationpasses">optimizationpasses</a></li>
+<li>-<a href="usage.html#allowaccessmodification">allowaccessmodification</a></li>
+<li>-<a href="usage.html#mergeinterfacesaggressively">mergeinterfacesaggressively</a></li>
+<li>-<a href="usage.html#assumenosideeffects">assumenosideeffects</a></li>
+<li><a href="usage.html#classspecification"><i>class_specification</i></a></li>
+</ul>
+<p>
+
+<h2><a name="information">The Information Tab</a></h2>
+
+The <i>Information</i> tab presents a number of options for preverification
+and targeting, and for the information that ProGuard returns when processing
+your code. The bottom list allows you to query ProGuard about why given
+classes and class members are being kept in the shrinking step.
+<p>
+
+Corresponding configuration options:
+<ul type="none">
+<li>-<a href="usage.html#dontpreverify">dontpreverify</a></li>
+<li>-<a href="usage.html#microedition">microedition</a></li>
+<li>-<a href="usage.html#target">target</a></li>
+<li>-<a href="usage.html#verbose">verbose</a></li>
+<li>-<a href="usage.html#dontnote">dontnote</a></li>
+<li>-<a href="usage.html#dontwarn">dontwarn</a></li>
+<li>-<a href="usage.html#ignorewarnings">ignorewarnings</a></li>
+<li>-<a href="usage.html#skipnonpubliclibraryclasses">skipnonpubliclibraryclasses</a></li>
+<li>-<a href="usage.html#dontskipnonpubliclibraryclasses">dontskipnonpubliclibraryclasses</a></li>
+<li>-<a href="usage.html#dontskipnonpubliclibraryclassmembers">dontskipnonpubliclibraryclassmembers</a></li>
+<li>-<a href="usage.html#keepdirectories">keepdirectories</a></li>
+<li>-<a href="usage.html#forceprocessing">forceprocessing</a></li>
+<li>-<a href="usage.html#printseeds">printseeds</a></li>
+<li>-<a href="usage.html#printconfiguration">printconfiguration</a></li>
+<li>-<a href="usage.html#dump">dump</a></li>
+<li>-<a href="usage.html#whyareyoukeeping">whyareyoukeeping</a></li>
+</ul>
+<p>
+
+<h2><a name="process">The Process Tab</a></h2>
+
+The <i>Process</i> tab has an output console for displaying the configuration
+and the messages while processing. There are three important buttons at the
+bottom:
+<p>
+
+<table cellspacing="5" cellpadding="5">
+<tr><td class="button">View configuration</td>
+ <td>displays the current ProGuard configuration in the console.</td></tr>
+<tr><td class="button">Save configuration...</td>
+ <td>opens a file chooser to save the current ProGuard
+ configuration.</td></tr>
+<tr><td class="button">Process!</td>
+ <td>executes ProGuard with the current configuration.</td></tr>
+</table>
+<p>
+
+<h2><a name="retrace">The ReTrace Tab</a></h2>
+
+The <i>ReTrace</i> tab has a panel with a few settings, an input text area for
+the obfuscated stack trace, and an output console to view the de-obfuscated
+stack trace:
+
+<ul>
+<li>The <b>Verbose</b> check box in the settings panel allows to toggle between
+ normal mode and verbose mode.</li>
+
+<li>The <b>Mapping file</b> text field takes the name of the required mapping
+ file that ProGuard wrote while processing the original code. The file name
+ can be entered manually or by means of the <b>Browse...</b> button that
+ opens a file chooser.</li>
+
+<li>The <b>Obfuscated stack trace</b> text area allows to enter the stack
+ trace, typically by copying and pasting it from elsewhere. Alternatively,
+ it can be loaded from a file by means of the load button below.</li>
+</ul>
+
+There are two buttons at the bottom:
+<p>
+
+<table cellspacing="5" cellpadding="5">
+<tr><td class="button">Load stack trace...</td>
+ <td>opens a file chooser to load an obfuscated stack trace.</td></tr>
+<tr><td class="button">ReTrace!</td>
+ <td>executes ReTrace with the current settings.</td></tr>
+</table>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/index.html b/third_party/java/proguard/proguard5.3.3/docs/manual/index.html
new file mode 100644
index 0000000000..8bf62eb5f0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/index.html
@@ -0,0 +1,41 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Manual</title>
+</head>
+<body>
+
+<h2>ProGuard</h2>
+
+<ol>
+<li><a href="introduction.html">Introduction</a></li>
+<li><a href="usage.html">Usage</a></li>
+<li><a href="limitations.html">Limitations</a></li>
+<li><a href="examples.html">Examples</a></li>
+<li><a href="troubleshooting.html">Troubleshooting</a></li>
+<li><a href="refcard.html">Reference Card</a></li>
+<li><a href="gui.html">Graphical User Interface</a></li>
+<li><a href="ant.html">Ant Task</a></li>
+<li><a href="gradle.html">Gradle Task</a></li>
+<li><a href="wtk.html">JME Wireless Toolkit Integration</a></li>
+</ol>
+
+<h2>ReTrace</h2>
+
+<ol>
+<li><a href="retrace/introduction.html">Introduction</a></li>
+<li><a href="retrace/usage.html">Usage</a></li>
+<li><a href="retrace/examples.html">Examples</a></li>
+</ol>
+
+<hr />
+<noscript><div><a target="_top" href="../index.html" class="button">Show menu</a></div></noscript>
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/introduction.html b/third_party/java/proguard/proguard5.3.3/docs/manual/introduction.html
new file mode 100644
index 0000000000..f07e290e23
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/introduction.html
@@ -0,0 +1,173 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Introduction</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/introduction.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/introduction.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Introduction</h2>
+
+<b>ProGuard</b> is a Java class file shrinker, optimizer, obfuscator, and
+preverifier. The shrinking step detects and removes unused classes, fields,
+methods, and attributes. The optimization step analyzes and optimizes the
+bytecode of the methods. The obfuscation step renames the remaining classes,
+fields, and methods using short meaningless names. These first steps make the
+code base smaller, more efficient, and harder to reverse-engineer. The final
+preverification step adds preverification information to the classes, which is
+required for Java Micro Edition and for Java 6 and higher.
+<p>
+Each of these steps is optional. For instance, ProGuard can also be used to
+just list dead code in an application, or to preverify class files for
+efficient use in Java 6.
+<p>
+
+<table class="diagram" align="center">
+
+<tr>
+<td rowspan="4" class="lightblock">Input jars</td>
+<td colspan="8" class="transparentblock"></td>
+</tr>
+
+<tr>
+<td rowspan="2" class="transparentblock"></td>
+<td rowspan="3" class="lightblock">Shrunk code</td>
+<td colspan="6" class="transparentblock"></td>
+</tr>
+
+<tr>
+<td class="transparentblock"></td>
+<td rowspan="2" class="lightblock">Optim. code</td>
+<td colspan="3" class="transparentblock"></td>
+<td rowspan="2" class="lightblock">Output jars</td>
+</tr>
+
+<tr>
+<td class="transparentblock">- shrink &rarr;</td>
+<td class="transparentblock">- optimize &rarr;</td>
+<td class="transparentblock">- obfuscate &rarr;</td>
+<td class="lightblock">Obfusc. code</td>
+<td class="transparentblock">- preverify &rarr;</td>
+</tr>
+
+<tr>
+<td class="darkblock">Library jars</td>
+<td colspan="7" class="transparentblock">------------------------------- (unchanged) -------------------------------&rarr;</td>
+<td class="darkblock">Library jars</td>
+</tr>
+
+</table>
+<p>
+
+ProGuard first reads the <b>input jars</b> (or aars, wars, ears, zips, apks,
+or directories). It then subsequently shrinks, optimizes, obfuscates, and
+preverifies them. You can optionally let ProGuard perform multiple
+optimization passes. ProGuard writes the processed results to one or
+more <b>output jars</b> (or aars, wars, ears, zips, apks, or directories). The
+input may contain resource files, whose names and contents can optionally be
+updated to reflect the obfuscated class names.
+<p>
+ProGuard requires the <b>library jars</b> (or aars, wars, ears, zips, apks, or
+directories) of the input jars to be specified. These are essentially the
+libraries that you would need for compiling the code. ProGuard uses them to
+reconstruct the class dependencies that are necessary for proper processing.
+The library jars themselves always remain unchanged. You should still put them
+in the class path of your final application.
+
+<h3>Entry points</h3>
+
+In order to determine which code has to be preserved and which code can be
+discarded or obfuscated, you have to specify one or more <i>entry points</i> to
+your code. These entry points are typically classes with main methods, applets,
+midlets, activities, etc.
+<ul>
+<li>In the <b>shrinking step</b>, ProGuard starts from these seeds and
+ recursively determines which classes and class members are used. All other
+ classes and class members are discarded.</li>
+
+<li>In the <b>optimization step</b>, ProGuard further optimizes the code.
+ Among other optimizations, classes and methods that are not entry points
+ can be made private, static, or final, unused parameters can be removed,
+ and some methods may be inlined.</li>
+
+<li>In the <b>obfuscation step</b>, ProGuard renames classes and class members
+ that are not entry points. In this entire process, keeping the entry
+ points ensures that they can still be accessed by their original names.</li>
+
+<li>The <b>preverification step</b> is the only step that doesn't have to know
+ the entry points.</li>
+</ul>
+<p>
+The <a href="usage.html">Usage section</a> of this manual describes the
+necessary <a href="usage.html#keepoptions"><code>-keep</code> options</a> and
+the <a href="examples.html">Examples section</a> provides plenty of examples.
+
+<h3>Reflection</h3>
+
+Reflection and introspection present particular problems for any automatic
+processing of code. In ProGuard, classes or class members in your code that
+are created or invoked dynamically (that is, by name) have to be specified as
+entry points too. For example, <code>Class.forName()</code> constructs may
+refer to any class at run-time. It is generally impossible to compute which
+classes have to be preserved (with their original names), since the class
+names might be read from a configuration file, for instance. You therefore
+have to specify them in your ProGuard configuration, with the same
+simple <code>-keep</code> options.
+<p>
+However, ProGuard will already detect and handle the following cases for you:
+
+<ul>
+<li><code>Class.forName("SomeClass")</code></li>
+<li><code>SomeClass.class</code></li>
+<li><code>SomeClass.class.getField("someField")</code></li>
+<li><code>SomeClass.class.getDeclaredField("someField")</code></li>
+<li><code>SomeClass.class.getMethod("someMethod", new Class[] {})</code></li>
+<li><code>SomeClass.class.getMethod("someMethod", new Class[] { A.class })</code></li>
+<li><code>SomeClass.class.getMethod("someMethod", new Class[] { A.class, B.class })</code></li>
+<li><code>SomeClass.class.getDeclaredMethod("someMethod", new Class[] {})</code></li>
+<li><code>SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class })</code></li>
+<li><code>SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class, B.class })</code></li>
+<li><code>AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")</code></li>
+<li><code>AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")</code></li>
+<li><code>AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")</code></li>
+</ul>
+
+The names of the classes and class members may of course be different, but the
+constructs should be literally the same for ProGuard to recognize them. The
+referenced classes and class members are preserved in the shrinking phase, and
+the string arguments are properly updated in the obfuscation phase.
+<p>
+Furthermore, ProGuard will offer some suggestions if keeping some classes or
+class members appears necessary. For example, ProGuard will note constructs
+like "<code>(SomeClass)Class.forName(variable).newInstance()</code>". These
+might be an indication that the class or interface <code>SomeClass</code>
+and/or its implementations may need to be preserved. You can then adapt your
+configuration accordingly.
+<p>
+For proper results, you should at least be somewhat familiar with the code
+that you are processing. Obfuscating code that performs a lot of reflection
+may require trial and error, especially without the necessary information
+about the internals of the code.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/limitations.html b/third_party/java/proguard/proguard5.3.3/docs/manual/limitations.html
new file mode 100644
index 0000000000..a7769be0f7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/limitations.html
@@ -0,0 +1,63 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Limitations</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/limitations.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/limitations.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Limitations</h2>
+
+When using ProGuard, you should be aware of a few technical issues, all of
+which are easily avoided or resolved:
+<p>
+<ul class="spacious">
+
+<li>For best results, ProGuard's optimization algorithms assume that the
+ processed code never <b>intentionally throws NullPointerExceptions</b> or
+ ArrayIndexOutOfBoundsExceptions, or even OutOfMemoryErrors or
+ StackOverflowErrors, in order to achieve something useful. For instance,
+ it may remove a method call <code>myObject.myMethod()</code> if that call
+ wouldn't have any effect. It ignores the possibility that
+ <code>myObject</code> might be null, causing a NullPointerException. In
+ some way this is a good thing: optimized code may throw fewer exceptions.
+ Should this entire assumption be false, you'll have to switch off
+ optimization using the <code>-dontoptimize</code> option.</li>
+
+<li>ProGuard's optimization algorithms currently also assume that the
+ processed code never creates <b>busy-waiting loops</b> without at least
+ testing on a volatile field. Again, it may remove such loops. Should this
+ assumption be false, you'll have to switch off optimization using
+ the <code>-dontoptimize</code> option.</li>
+
+<li>When obfuscating, ProGuard writes out class files named
+ "<code>a.class</code>", "<code>b.class</code>", etc. If a package contains
+ a large number of classes, ProGuard may also write out
+ <b>"<code>aux.class</code>"</b>. Inconveniently, Windows refuses to create
+ files with this reserved name (among a few other names). It's generally
+ better to write the output to a jar, in order to avoid such problems.</li>
+
+</ul>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/optimizations.html b/third_party/java/proguard/proguard5.3.3/docs/manual/optimizations.html
new file mode 100644
index 0000000000..09270e2ca5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/optimizations.html
@@ -0,0 +1,202 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>Optimizations</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/optimizations.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/optimizations.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Optimizations</h2>
+
+The optimization step of ProGuard can be switched off with the
+<a href="usage.html#dontoptimize"><code>-dontoptimize</code></a> option. For
+more fine-grained control over individual optimizations, experts can use the
+<a href="usage.html#optimizations"><code>-optimizations</code></a> option,
+with a filter based on the optimization names listed below. The filter works
+like any <a href="usage.html#filters">filter</a> in ProGuard.
+<p>
+
+The following wildcards are supported:
+
+<table cellspacing="10">
+<tr><td valign="top"><code><b>?</b></code></td>
+ <td>matches any single character in an optimization name.</td></tr>
+<tr><td valign="top"><code><b>*</b></code></td>
+ <td>matches any part of an optimization name.</td></tr>
+</table>
+
+An optimization that is preceded by an exclamation mark '<b>!</b>' is
+<i>excluded</i> from further attempts to match with <i>subsequent</i>
+optimization names in the filter. Make sure to specify filters correctly,
+since they are not checked for potential typos.
+<p>
+
+For example,
+"<code>code/simplification/variable,code/simplification/arithmetic</code>"
+only performs the two specified peephole optimizations.
+<p>
+
+For example, "<code>!method/propagation/*</code>" performs all optimizations,
+except the ones that propagate values between methods.
+<p>
+
+For example,
+"<code>!code/simplification/advanced,code/simplification/*</code>" only
+performs all peephole optimizations.
+<p>
+Some optimizations necessarily imply other optimizations. These are then
+indicated. Note that the list is likely to change over time, as optimizations
+are added and reorganized.
+<p>
+
+<dl>
+<dt><code><b>class/marking/final</b></code></dt>
+<dd>Marks classes as final, whenever possible.</dd>
+
+<dt><code><b>class/unboxing/enum</b></code></dt>
+<dd>Simplifies enum types to integer constants, whenever possible.</dd>
+
+<dt><code><b>class/merging/vertical</b></code></dt>
+<dd>Merges classes vertically in the class hierarchy, whenever possible.</dd>
+
+<dt><code><b>class/merging/horizontal</b></code></dt>
+<dd>Merges classes horizontally in the class hierarchy, whenever possible.</dd>
+
+<dt><div>(&rArr; <code>code/removal/advanced</code>)</div>
+ <code><b>field/removal/writeonly</b></code></dt>
+<dd>Removes write-only fields.</dd>
+
+<dt><code><b>field/marking/private</b></code></dt>
+<dd>Marks fields as private, whenever possible.</dd>
+
+<dt><div>(&rArr; <code>code/simplification/advanced</code>)</div>
+ <code><b>field/propagation/value</b></code></dt>
+<dd>Propagates the values of fields across methods.</dd>
+
+<dt><code><b>method/marking/private</b></code></dt>
+<dd>Marks methods as private, whenever possible (<i>devirtualization</i>).</dd>
+
+<dt><div>(&rArr; <code>code/removal/advanced</code>)</div>
+ <code><b>method/marking/static</b></code></dt>
+<dd>Marks methods as static, whenever possible (<i>devirtualization</i>).</dd>
+
+<dt><code><b>method/marking/final</b></code></dt>
+<dd>Marks methods as final, whenever possible.</dd>
+
+<dt><div>(&rArr; <code>code/removal/advanced</code>)</div>
+ <code><b>method/removal/parameter</b></code></dt>
+<dd>Removes unused method parameters.</dd>
+
+<dt><div>(&rArr; <code>code/simplification/advanced</code>)</div>
+ <code><b>method/propagation/parameter</b></code></dt>
+<dd>Propagates the values of method parameters from method invocations to
+ the invoked methods.</dd>
+
+<dt><div>(&rArr; <code>code/simplification/advanced</code>)</div>
+ <code><b>method/propagation/returnvalue</b></code></dt>
+<dd>Propagates the values of method return values from methods to their
+ invocations.</dd>
+
+<dt><code><b>method/inlining/short</b></code></dt>
+<dd>Inlines short methods.</dd>
+
+<dt><code><b>method/inlining/unique</b></code></dt>
+<dd>Inlines methods that are only called once.</dd>
+
+<dt><code><b>method/inlining/tailrecursion</b></code></dt>
+<dd>Simplifies tail recursion calls, whenever possible.</dd>
+
+<dt><code><b>code/merging</b></code></dt>
+<dd>Merges identical blocks of code by modifying branch targets.</dd>
+
+<dt><code><b>code/simplification/variable</b></code></dt>
+<dd>Performs peephole optimizations for variable loading and storing.</dd>
+
+<dt><code><b>code/simplification/arithmetic</b></code></dt>
+<dd>Performs peephole optimizations for arithmetic instructions.</dd>
+
+<dt><code><b>code/simplification/cast</b></code></dt>
+<dd>Performs peephole optimizations for casting operations.</dd>
+
+<dt><code><b>code/simplification/field</b></code></dt>
+<dd>Performs peephole optimizations for field loading and storing.</dd>
+
+<dt><div>(&rArr; <code>code/removal/simple</code>)</div>
+ <code><b>code/simplification/branch</b></code></dt>
+<dd>Performs peephole optimizations for branch instructions.</dd>
+
+<dt><code><b>code/simplification/string</b></code></dt>
+<dd>Performs peephole optimizations for constant strings.</dd>
+
+<dt><div>(<i>best used with</i> <code>code/removal/advanced</code>)</div>
+ <code><b>code/simplification/advanced</b></code></dt>
+<dd>Simplifies code based on control flow analysis and data flow
+ analysis.</dd>
+
+<dt><div>(&rArr; <code>code/removal/exception</code>)</div>
+ <code><b>code/removal/advanced</b></code></dt>
+<dd>Removes dead code based on control flow analysis and data flow
+ analysis.</dd>
+
+<dt><div>(&rArr; <code>code/removal/exception</code>)</div>
+ <code><b>code/removal/simple</b></code></dt>
+<dd>Removes dead code based on a simple control flow analysis.</dd>
+
+<dt><code><b>code/removal/variable</b></code></dt>
+<dd>Removes unused variables from the local variable frame.</dd>
+
+<dt><code><b>code/removal/exception</b></code></dt>
+<dd>Removes exceptions with empty try blocks.</dd>
+
+<dt><code><b>code/allocation/variable</b></code></dt>
+<dd>Optimizes variable allocation on the local variable frame.</dd>
+</dl>
+<p>
+
+ProGuard also provides some unofficial settings to control optimizations, that
+may disappear in future versions. These are Java system properties, which
+can be set as JVM arguments (with <code>-D.....)</code>:
+<dl>
+<dt><code><b>maximum.inlined.code.length</b></code> (default = 8 bytes)</dt>
+<dd>Specifies the maximum code length (expressed in bytes) of short methods
+ that are eligible to be inlined. Inlining methods that are too long may
+ unnecessarily inflate the code size.</dd>
+
+<dt><code><b>maximum.resulting.code.length</b></code> (default = 8000 bytes
+ for JSE, 2000 bytes for JME)</dt>
+<dd>Specifies the maximum resulting code length (expressed in bytes) allowed
+ when inlining methods. Many Java virtual machines do not apply just-in-time
+ compilation to methods that are too long, so it's important not to let them
+ grow too large.</dd>
+
+<dt><code><b>optimize.conservatively</b></code> (default = unset)</dt>
+<dd>Allows input code with ordinary instructions intentionally throwing
+ <code>NullPointerException</code>,
+ <code>ArrayIndexOutOfBoundsException</code>, or
+ <code>ClassCastException</code>, without any other useful purposes. By
+ default, ProGuard may just discard such seemingly useless instructions,
+ resulting in better optimization of most common code.</dd>
+</dl>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/refcard.html b/third_party/java/proguard/proguard5.3.3/docs/manual/refcard.html
new file mode 100644
index 0000000000..0555c33204
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/refcard.html
@@ -0,0 +1,493 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Reference Card</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/refcard.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/refcard.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h1>ProGuard Reference Card</h1>
+
+<h2>Usage</h2>
+
+<code><b>java -jar proguard.jar </b></code><i>options</i> ...
+<p>
+&nbsp;&nbsp;Typically:
+<p>
+<code><b>java -jar proguard.jar @myconfig.pro</b></code>
+<p>
+
+<h2>Options</h2>
+
+<table cellspacing="10">
+
+<tr>
+<td valign="top"><a href="usage.html#at"><code><b>@</b></code></a><a href="usage.html#filename"><i>filename</i></a></td>
+
+<td>Short for '<code>-include</code> <i>filename</i>'.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#include"><code><b>-include</b></code></a>
+ <a href="usage.html#filename"><i>filename</i></a></td>
+
+<td>Read configuration options from the given file.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#basedirectory"><code><b>-basedirectory</b></code></a>
+ <a href="usage.html#filename"><i>directoryname</i></a></td>
+
+<td>Specifies the base directory for subsequent relative file names.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#injars"><code><b>-injars</b></code></a>
+ <a href="usage.html#classpath"><i>class_path</i></a></td>
+<td>Specifies the program jars (or wars, ears, zips, or directories).</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#outjars"><code><b>-outjars</b></code></a>
+ <a href="usage.html#classpath"><i>class_path</i></a></td>
+<td>Specifies the names of the output jars (or wars, ears, zips, or
+ directories).</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#libraryjars"><code><b>-libraryjars</b></code></a>
+ <a href="usage.html#classpath"><i>class_path</i></a></td>
+<td>Specifies the library jars (or wars, ears, zips, or directories).</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#skipnonpubliclibraryclasses"><code><b>-skipnonpubliclibraryclasses</b></code></a></td>
+<td>Ignore non-public library classes.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#dontskipnonpubliclibraryclasses"><code><b>-dontskipnonpubliclibraryclasses</b></code></a></td>
+<td>Don't ignore non-public library classes (the default).</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#dontskipnonpubliclibraryclassmembers"><code><b>-dontskipnonpubliclibraryclassmembers</b></code></a></td>
+<td>Don't ignore package visible library class members.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#keepdirectories"><code><b>-keepdirectories</b></code></a>
+ [<a href="usage.html#filters"><i>directory_filter</i></a>]</td>
+<td>Keep the specified directories in the output jars (or wars, ears, zips, or
+ directories).</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#target"><code><b>-target</b></code></a>
+ <i>version</i></td>
+<td>Set the given version number in the processed classes.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#forceprocessing"><code><b>-forceprocessing</b></code></a></td>
+<td>Process the input, even if the output seems up to date.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#keep"><code><b>-keep</b></code></a>
+ [<a href="usage.html#keepoptionmodifiers">,<i>modifier</i></a>,...]
+ <a href="usage.html#classspecification"><i>class_specification</i></a></td>
+<td>Preserve the specified classes <i>and</i> class members.</td>
+
+</tr>
+<tr>
+<td valign="top"><a href="usage.html#keepclassmembers"><code><b>-keepclassmembers</b></code></a>
+ [<a href="usage.html#keepoptionmodifiers">,<i>modifier</i></a>,...]
+ <a href="usage.html#classspecification"><i>class_specification</i></a></td>
+<td>Preserve the specified class members, if their classes are preserved as
+ well.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#keepclasseswithmembers"><code><b>-keepclasseswithmembers</b></code></a>
+ [<a href="usage.html#keepoptionmodifiers">,<i>modifier</i></a>,...]
+ <a href="usage.html#classspecification"><i>class_specification</i></a></td>
+<td>Preserve the specified classes <i>and</i> class members, if all of the
+ specified class members are present.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#keepnames"><code><b>-keepnames</b></code></a>
+ <a href="usage.html#classspecification"><i>class_specification</i></a></td>
+<td>Preserve the names of the specified classes <i>and</i> class members (if
+ they aren't removed in the shrinking step).</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#keepclassmembernames"><code><b>-keepclassmembernames</b></code></a>
+ <a href="usage.html#classspecification"><i>class_specification</i></a></td>
+<td>Preserve the names of the specified class members (if they aren't removed
+ in the shrinking step).</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#keepclasseswithmembernames"><code><b>-keepclasseswithmembernames</b></code></a>
+ <a href="usage.html#classspecification"><i>class_specification</i></a></td>
+<td>Preserve the names of the specified classes <i>and</i> class members, if
+ all of the specified class members are present (after the shrinking
+ step).</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#printseeds"><code><b>-printseeds</b></code></a>
+ [<a href="usage.html#filename"><i>filename</i></a>]</td>
+<td>List classes and class members matched by the various <code>-keep</code>
+ options, to the standard output or to the given file.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#dontshrink"><code><b>-dontshrink</b></code></a></td>
+<td>Don't shrink the input class files.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#printusage"><code><b>-printusage</b></code></a>
+ [<a href="usage.html#filename"><i>filename</i></a>]</td>
+<td>List dead code of the input class files, to the standard output or to the
+ given file.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#whyareyoukeeping"><code><b>-whyareyoukeeping</b></code></a>
+ <a href="usage.html#classspecification"><i>class_specification</i></a></td>
+<td>Print details on why the given classes and class members are being kept in
+ the shrinking step.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#dontoptimize"><code><b>-dontoptimize</b></code></a></td>
+<td>Don't optimize the input class files.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#optimizations"><code><b>-optimizations</b></code></a>
+ <a href="optimizations.html"><i>optimization_filter</i></a></td>
+<td>The optimizations to be enabled and disabled.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#optimizationpasses"><code><b>-optimizationpasses</b></code></a>
+ <i>n</i></td>
+<td>The number of optimization passes to be performed.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#assumenosideeffects"><code><b>-assumenosideeffects</b></code></a>
+ <a href="usage.html#classspecification"><i>class_specification</i></a></td>
+<td>Assume that the specified methods don't have any side effects, while
+ optimizing.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#allowaccessmodification"><code><b>-allowaccessmodification</b></code></a></td>
+<td>Allow the access modifiers of classes and class members to be modified,
+ while optimizing.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#mergeinterfacesaggressively"><code><b>-mergeinterfacesaggressively</b></code></a></td>
+<td>Allow any interfaces to be merged, while optimizing.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#dontobfuscate"><code><b>-dontobfuscate</b></code></a></td>
+<td>Don't obfuscate the input class files.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#printmapping"><code><b>-printmapping</b></code></a>
+ [<a href="usage.html#filename"><i>filename</i></a>]</td>
+<td>Print the mapping from old names to new names for classes and class members
+ that have been renamed, to the standard output or to the given file.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#applymapping"><code><b>-applymapping</b></code></a>
+ <a href="usage.html#filename"><i>filename</i></a></td>
+<td>Reuse the given mapping, for incremental obfuscation.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#obfuscationdictionary"><code><b>-obfuscationdictionary</b></code></a>
+ <a href="usage.html#filename"><i>filename</i></a></td>
+<td>Use the words in the given text file as obfuscated field names and method names.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#classobfuscationdictionary"><code><b>-classobfuscationdictionary</b></code></a>
+ <a href="usage.html#filename"><i>filename</i></a></td>
+<td>Use the words in the given text file as obfuscated class names.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#packageobfuscationdictionary"><code><b>-packageobfuscationdictionary</b></code></a>
+ <a href="usage.html#filename"><i>filename</i></a></td>
+<td>Use the words in the given text file as obfuscated package names.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#overloadaggressively"><code><b>-overloadaggressively</b></code></a></td>
+<td>Apply aggressive overloading while obfuscating.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#useuniqueclassmembernames"><code><b>-useuniqueclassmembernames</b></code></a></td>
+<td>Ensure uniform obfuscated class member names for subsequent incremental
+ obfuscation.</td> </tr>
+
+<tr>
+<td valign="top"><a href="usage.html#dontusemixedcaseclassnames"><code><b>-dontusemixedcaseclassnames</b></code></a></td>
+<td>Don't generate mixed-case class names while obfuscating.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#keeppackagenames"><code><b>-keeppackagenames</b></code></a>
+ [<i><a href="usage.html#filters">package_filter</a></i>]</td>
+<td>Keep the specified package names from being obfuscated.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#flattenpackagehierarchy"><code><b>-flattenpackagehierarchy</b></code></a>
+ [<i>package_name</i>]</td>
+<td>Repackage all packages that are renamed into the single given parent
+ package.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#repackageclasses"><code><b>-repackageclasses</b></code></a>
+ [<i>package_name</i>]</td>
+<td>Repackage all class files that are renamed into the single given
+ package.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#keepattributes"><code><b>-keepattributes</b></code></a>
+ [<i><a href="usage.html#filters">attribute_filter</a></i>]</td>
+<td>Preserve the given optional attributes; typically
+ <code>Exceptions</code>, <code>InnerClasses</code>,
+ <code>Signature</code>, <code>Deprecated</code>,
+ <code>SourceFile</code>, <code>SourceDir</code>,
+ <code>LineNumberTable</code>,
+ <code>LocalVariableTable</code>, <code>LocalVariableTypeTable</code>,
+ <code>Synthetic</code>, <code>EnclosingMethod</code>, and
+ <code>*Annotation*</code>.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#keepparameternames"><code><b>-keepparameternames</b></code></a></td>
+<td>Keep the parameter names and types of methods that are kept.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#renamesourcefileattribute"><code><b>-renamesourcefileattribute</b></code></a>
+ [<i>string</i>]</td>
+<td>Put the given constant string in the <code>SourceFile</code>
+ attributes.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#adaptclassstrings"><code><b>-adaptclassstrings</b></code></a>
+ [<a href="usage.html#filters"><i>class_filter</i></a>]</td>
+<td>Adapt string constants in the specified classes, based on the obfuscated
+ names of any corresponding classes.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#adaptresourcefilenames"><code><b>-adaptresourcefilenames</b></code></a>
+ [<a href="usage.html#filefilters"><i>file_filter</i></a>]</td>
+<td>Rename the specified resource files, based on the obfuscated names of the
+ corresponding class files.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#adaptresourcefilecontents"><code><b>-adaptresourcefilecontents</b></code></a>
+ [<a href="usage.html#filefilters"><i>file_filter</i></a>]</td>
+<td>Update the contents of the specified resource files, based on the
+ obfuscated names of the processed classes.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#dontpreverify"><code><b>-dontpreverify</b></code></a></td>
+<td>Don't preverify the processed class files.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#microedition"><code><b>-microedition</b></code></a></td>
+<td>Target the processed class files at Java Micro Edition.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#verbose"><code><b>-verbose</b></code></a></td>
+<td>Write out some more information during processing.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#dontnote"><code><b>-dontnote</b></code></a>
+ [<a href="usage.html#filters"><i>class_filter</i></a>]</td>
+<td>Don't print notes about potential mistakes or omissions in the
+ configuration.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#dontwarn"><code><b>-dontwarn</b></code></a>
+ [<a href="usage.html#filters"><i>class_filter</i></a>]</td>
+<td>Don't warn about unresolved references at all.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#ignorewarnings"><code><b>-ignorewarnings</b></code></a></td>
+<td>Print warnings about unresolved references, but continue processing
+ anyhow.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#printconfiguration"><code><b>-printconfiguration</b></code></a>
+ [<a href="usage.html#filename"><i>filename</i></a>]</td>
+<td>Write out the entire configuration in traditional ProGuard style, to the
+ standard output or to the given file.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#dump"><code><b>-dump</b></code></a>
+ [<a href="usage.html#filename"><i>filename</i></a>]</td>
+<td>Write out the internal structure of the processed class files, to the
+ standard output or to the given file.</td>
+</tr>
+
+</table>
+<p>
+Notes:
+<ul>
+
+<li><i>class_path</i> is a list of jars, wars, ears, zips, and directories,
+ with optional filters, separated by path separators.</li>
+<li><i>filename</i> can contain Java system properties delimited by
+ '<b>&lt;</b>' and '<b>&gt;</b>'.</li>
+<li>If <i>filename</i> contains special characters, the entire name
+ should be quoted with single or double quotes.</li>
+</ul>
+<p>
+
+<h2>Overview of <code>Keep</code> Options</h2>
+
+<table cellpadding="5">
+
+<tr>
+<th>Keep</th>
+<td>From being removed or renamed</td>
+<td>From being renamed</td>
+</tr>
+
+<tr>
+<td>Classes and class members</td>
+<td bgcolor="#E0E0E0"><a href="usage.html#keep"><code>-keep</code></a></td>
+<td bgcolor="#E0E0E0"><a href="usage.html#keepnames"><code>-keepnames</code></a></td>
+</tr>
+
+<tr>
+<td>Class members only</td>
+<td bgcolor="#E0E0E0"><a href="usage.html#keepclassmembers"><code>-keepclassmembers</code></a></td>
+<td bgcolor="#E0E0E0"><a href="usage.html#keepclassmembernames"><code>-keepclassmembernames</code></a></td>
+</tr>
+
+<tr>
+<td>Classes and class members, if class members present</td>
+<td bgcolor="#E0E0E0"><a href="usage.html#keepclasseswithmembers"><code>-keepclasseswithmembers</code></a></td>
+<td bgcolor="#E0E0E0"><a href="usage.html#keepclasseswithmembernames"><code>-keepclasseswithmembernames</code></a></td>
+</tr>
+
+</table>
+<p>
+
+<h2>Keep Option Modifiers</h2>
+
+<table cellspacing="10">
+
+<tr>
+<td valign="top"><a href="usage.html#includedescriptorclasses"><code><b>includedescriptorclasses</b></code></a></td>
+<td>Also keep any classes in the descriptors of specified fields and methods.
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#allowshrinking"><code><b>allowshrinking</b></code></a></td>
+<td>Allow the specified entry points to be removed in the shrinking step.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#allowoptimization"><code><b>allowoptimization</b></code></a></td>
+<td>Allow the specified entry points to be modified in the optimization
+ step.</td>
+</tr>
+
+<tr>
+<td valign="top"><a href="usage.html#allowobfuscation"><code><b>allowobfuscation</b></code></a></td>
+<td>Allow the specified entry points to be renamed in the obfuscation step.</td>
+</tr>
+
+</table>
+<p>
+
+<h2>Class Specifications</h2>
+
+<pre>
+[<b>@</b><i>annotationtype</i>] [[<b>!</b>]<b>public</b>|<b>final</b>|<b>abstract</b> ...] [<b>!</b>]<b>interface</b>|<b>class</b> <i>classname</i>
+ [<b>extends</b>|<b>implements</b> [<b>@</b><i>annotationtype</i>] <i>classname</i>]
+[<b>{</b>
+ [<b>@</b><i>annotationtype</i>] [[<b>!</b>]<b>public</b>|<b>private</b>|<b>protected</b>|<b>static</b>|<b>volatile</b>|<b>transient</b> ...] <b>&lt;fields&gt;</b> |
+ (<i>fieldtype fieldname</i>)<b>;</b>
+ [<b>@</b><i>annotationtype</i>] [[<b>!</b>]<b>public</b>|<b>private</b>|<b>protected</b>|<b>static</b>|<b>synchronized</b>|<b>native</b>|<b>abstract</b>|<b>strictfp</b> ...] <b>&lt;methods&gt;</b> |
+ <b>&lt;init&gt;(</b><i>argumenttype,...</i><b>)</b> |
+ <i>classname</i><b>(</b><i>argumenttype,...</i><b>)</b> |
+ (<i>returntype methodname</i><b>(</b><i>argumenttype,...</i><b>)</b>)<b>;</b>
+ [<b>@</b><i>annotationtype</i>] [[<b>!</b>]<b>public</b>|<b>private</b>|<b>protected</b>|<b>static</b> ... ] <b>*;</b>
+ ...
+<b>}</b>]
+</pre>
+<p>
+Notes:
+<ul>
+<li>Class names must always be fully qualified, i.e. including their package
+ names.</li>
+<li>Types in <i>classname</i>, <i>annotationtype</i>, <i>returntype</i>, and
+ <i>argumenttype</i> can contain wildcards: '<code><b>?</b></code>' for a
+ single character, '<code><b>*</b></code>' for any number of characters
+ (but not the package separator), '<code><b>**</b></code>' for any number
+ of (any) characters, '<code><b>%</b></code>' for any primitive type,
+ '<code><b>***</b></code>' for any type, and '<code><b>...</b></code>' for any number of arguments.</li>
+<li><i>fieldname</i> and <i>methodname</i> can contain wildcards as well:
+ '<code><b>?</b></code>' for a single character and '<code><b>*</b></code>'
+ for any number of characters.</li>
+</ul>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/examples.html b/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/examples.html
new file mode 100644
index 0000000000..ec2a99bbc3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/examples.html
@@ -0,0 +1,182 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="../style.css">
+<title>ReTrace Examples</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../../index.html#manual/retrace/examples.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../../index.html#manual/retrace/examples.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Examples</h2>
+
+Some typical example uses:
+<ol>
+<li><a href="#with">Restoring a stack trace with line numbers</a></li>
+<li><a href="#withverbose">Restoring a stack trace with line numbers
+ (verbose)</a></li>
+<li><a href="#without">Restoring a stack trace without line numbers</a></li>
+</ol>
+
+<h3><a name="with">Restoring a stack trace with line numbers</a></h3>
+
+Assume for instance ProGuard itself has been obfuscated using the following
+extra options:
+<pre>
+-printmapping mapping.txt
+
+-renamesourcefileattribute MyApplication
+-keepattributes SourceFile,LineNumberTable
+</pre>
+<p>
+
+Now assume the processed application throws an exception:
+<pre>
+java.io.IOException: Can't read [dummy.jar] (No such file or directory)
+ at proguard.y.a(MyApplication:188)
+ at proguard.y.a(MyApplication:158)
+ at proguard.y.a(MyApplication:136)
+ at proguard.y.a(MyApplication:66)
+ at proguard.ProGuard.c(MyApplication:218)
+ at proguard.ProGuard.a(MyApplication:82)
+ at proguard.ProGuard.main(MyApplication:538)
+Caused by: java.io.IOException: No such file or directory
+ at proguard.d.q.a(MyApplication:50)
+ at proguard.y.a(MyApplication:184)
+ ... 6 more
+</pre>
+<p>
+
+If we have saved the stack trace in a file <code>stacktrace.txt</code>, we can
+use the following command to recover the stack trace:
+<pre>
+<b>java -jar retrace.jar mapping.txt stacktrace.txt</b>
+</pre>
+<p>
+
+The output will correspond to the original stack trace:
+<pre>
+java.io.IOException: Can't read [dummy.jar] (No such file or directory)
+ at proguard.InputReader.readInput(InputReader.java:188)
+ at proguard.InputReader.readInput(InputReader.java:158)
+ at proguard.InputReader.readInput(InputReader.java:136)
+ at proguard.InputReader.execute(InputReader.java:66)
+ at proguard.ProGuard.readInput(ProGuard.java:218)
+ at proguard.ProGuard.execute(ProGuard.java:82)
+ at proguard.ProGuard.main(ProGuard.java:538)
+Caused by: java.io.IOException: No such file or directory
+ at proguard.io.DirectoryPump.pumpDataEntries(DirectoryPump.java:50)
+ at proguard.InputReader.readInput(InputReader.java:184)
+ ... 6 more
+</pre>
+
+<h3><a name="withverbose">Restoring a stack trace with line numbers (verbose)</a></h3>
+
+In the previous example, we could also use the verbose flag:
+<pre>
+<b>java -jar retrace.jar -verbose mapping.txt stacktrace.txt</b>
+</pre>
+<p>
+
+The output will then look as follows:
+<pre>
+java.io.IOException: Can't read [dummy.jar] (No such file or directory)
+ at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPathEntry,proguard.io.DataEntryReader)(InputReader.java:188)
+ at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPath,int,int,proguard.io.DataEntryReader)(InputReader.java:158)
+ at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPath,proguard.io.DataEntryReader)(InputReader.java:136)
+ at proguard.InputReader.void execute(proguard.classfile.ClassPool,proguard.classfile.ClassPool)(InputReader.java:66)
+ at proguard.ProGuard.void readInput()(ProGuard.java:218)
+ at proguard.ProGuard.void execute()(ProGuard.java:82)
+ at proguard.ProGuard.void main(java.lang.String[])(ProGuard.java:538)
+Caused by: java.io.IOException: No such file or directory
+ at proguard.io.DirectoryPump.void pumpDataEntries(proguard.io.DataEntryReader)(DirectoryPump.java:50)
+ at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPathEntry,proguard.io.DataEntryReader)(InputReader.java:184)
+ ... 6 more
+</pre>
+
+
+<h3><a name="without">Restoring a stack trace without line numbers</a></h3>
+
+Assume for instance ProGuard itself has been obfuscated using the following
+extra options, this time without preserving the line number tables:
+<pre>
+-printmapping mapping.txt
+</pre>
+<p>
+
+A stack trace <code>stacktrace.txt</code> will then lack line number
+information, showing "Unknown source" instead:
+<pre>
+java.io.IOException: Can't read [dummy.jar] (No such file or directory)
+ at proguard.y.a(Unknown Source)
+ at proguard.y.a(Unknown Source)
+ at proguard.y.a(Unknown Source)
+ at proguard.y.a(Unknown Source)
+ at proguard.ProGuard.c(Unknown Source)
+ at proguard.ProGuard.a(Unknown Source)
+ at proguard.ProGuard.main(Unknown Source)
+Caused by: java.io.IOException: No such file or directory
+ at proguard.d.q.a(Unknown Source)
+ ... 7 more
+</pre>
+<p>
+
+We can still use the same command to recover the stack trace:
+<pre>
+<b>java -jar retrace.jar mapping.txt stacktrace.txt</b>
+</pre>
+<p>
+
+The output will now list all alternative original method names for each
+ambiguous obfuscated method name:
+<pre>
+java.io.IOException: Can't read [dummy.jar] (No such file or directory)
+ at proguard.InputReader.execute(InputReader.java)
+ readInput(InputReader.java)
+ at proguard.InputReader.execute(InputReader.java)
+ readInput(InputReader.java)
+ at proguard.InputReader.execute(InputReader.java)
+ readInput(InputReader.java)
+ at proguard.InputReader.execute(InputReader.java)
+ readInput(InputReader.java)
+ at proguard.ProGuard.readInput(ProGuard.java)
+ at proguard.ProGuard.execute(ProGuard.java)
+ optimize(ProGuard.java)
+ createPrintStream(ProGuard.java)
+ closePrintStream(ProGuard.java)
+ fileName(ProGuard.java)
+ at proguard.ProGuard.main(ProGuard.java)
+Caused by: java.io.IOException: No such file or directory
+ at proguard.io.DirectoryPump.pumpDataEntries(DirectoryPump.java)
+ readFiles(DirectoryPump.java)
+</pre>
+<p>
+
+For instance, ReTrace can't tell if the method <code>a</code> corresponds
+to <code>execute</code> or to <code>readInput</code>, so it lists both. You
+need to figure it out based on your knowledge of the application. Having line
+numbers and unambiguous names clearly is a lot easier, so you should consider
+<a href="../examples.html#stacktrace">preserving the line numbers</a> when you
+obfuscate your application.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
+
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/index.html b/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/index.html
new file mode 100644
index 0000000000..71cc0acd58
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/index.html
@@ -0,0 +1,26 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="../style.css">
+<title>ReTrace Manual</title>
+</head>
+<body>
+
+<h2>ReTrace</h2>
+
+<ol>
+<li><a href="introduction.html">Introduction</a></li>
+<li><a href="usage.html">Usage</a></li>
+<li><a href="examples.html">Examples</a></li>
+</ol>
+
+<hr />
+<noscript><div><a target="_top" href="../../index.html" class="button">Show menu</a></div></noscript>
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/introduction.html b/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/introduction.html
new file mode 100644
index 0000000000..3158ad9246
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/introduction.html
@@ -0,0 +1,80 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="../style.css">
+<title>ReTrace Introduction</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../../index.html#manual/retrace/introduction.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../../index.html#manual/retrace/introduction.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Introduction</h2>
+
+<b>ReTrace</b> is a companion tool for <b>ProGuard</b> that 'de-obfuscates'
+stack traces.
+<p>
+When an obfuscated program throws an exception, the resulting stack trace
+typically isn't very informative. Class names and method names have been
+replaced by short meaningless strings. Source file names and line numbers are
+missing altogether. While this may be intentional, it can also be inconvenient
+when debugging problems.
+<p>
+
+<table class="diagram" align="center">
+
+<tr>
+<td rowspan="1" class="lightblock">Original code</td>
+<td class="transparentblock">- <b>ProGuard</b> &rarr;</td>
+<td rowspan="1" class="lightblock">Obfuscated code</td>
+</tr>
+
+<tr>
+<td rowspan="3" class="transparentblock"></td>
+<td class="transparentblock">&darr;</td>
+<td class="transparentblock">&darr;</td>
+</tr>
+
+<tr>
+<td class="whiteblock">Mapping file</td>
+<td class="transparentblock">&darr;</td>
+</tr>
+
+<tr>
+<td class="transparentblock">&darr;</td>
+<td class="transparentblock">&darr;</td>
+</tr>
+
+<tr>
+<td class="whiteblock">Readable stack trace</td>
+<td class="transparentblock">&larr; <b>ReTrace</b> -</td>
+<td class="whiteblock">Obfuscated stack trace</td>
+</tr>
+
+</table>
+<p>
+ReTrace can read an obfuscated stack trace and restore it to what it would
+look like without obfuscation. The restoration is based on the mapping file
+that ProGuard can write out during obfuscation. The mapping file links the
+original class names and class member names to their obfuscated names.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
+
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/usage.html b/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/usage.html
new file mode 100644
index 0000000000..aefcf67b30
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/retrace/usage.html
@@ -0,0 +1,143 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="../style.css">
+<title>ReTrace Usage</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../../index.html#manual/retrace/usage.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../../index.html#manual/retrace/usage.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Usage</h2>
+
+You can find the ReTrace jar in the <code>lib</code> directory of the
+ProGuard distribution. To run ReTrace, just type:
+<p>
+<p class="code">
+<code><b>java -jar retrace.jar </b></code>[<i>options...</i>]
+ <i>mapping_file</i> [<i>stacktrace_file</i>]
+</p>
+Alternatively, the <code>bin</code> directory contains some short Linux and
+Windows scripts containing this command. These are the arguments:
+
+<dl>
+<dt><i>mapping_file</i></dt>
+
+<dd>Specifies the name of the mapping file, produced by ProGuard with the
+ option
+ "<a href="../usage.html#printmapping"><code>-printmapping</code></a> <i>mapping_file</i>",
+ while obfuscating the application that produced the stack trace.</dd>
+
+<dt><i>stacktrace_file</i></dt>
+
+<dd>Optionally specifies the name of the file containing the stack trace. If
+ no file is specified, a stack trace is read from the standard input. Blank
+ lines and unrecognized lines are ignored, as far as possible.</dd>
+</dl>
+
+The following options are supported:
+<dl>
+<dt><code><b>-verbose</b></code></dt>
+
+<dd>Specifies to print out more informative stack traces that include not only
+ method names, but also method return types and arguments.</dd>
+
+<dt><code><b>-regex</b></code> <i>regular_expression</i></dt>
+
+<dd>Specifies the regular expression that is used to parse the lines in the
+ stack trace. Specifying a different regular expression allows to
+ de-obfuscate more general types of input than just stack traces. The
+ default is suitable for stack traces produced by most JVMs:
+ <pre>
+(?:.*?\bat\s+%c\.%m\s*\(%s(?::%l)?\)\s*(?:~\[.*\])?)|(?:(?:.*?[:"]\s+)?%c(?::.*)?)
+ </pre>
+ The regular expression is a Java regular expression (cfr. the documentation
+ of <code>java.util.regex.Pattern</code>), with a few additional wildcards:
+ <table cellspacing="10">
+ <tr><td valign="top"><code><b>%c</b></code></td>
+ <td>matches a class name (e.g.
+ "<code>myapplication.MyClass</code>").</td></tr>
+ <tr><td valign="top"><code><b>%C</b></code></td>
+ <td>matches a class name with slashes (e.g.
+ "<code>myapplication/MyClass</code>").</td></tr>
+ <tr><td valign="top"><code><b>%t</b></code></td>
+ <td>matches a field type or method return type (e.g.
+ "<code>myapplication.MyClass[]</code>").</td></tr>
+ <tr><td valign="top"><code><b>%f</b></code></td>
+ <td>matches a field name (e.g.
+ "<code>myField</code>").</td></tr>
+ <tr><td valign="top"><code><b>%m</b></code></td>
+ <td>matches a method name (e.g.
+ "<code>myMethod</code>").</td></tr>
+ <tr><td valign="top"><code><b>%a</b></code></td>
+ <td>matches a list of method arguments (e.g.
+ "<code>boolean,int</code>").</td></tr>
+ <tr><td valign="top"><code><b>%s</b></code></td>
+ <td>matches a source file name (e.g.
+ "<code>MyClass.java</code>").</td></tr>
+ <tr><td valign="top"><code><b>%l</b></code></td>
+ <td>matches a line number inside a method (e.g.
+ "<code>123</code>").</td></tr>
+ </table>
+ Elements that match these wildcards are de-obfuscated, when possible. Note
+ that regular expressions must not contain any capturing groups. Use
+ non-capturing groups instead: <code>(?:</code>...<code>)</code>
+ <p>
+ The default expression for instance matches the following lines:
+ <pre>
+Exception in thread "main" myapplication.MyException: Some message
+ at myapplication.MyClass.myMethod(SourceFile:123)
+ </pre>
+ </dd>
+</dl>
+
+The restored stack trace is printed to the standard output. The completeness
+of the restored stack trace depends on the presence of line number tables in
+the obfuscated class files:
+
+<ul>
+<li>If all line numbers have been preserved while obfuscating the application,
+ ReTrace will be able to restore the stack trace completely.</li>
+
+<li>If the line numbers have been removed, mapping obfuscated method names
+ back to their original names has become ambiguous. Retrace will list all
+ possible original method names for each line in the stack trace. The user
+ can then try to deduce the actual stack trace manually, based on the logic
+ of the program.</li>
+
+</ul>
+<p>
+
+Preserving line number tables is explained in detail in this <a
+href="../examples.html#stacktrace">example</a> in the ProGuard User Manual.
+<p>
+
+Source file names are currently restored based on the names of the outer-most
+classes. If you prefer to keep the obfuscated name, you can
+replace <code>%s</code> in the default regular expression by <code>.*</code>
+<p>
+
+Unobfuscated elements and obfuscated elements for which no mapping is available
+will be left unchanged.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
+
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/sections.html b/third_party/java/proguard/proguard5.3.3/docs/manual/sections.html
new file mode 100644
index 0000000000..1b04ed6349
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/sections.html
@@ -0,0 +1,54 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-script-type" content="text/javascript">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="../style.css">
+<title>Sections</title>
+</head>
+<body class="navigation">
+
+<ul class="navigation">
+<li><a href="../sections.html">&lt;&lt; Main menu</a></li>
+
+<li class="title">ProGuard Manual</li>
+<li><a target="main" href="introduction.html">Introduction</a></li>
+<li><a target="main" href="usage.html">Usage</a></li>
+<li><a target="main" href="limitations.html">Limitations</a></li>
+<li><a target="main" href="examples.html">Examples</a></li>
+<li><a target="main" href="troubleshooting.html">Troubleshooting</a></li>
+<li><a target="main" href="refcard.html">Ref Card</a></li>
+<li><a target="main" href="gui.html">GUI</a></li>
+<li><a target="main" href="ant.html">Ant Task</a></li>
+<li><a target="main" href="gradle.html">Gradle Task</a></li>
+<li><a target="main" href="wtk.html">JME WTK</a></li>
+
+<li class="title">ReTrace Manual</li>
+<li><a target="main" href="retrace/introduction.html">Introduction</a></li>
+<li><a target="main" href="retrace/usage.html">Usage</a></li>
+<li><a target="main" href="retrace/examples.html">Examples</a></li>
+</ul>
+
+<p>
+<center>
+<small>More Android code protection:</small>
+<p>
+<a href="http://www.guardsquare.com/dexguard" target="_top">
+<img src="../dexguard.png" width="88" height="55" alt="DexGuard" /></a>
+
+<p>
+<small>With support of</small>
+
+<p>
+<a href="http://www.guardsquare.com/" target="_top">
+<img src="../guardsquare.png" width="88" height="25" alt="GuardSquare" /></a>
+
+<p>
+<a href="http://sourceforge.net/projects/proguard/" target="other">
+<img src="../sflogo.png" width="88" height="31" alt="SourceForge" /></a>
+
+</center>
+
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/style.css b/third_party/java/proguard/proguard5.3.3/docs/manual/style.css
new file mode 100644
index 0000000000..415b8ef3cb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/style.css
@@ -0,0 +1,184 @@
+@charset "iso-8859-1";
+
+/* Fonts. */
+
+@font-face
+{
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: url('fonts/OpenSans-Regular.eot');
+ src: local('Open Sans'),
+ local('OpenSans'),
+ url('fonts/OpenSans-Regular.eot?#iefix') format('embedded-opentype'),
+ url('fonts/OpenSans-Regular.woff') format('woff'),
+ url('fonts/OpenSans-Regular.ttf') format('truetype'),
+ url('fonts/OpenSans-Regular.svg#OpenSansRegular') format('svg');
+}
+
+@font-face
+{
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: url('fonts/OpenSans-Bold.eot');
+ src: local('Open Sans Bold'),
+ local('OpenSans-Bold'),
+ url('fonts/OpenSans-Bold.eot?#iefix') format('embedded-opentype'),
+ url('fonts/OpenSans-Bold.woff') format('woff'),
+ url('fonts/OpenSans-Bold.ttf') format('truetype'),
+ url('fonts/OpenSans-Bold.svg#OpenSansBold') format('svg');
+}
+
+@font-face
+{
+ font-family: 'Open Sans';
+ font-style: italic;
+ font-weight: 400;
+ src: url('fonts/OpenSans-Italic.eot');
+ src: local('Open Sans Italic'),
+ local('OpenSans-Italic'),
+ url('fonts/OpenSans-Italic.eot?#iefix') format('embedded-opentype'),
+ url('fonts/OpenSans-Italic.woff') format('woff'),
+ url('fonts/OpenSans-Italic.ttf') format('truetype'),
+ url('fonts/OpenSans-Italic.svg#OpenSansItalic') format('svg');
+}
+
+/* Global settings. */
+
+body
+{
+ background: #FFFFFF;
+ font-family: "Open Sans",Verdana,sans-serif;
+}
+
+h1
+{
+ text-align: center;
+}
+
+h2
+{
+ background: #EEEEFF;
+ padding: 10px;
+}
+
+dt
+{
+ padding: 6px;
+}
+
+dt div
+{
+ color: grey;
+ float: right;
+}
+
+dd
+{
+ padding: 6px;
+}
+
+pre
+{
+ padding: 10px;
+ background: #E0E0E0;
+}
+
+.spacious li
+{
+ padding: 8px;
+}
+
+.shifted li
+{
+ margin-left: 50px;
+}
+
+img.float
+{
+ float: left;
+}
+
+a
+{
+ text-decoration: none;
+}
+
+a.button
+{
+ color: #000000;
+ text-decoration: none;
+ background: #E0E0E0;
+ border: 1px outset #FFFFFF;
+ float: right;
+}
+
+a.largebutton {
+ font-weight: bold;
+ color: #000000;
+ margin: 0px;
+ padding: 10px;
+ background: #D0D0D0;
+ text-decoration: none;
+ border: 1px outset #FFFFFF;
+}
+
+/* Settings for variable width code. */
+
+p.code
+{
+ padding: 10px;
+ background: #E0E0E0;
+}
+
+
+/* Settings for diagrams. */
+
+table.diagram
+{
+ padding: 8px;
+ border: none;
+ border-spacing: 2px;
+}
+
+td.transparentblock
+{
+ text-align: center;
+ padding: 10px 0px;
+}
+
+td.whiteblock
+{
+ width: 100px;
+ text-align: center;
+ border: 1px solid #C0C0C0;
+ background: #E0E0E0;
+ padding: 10px 0px;
+}
+
+td.lightblock
+{
+ width: 100px;
+ text-align: center;
+ border: 1px solid #8888FF;
+ background: #BBBBFF;
+ padding: 20px 0px;
+}
+
+td.darkblock
+{
+ width: 100px;
+ text-align: center;
+ background: #8888FF;
+ padding: 20px 0px;
+}
+
+/* Settings for buttons. */
+
+td.button
+{
+ background: #E0E0E0;
+ border: 1px outset #FFFFFF;
+ font-weight: bold;
+}
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/troubleshooting.html b/third_party/java/proguard/proguard5.3.3/docs/manual/troubleshooting.html
new file mode 100644
index 0000000000..81c49b53e1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/troubleshooting.html
@@ -0,0 +1,933 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Troubleshooting</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/troubleshooting.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/troubleshooting.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Troubleshooting</h2>
+
+While preparing a configuration for processing your code, you may bump into a
+few problems. The following sections discuss some common issues and solutions:
+
+<h3><a href="#processing">Problems while processing</a></h3>
+<ul>
+<li><a href="#dynamicalclass">Note: can't find dynamically referenced class ...</a></li>
+<li><a href="#dynamicalclasscast">Note: ... calls '(...)Class.forName(variable).newInstance()'</a></li>
+<li><a href="#dynamicalclassmember">Note: ... accesses a field/method '...' dynamically</a></li>
+<li><a href="#attributes">Note: ... calls 'Class.get...', 'Field.get...', or 'Method.get...'</a></li>
+<li><a href="#unknownclass">Note: the configuration refers to the unknown class '...'</a></li>
+<li><a href="#descriptorclass">Note: the configuration keeps the entry point '...', but not the descriptor class '...'</a></li>
+<li><a href="#libraryclass">Note: the configuration explicitly specifies '...' to keep library class '...'</a></li>
+<li><a href="#classmembers">Note: the configuration doesn't specify which class members to keep for class '...'</a></li>
+<li><a href="#nosideeffects">Note: the configuration specifies that none of the methods of class '...' have any side effects</a></li>
+<li><a href="#duplicateclass">Note: duplicate definition of program/library class</a></li>
+<li><a href="#duplicatezipentry">Warning: can't write resource ... Duplicate zip entry</a></li>
+<li><a href="#unresolvedclass">Warning: can't find superclass or interface</a></li>
+<li><a href="#unresolvedclass">Warning: can't find referenced class</a></li>
+<li><a href="#superclass">Error: Can't find any super classes of ... (not even immediate super class ...)</a></li>
+<li><a href="#superclass">Error: Can't find common super class of ... and ...</a></li>
+<li><a href="#unresolvedprogramclassmember">Warning: can't find referenced field/method '...' in program class ...</a></li>
+<li><a href="#unresolvedlibraryclassmember">Warning: can't find referenced field/method '...' in library class ...</a></li>
+<li><a href="#unresolvedenclosingmethod">Warning: can't find enclosing class/method</a></li>
+<li><a href="#dependency">Warning: library class ... depends on program class ...</a></li>
+<li><a href="#unexpectedclass">Warning: class file ... unexpectedly contains class ...</a></li>
+<li><a href="#mappingconflict1">Warning: ... is not being kept as ..., but remapped to ...</a></li>
+<li><a href="#mappingconflict2">Warning: field/method ... can't be mapped to ...</a></li>
+<li><a href="#unsupportedclassversion">Error: Unsupported class version number</a></li>
+<li><a href="#keep">Error: You have to specify '-keep' options</a></li>
+<li><a href="#filename">Error: Expecting class path separator ';' before 'Files\Java\...' (in Windows)</a></li>
+<li><a href="#macosx">Error: Can't read [.../lib/rt.jar] (No such file or directory) (in MacOS X)</a></li>
+<li><a href="#cantread">Error: Can't read ...</a></li>
+<li><a href="#cantwrite">Error: Can't write ...</a></li>
+<li><a href="#startinggui">Internal problem starting the ProGuard GUI (Cannot write XdndAware property) (in Linux)</a></li>
+<li><a href="#outofmemoryerror">OutOfMemoryError</a></li>
+<li><a href="#stackoverflowerror">StackOverflowError</a></li>
+<li><a href="#unexpectederror">Unexpected error</a></li>
+<li><a href="#otherwise">Otherwise...</a></li>
+</ul>
+
+<h3><a href="#afterprocessing">Unexpected observations after processing</a></h3>
+<ul>
+<li><a href="#disappearingclasses">Disappearing classes</a></li>
+<li><a href="#notkept">Classes or class members not being kept</a></li>
+<li><a href="#notobfuscated">Variable names not being obfuscated</a></li>
+</ul>
+
+<h3><a href="#dalvik">Problems while converting to Android Dalvik bytecode</a></h3>
+
+<ul>
+<li><a href="#simexception">SimException: local variable type mismatch</a></li>
+<li><a href="#conversionerror">Conversion to Dalvik format failed with error 1</a></li>
+</ul>
+
+<h3><a href="#preverifying">Problems while preverifying for Java Micro Edition</a></h3>
+
+<ul>
+<li><a href="#invalidclassexception1">InvalidClassException, class loading error, or verification error</a></li>
+</ul>
+
+<h3><a href="#runtime">Problems at run-time</a></h3>
+<ul>
+<li><a href="#stacktraces">Stack traces without class names or line numbers</a></li>
+<li><a href="#noclassdeffounderror">NoClassDefFoundError</a></li>
+<li><a href="#classnotfoundexception">ClassNotFoundException</a></li>
+<li><a href="#nosuchfieldexception">NoSuchFieldException</a></li>
+<li><a href="#nosuchmethodexception">NoSuchMethodException</a></li>
+<li><a href="#missingresourceexception">MissingResourceException or NullPointerException</a></li>
+<li><a href="#disappearingannotations">Disappearing annotations</a></li>
+<li><a href="#invalidjarfile">Invalid or corrupt jarfile</a></li>
+<li><a href="#invalidjarindexexception">InvalidJarIndexException: Invalid index</a></li>
+<li><a href="#invalidclassexception2">InvalidClassException, class loading error, or verification error (in Java Micro Edition)</a></li>
+<li><a href="#nosuchfieldormethod">Error: No Such Field or Method, Error verifying method (in a Java Micro Edition emulator)</a></li>
+<li><a href="#failingmidlets">Failing midlets (on a Java Micro Edition device)</a></li>
+<li><a href="#disappearingloops">Disappearing loops</a></li>
+<li><a href="#securityexception">SecurityException: SHA1 digest error</a></li>
+<li><a href="#classcastexception">ClassCastException: class not an enum</a></li><li><a href="#classcastexception">IllegalArgumentException: class not an enum type</a></li>
+<li><a href="#arraystoreexception">ArrayStoreException: sun.reflect.annotation.EnumConstantNotPresentExceptionProxy</a></li>
+<li><a href="#illegalargumentexception">IllegalArgumentException: methods with same signature but incompatible return types</a></li>
+<li><a href="#compilererror">CompilerError: duplicate addition</a></li>
+<li><a href="#classformaterror1">ClassFormatError: repetitive field name/signature</a></li>
+<li><a href="#classformaterror2">ClassFormatError: Invalid index in LocalVariableTable in class file</a></li>
+<li><a href="#nosuchmethoderror">NoSuchMethodError or AbstractMethodError</a></li>
+<li><a href="#verifyerror">VerifyError</a></li>
+</ul>
+
+
+<h2><a name="processing">Problems while processing</a></h2>
+
+ProGuard may print out some notes and non-fatal warnings:
+
+<dl>
+<dt><a name="dynamicalclass"><b>Note: can't find dynamically referenced class ...</b></a></dt>
+
+<dd>ProGuard can't find a class or interface that your code is accessing by
+ means of introspection. You should consider adding the jar that contains
+ this class.</dd>
+
+<dt><a name="dynamicalclasscast"><b>Note: ... calls '(...)Class.forName(variable).newInstance()'</b></a></dt>
+
+<dd>Your code uses reflection to dynamically create class instances, with a
+ construct like
+ "<code>(MyClass)Class.forName(variable).newInstance()</code>". Depending
+ on your application, you may need to keep the mentioned classes with an
+ option like "<code>-keep class MyClass</code>", or their implementations
+ with an option like "<code>-keep class * implements MyClass</code>". You
+ can switch off these notes by specifying the
+ <a href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+
+<dt><a name="dynamicalclassmember"><b>Note: ... accesses a field/method '...' dynamically</b></a></dt>
+
+<dd>Your code uses reflection to find a fields or a method, with a construct
+ like "<code>.getField("myField")</code>". Depending on your application,
+ you may need to figure out where the mentioned class members are defined
+ and keep them with an option like "<code>-keep class MyClass { MyFieldType
+ myField; }</code>". Otherwise, ProGuard might remove or obfuscate the
+ class members, since it can't know which ones they are exactly. It does
+ list possible candidates, for your information. You can switch off these
+ notes by specifying
+ the <a href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+
+<dt><a name="attributes"><b>Note: ... calls 'Class.get...'</b>, <b>'Field.get...'</b>, or <b>'Method.get...'</b></a></dt>
+<dd>Your code uses reflection to access metadata from the code, with an
+ invocation like "<code>class.getAnnotations()</code>". You then generally
+ need to preserve optional <a href="attributes.html">class file
+ attributes</a>, which ProGuard removes by default. The attributes contain
+ information about annotations, enclosing classes, enclosing methods, etc.
+ In a summary in the log, ProGuard provides a suggested configuration,
+ like <a href="usage.html#keepattributes"><code>-keepattributes
+ *Annotation*</code></a>. If you're sure the attributes are not necessary,
+ you can switch off these notes by specifying
+ the <a href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+
+<dt><a name="unknownclass"><b>Note: the configuration refers to the unknown class '...'</b></a></dt>
+
+<dd>Your configuration refers to the name of a class that is not present in
+ the program jars or library jars. You should check whether the name is
+ correct. Notably, you should make sure that you always specify
+ fully-qualified names, not forgetting the package names.</dd>
+
+<dt><a name="descriptorclass"><b>Note: the configuration keeps the entry point '...', but not the descriptor class '...'</b></a></dt>
+
+<dd>Your configuration contains a <code>-keep</code> option to preserve the
+ given method (or field), but no <code>-keep</code> option for the given
+ class that is an argument type or return type in the method's descriptor.
+ You may then want to keep the class too. Otherwise, ProGuard will
+ obfuscate its name, thus changing the method's signature. The method might
+ then become unfindable as an entry point, e.g. if it is part of a public
+ API. You can automatically keep such descriptor classes with
+ the <code>-keep</code> option modifier
+ <a href="usage.html#includedescriptorclasses"><code>includedescriptorclasses</code></a>
+ (<code>-keep,includedescriptorclasses</code> ...). You can switch off
+ these notes by specifying
+ the <a href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+
+<dt><a name="libraryclass"><b>Note: the configuration explicitly specifies '...' to keep library class '...'</b></a></dt>
+
+<dd>Your configuration contains a <code>-keep</code> option to preserve the
+ given library class. However, you don't need to keep any library classes.
+ ProGuard always leaves underlying libraries unchanged. You can switch off
+ these notes by specifying the
+ <a href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+
+<dt><a name="classmembers"><b>Note: the configuration doesn't specify which class members to keep for class '...'</b></a></dt>
+
+<dd>Your configuration contains a
+ <a href="usage.html#keepclassmembers"><code>-keepclassmembers</code></a>/<a href="usage.html#keepclasseswithmembers"><code>-keepclasseswithmembers</code></a>
+ option to preserve fields or methods in the given class, but it doesn't
+ specify which fields or methods. This way, the option simply won't have
+ any effect. You probably want to specify one or more fields or methods, as
+ usual between curly braces. You can specify all fields or methods with a
+ wildcard "<code>*;</code>". You should also consider if you just need the
+ more common <a href="usage.html#keep"><code>-keep</code></a> option, which
+ preserves all specified classes <i>and</i> class members.
+ The <a href="usage.html#keepoverview">overview of all <code>keep</code>
+ options</a> can help. You can switch off these notes by specifying
+ the <a href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+
+<dt><a name="nosideeffects"><b>Note: the configuration specifies that none of the methods of class '...' have any side effects</b></a></dt>
+
+<dd>Your configuration contains an option
+ <a href="usage.html#assumenosideeffects"><code>-assumenosideeffects</code></a>
+ to indicate that the specified methods don't have any side effects.
+ However, the configuration tries to match <i>all</i> methods, by using a
+ wildcard like "<code>*;</code>". This includes methods
+ from <code>java.lang.Object</code>, such as <code>wait()</code> and
+ <code>notify()</code>. Removing invocations of those methods will most
+ likely break your application. You should list the methods without side
+ effects more conservatively. You can switch off these notes by specifying
+ the <a href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+
+<dt><a name="duplicateclass"><b>Note: duplicate definition of program/library class</b></a></dt>
+
+<dd>Your program jars or library jars contain multiple definitions of the
+ listed classes. ProGuard continues processing as usual, only considering
+ the first definitions. The warning may be an indication of some problem
+ though, so it's advisable to remove the duplicates. A convenient way to do
+ so is by specifying filters on the input jars or library jars. You can
+ switch off these notes by specifying the <a
+ href="usage.html#dontnote"><code>-dontnote</code></a> option.
+ <p>
+ <img class="float" src="android_small.png" width="32" height="32"
+ alt="android" /> The standard Android build process automatically
+ specifies the input jars for you. There may not be an easy way to filter
+ them to remove these notes. You could remove the duplicate classes
+ manually from your libraries. You should never explicitly specify the
+ input jars yourself (with <code>-injars</code> or
+ <code>-libraryjars</code>), since you'll then get duplicate definitions.
+ You should also not add libraries to your application that are already
+ part of the Android run-time (notably <code>org.w3c.dom</code>,
+ <code>org.xml.sax</code>, <code>org.xmlpull.v1</code>,
+ <code>org.apache.commons.logging.Log</code>, <code>org.apache.http</code>,
+ and <code>org.json</code>). They are possibly inconsistent, and the
+ run-time libraries would get precedence anyway.</dd>
+
+<dt><a name="duplicatezipentry"><b>Warning: can't write resource ... Duplicate zip entry</b></a></dt>
+
+<dd>Your input jars contain multiple resource files with the same name.
+ ProGuard continues copying the resource files as usual, skipping any files
+ with previously used names. Once more, the warning may be an indication of
+ some problem though, so it's advisable to remove the duplicates. A
+ convenient way to do so is by specifying filters on the input jars. There
+ is no option to switch off these warnings.
+ <p>
+ <img class="float" src="android_small.png" width="32" height="32"
+ alt="android" /> The standard Android build process automatically
+ specifies the input jars for you. There may not be an easy way to filter
+ them to remove these warnings. You could remove the duplicate resource files
+ manually from the input and the libraries.</dd>
+
+</dl>
+<p>
+
+ProGuard may terminate when it encounters parsing errors or I/O errors, or
+some more serious warnings:
+
+<dl>
+<dt><a name="unresolvedclass"><b>Warning: can't find superclass or interface</b><br/><b>Warning: can't find referenced class</b></a></dt>
+
+<dd>A class in one of your program jars or library jars is referring to a
+ class or interface that is missing from the input. The warning lists both
+ the referencing class(es) and the missing referenced class(es). There can
+ be a few reasons, with their own solutions:
+ <p>
+ <ol>
+ <li>If the missing class is referenced from your own code, you may have
+ forgotten to specify an essential library. Just like when compiling
+ all code from scratch, you must specify all libraries that the code is
+ referencing, directly or indirectly. If the library should be
+ processed and included in the output, you should specify it with
+ <a href="usage.html#injars"><code>-injars</code></a>, otherwise you
+ should specify it with
+ <a href="usage.html#libraryjars"><code>-libraryjars</code></a>.
+ <p>
+ For example, if ProGuard complains that it can't find a
+ <code>java.lang</code> class, you have to make sure that you are
+ specifying the run-time library of your platform. For JSE, these are
+ typically packaged in <code>lib/rt.jar</code> (<code>vm.jar</code> for
+ IBM's JVM, and <code>classes.jar</code> in MacOS X). Other platforms
+ like JME and Android have their own run-time libraries.
+ The <a href="examples.html">examples section</a> provides more details
+ for the various platforms.
+ <p>
+ If ProGuard still complains that it can't find a
+ <code>javax.crypto</code> class, you probably still have to specify
+ <code>jce.jar</code>, next to the more common <code>rt.jar</code>.</li>
+ <li>If the missing class is referenced from a pre-compiled third-party
+ library, and your original code runs fine without it, then the missing
+ dependency doesn't seem to hurt. The cleanest solution is to
+ <a href="usage.html#filters">filter out</a> the <i>referencing</i>
+ class or classes from the input, with a filter like "<code>-libraryjars
+ mylibrary.jar(!somepackage/SomeUnusedReferencingClass.class)</code>".
+ ProGuard will then skip this class entirely in the input, and it will
+ not bump into the problem of its missing reference. However, you may
+ then have to filter out other classes that are in turn referencing the
+ removed class. In practice, this works best if you can filter out
+ entire unused packages at once, with a wildcard filter like
+ "<code>-libraryjars
+ mylibrary.jar(!someunusedpackage/**)</code>".<p></li>
+ <li>If you don't feel like filtering out the problematic classes, you can
+ try your luck with the <a
+ href="usage.html#ignorewarnings"><code>-ignorewarnings</code></a>
+ option, or even
+ the <a href="usage.html#dontwarn"><code>-dontwarn</code></a> option.
+ Only use these options if you really know what you're doing though.</li>
+ </ol>
+ <p>
+ <img class="float" src="android_small.png" width="32" height="32"
+ alt="android" /> The standard Android build process automatically
+ specifies the input jars for you. Unfortunately, many pre-compiled
+ third-party libraries refer to other libraries that are not actually used
+ and therefore not present. This works fine in debug builds, but in release
+ builds, ProGuard expects all libraries, so it can perform a proper static
+ analysis. For example, if ProGuard complains that it can't find
+ a <code>java.awt</code> class, then some library that you are using is
+ referring to <code>java.awt</code>. This is a bit shady, since Android
+ doesn't have this package at all, but if your application works anyway,
+ you can let ProGuard accept it with "<code>-dontwarn java.awt.**</code>",
+ for instance.
+ <p>
+ If the missing class is an Android run-time class, you should make sure
+ that you are building against an Android run-time that is sufficiently
+ recent. You may need to change the build target in your
+ <code>project.properties</code> file or <code>build.gradle</code> file to
+ that recent version. You can still specify a different
+ <code>minSdkVersion</code> and a different <code>targetSdkVersion</code>
+ in your <code>AndroidManifest.xml</code> file.</dd>
+
+<dt><a name="superclass"><b>Error: Can't find any super classes of ... (not even immediate super class ...)</b><br/><b>Error: Can't find common super class of ... and ...</b></a></dt>
+
+<dd>It seems like you tried to avoid the warnings from the previous paragraph
+ by specifying
+ <a href="usage.html#ignorewarnings"><code>-ignorewarnings</code></a>
+ or <a href="usage.html#dontwarn"><code>-dontwarn</code></a>, but it didn't
+ work out. ProGuard's optimization step and preverification step really
+ need the missing classes to make sense of the code. Preferably, you would
+ solve the problem by adding the missing library, as discussed. If you're
+ sure the class that references the missing class isn't used either, you
+ could also try filtering it out from the input, by adding a filter to the
+ corresponding <a href="usage.html#injars"><code>-injars</code></a> option:
+ "<code>-injars
+ myapplication.jar(!somepackage/SomeUnusedClass.class)</code>". As a final
+ solution, you could switch off optimization
+ (<a href="usage.html#dontoptimize"><code>-dontoptimize</code></a>) and
+ preverification
+ (<a href="usage.html#dontpreverify"><code>-dontpreverify</code></a>).</dd>
+
+<dt><a name="unresolvedprogramclassmember"><b>Warning: can't find referenced field/method '...' in program class ...</b></a></dt>
+
+<dd>A program class is referring to a field or a method that is missing from
+ another program class. The warning lists both the referencing class and
+ the missing referenced class member. Your compiled class files are most
+ likely inconsistent. Possibly, some class file didn't get recompiled
+ properly, or some class file was left behind after its source file was
+ removed. Try removing all compiled class files and rebuilding your
+ project.</dd>
+
+<dt><a name="unresolvedlibraryclassmember"><b>Warning: can't find referenced field/method '...' in library class ...</b></a></dt>
+
+<dd>A program class is referring to a field or a method that is missing from a
+ library class. The warning lists both the referencing class and the
+ missing referenced class member. Your compiled class files are
+ inconsistent with the libraries. You may need to recompile the class
+ files, or otherwise upgrade the libraries to consistent versions.
+ <p>
+ <img class="float" src="android_small.png" width="32" height="32"
+ alt="android" /> If you're developing for Android and ProGuard complains
+ that it can't find a method that is only available in a recent version of
+ the Android run-time, you should change the build target in your
+ <code>project.properties</code> file or <code>build.gradle</code> file to
+ that recent version. You can still specify a different
+ <code>minSdkVersion</code> and a different <code>targetSdkVersion</code>
+ in your <code>AndroidManifest.xml</code> file.
+ <p>
+ Alternatively, you may get away with ignoring the inconsistency with the
+ options
+ <a href="usage.html#ignorewarnings"><code>-ignorewarnings</code></a> or
+ even
+ <a href="usage.html#dontwarn"><code>-dontwarn</code></a>. For instance, you
+ can specify "<code>-dontwarn mypackage.MyInconsistentClass</code>".
+ <p>
+ Finally, should your program classes reside in the same packages as
+ library classes and should they refer to their package visible class
+ members, then you should also specify the
+ <a href="usage.html#dontskipnonpubliclibraryclassmembers"><code>-dontskipnonpubliclibraryclassmembers</code></a>
+ option.</dd>
+
+<dt><a name="unresolvedenclosingmethod"><b>Warning: can't find enclosing class/method</b></a></dt>
+
+<dd>If there are unresolved references to classes that are defined inside
+ methods in your input, once more, your compiled class files are most likely
+ inconsistent. Possibly, some class file didn't get recompiled properly, or
+ some class file was left behind after its source file was removed. Try
+ removing all compiled class files and rebuilding your project.</dd>
+
+<dt><a name="dependency"><b>Warning: library class ... depends on program class ...</b></a></dt>
+
+<dd>If any of your library classes depend on your program classes, by
+ extending, implementing or just referencing them, your processed code will
+ generally be unusable. Program classes can depend on library classes, but
+ not the other way around. Program classes are processed, while library
+ classes always remain unchanged. It is therefore impossible to adapt
+ references from library classes to program classes, for instance if the
+ program classes are renamed. You should define a clean separation between
+ program code (specified with <a
+ href="usage.html#injars"><code>-injars</code></a>) and library code
+ (specified with <a
+ href="usage.html#libraryjars"><code>-libraryjars</code></a>), and try
+ again.
+ <p>
+ <img class="float" src="android_small.png" width="32" height="32"
+ alt="android" /> In Android development, sloppy libraries may contain
+ duplicates of classes that are already present in the Android run-time
+ (notably <code>org.w3c.dom</code>, <code>org.xml.sax</code>,
+ <code>org.xmlpull.v1</code>, <code>org.apache.commons.logging.Log</code>,
+ <code>org.apache.http</code>, and <code>org.json</code>). You must remove
+ these classes from your libraries, since they are possibly inconsistent,
+ and the run-time libraries would get precedence anyway.</dd>
+
+<dt><a name="unexpectedclass"><b>Warning: class file ... unexpectedly contains class ...</b></a></dt>
+
+<dd>The given class file contains a definition for the given class, but the
+ directory name of the file doesn't correspond to the package name of the
+ class. ProGuard will accept the class definition, but the current
+ implementation will not write out the processed version. Please make sure
+ your input classes are packaged correctly. Notably, class files that are
+ in the <code>WEB-INF/classes</code> directory in a war should be packaged
+ in a jar and put in the <code>WEB-INF/lib</code> directory. If you don't
+ mind these classes not being written to the output, you can specify the <a
+ href="usage.html#ignorewarnings"><code>-ignorewarnings</code></a> option,
+ or even the <a href="usage.html#dontwarn"><code>-dontwarn</code></a>
+ option.</dd>
+
+<dt><a name="mappingconflict1"><b>Warning: ... is not being kept as ..., but remapped to ...</b></a></dt>
+
+<dd>There is a conflict between a <code>-keep</code> option in the
+ configuration, and the mapping file, in the obfuscation step. The given
+ class name or class member name can't be kept by its original name, as
+ specified in the configuration, but it has to be mapped to the other given
+ name, as specified in the mapping file. You should adapt your
+ configuration or your mapping file to remove the conflict. Alternatively,
+ if you're sure the renaming won't hurt, you can specify the <a
+ href="usage.html#ignorewarnings"><code>-ignorewarnings</code></a> option,
+ or even the <a href="usage.html#dontwarn"><code>-dontwarn</code></a>
+ option.</dd>
+
+<dt><a name="mappingconflict2"><b>Warning: field/method ... can't be mapped to ...</b></a></dt>
+
+<dd>There is a conflict between some new program code and the mapping file, in
+ the obfuscation step. The given class member can't be mapped to the given
+ name, because it would conflict with another class member that is already
+ being mapped to the same name. This can happen if you are performing
+ incremental obfuscation, applying an obfuscation mapping file from an
+ initial obfuscation step. For instance, some new class may have been added
+ that extends two existing classes, introducing a conflict in the name
+ space of its class members. If you're sure the class member receiving
+ another name than the one specified won't hurt, you can specify the <a
+ href="usage.html#ignorewarnings"><code>-ignorewarnings</code></a> option,
+ or even the <a href="usage.html#dontwarn"><code>-dontwarn</code></a>
+ option. Note that you should always use the <a
+ href="usage.html#useuniqueclassmembernames"><code>-useuniqueclassmembernames</code></a>
+ option in the initial obfuscation step, in order to reduce the risk of
+ conflicts.</dd>
+
+<dt><a name="unsupportedclassversion"><b>Error: Unsupported class version number</b></a></dt>
+
+<dd>You are trying to process class files compiled for a recent version of
+ Java that your copy of ProGuard doesn't support yet. You
+ should <a href="http://proguard.sourceforge.net/downloads.html">check
+ on-line</a> if there is a more recent release.</dd>
+
+<dt><a name="keep"><b>Error: You have to specify '-keep' options</b></a></dt>
+
+<dd>You either forgot to specify <a
+ href="usage.html#keep"><code>-keep</code></a> options, or you mistyped the
+ class names. ProGuard has to know exactly what you want to keep: an
+ application, an applet, a servlet, a midlet,..., or any combination of
+ these. Without the proper seed specifications, ProGuard would shrink,
+ optimize, or obfuscate all class files away.</dd>
+
+<dt><a name="filename"><b>Error: Expecting class path separator ';' before 'Files\Java\</b>...<b>'</b> (in Windows)</a></dt>
+
+<dd>If the path of your run-time jar contains spaces, like in "Program Files",
+ you have to enclose it with single or double quotes, as explained in the
+ section on <a href="usage.html#filename">file names</a>. This is actually
+ true for all file names containing special characters, on all
+ platforms.</dd>
+
+<dt><a name="macosx"><b>Error: Can't read [</b>...<b>/lib/rt.jar] (No such file or directory)</b> (in MacOS X)</a></dt>
+
+<dd>In MacOS X, the run-time classes may be in a different place than on most
+ other platforms. You'll then have to adapt your configuration, replacing
+ the path <code>&lt;java.home&gt;/lib/rt.jar</code> by
+ <code>&lt;java.home&gt;/../Classes/classes.jar</code>.</dd>
+
+<dt><a name="cantread"><b>Error: Can't read ...</b></a></dt>
+
+<dd>ProGuard can't read the specified file or directory. Double-check that the
+ name is correct in your configuration, that the file is readable, and that
+ it is not corrupt. An additional message "Unexpected end of ZLIB input
+ stream" suggests that the file is truncated. You should then make sure
+ that the file is complete on disk when ProGuard starts (asynchronous
+ copying? unflushed buffer or cache?), and that it is not somehow
+ overwritten by ProGuard's own output.</dd>
+
+<dt><a name="cantwrite"><b>Error: Can't write ...</b></a></dt>
+
+<dd>ProGuard can't write the specified file or directory. Double-check that
+ the name is correct in your configuration and that the file is
+ writable.</dd>
+
+<dt><a name="startinggui"><b>Internal problem starting the ProGuard GUI (Cannot write XdndAware property)</b> (in Linux)</a></dt>
+
+<dd>In Linux, at least with Java 6, the GUI may not start properly, due to
+ <a href="http://bugs.sun.com/view_bug.do?bug_id=7027598">Sun
+ Bug #7027598</a>. The work-around at this time is to specify the JVM
+ option <code>-DsuppressSwingDropSupport=true</code> when running the
+ GUI.</dd>
+
+</dl>
+<p>
+
+Should ProGuard crash while processing your application:
+
+<dl>
+<dt><a name="outofmemoryerror"><b>OutOfMemoryError</b></a></dt>
+
+<dd>You can try increasing the heap size of the Java virtual machine, with the
+ usual <code>-Xmx</code> option:
+ <ul>
+ <li>In Java, specify the option as an argument to the JVM: <code>java
+ -Xmx1024m</code> ...
+ <li>In Ant, set the environment variable <code>ANT_OPTS=-Xmx1024m</code>
+ <li>In Gradle, set the environment variable
+ <code>GRADLE_OPTS=-Xmx1024m</code>
+ <li>In Maven, set the environment variable
+ <code>MAVEN_OPTS=-Xmx1024m</code>
+ <li>In Eclipse, add the line <code>-Xmx1024m</code> to the file
+ <code>eclipse.ini</code> inside your Eclipse install.
+ </ul>
+ You can also reduce the amount of memory that ProGuard needs by removing
+ unnecessary library jars from your configuration, or by filtering out
+ unused library packages and classes.</dd>
+
+<dt><a name="stackoverflowerror"><b>StackOverflowError</b></a></dt>
+
+<dd>This error might occur when processing a large code base on Windows
+ (surprisingly, not so easily on Linux). In theory, increasing the stack
+ size of the Java virtual machine (with the usual <code>-Xss</code> option)
+ should help too. In practice however, the <code>-Xss</code> setting
+ doesn't have any effect on the main thread, due to <a
+ href="http://bugs.sun.com/view_bug.do?bug_id=4362291">Sun Bug
+ #4362291</a>. As a result, this solution will only work when running
+ ProGuard in a different thread, e.g. from its GUI.</dd>
+
+<dt><a name="unexpectederror"><b>Unexpected error</b></a></dt>
+
+<dd>ProGuard has encountered an unexpected condition, typically in the
+ optimization step. It may or may not recover. You should be able to avoid
+ it using the <a
+ href="usage.html#dontoptimize"><code>-dontoptimize</code></a> option. In
+ any case, please report the problem, preferably with the simplest example
+ that causes ProGuard to crash.</dd>
+
+<dt><a name="otherwise"><b>Otherwise...</b></a></dt>
+
+<dd>Maybe your class files are corrupt. See if recompiling them and trying
+ again helps. If not, please report the problem, preferably with the
+ simplest example that causes ProGuard to crash.</dd>
+
+</dl>
+<p>
+
+<h2><a name="afterprocessing">Unexpected observations after processing</a></h2>
+
+If ProGuard seems to run fine, but your processed code doesn't look right,
+there might be a couple of reasons:
+
+<dl>
+<dt><a name="disappearingclasses"><b>Disappearing classes</b></a></dt>
+
+<dd>If you are working on Windows and it looks like some classes have
+ disappeared from your output, you should make sure you're not writing your
+ output class files to a directory (or unpacking the output jar). On
+ platforms with case-insensitive file systems, such as Windows, unpacking
+ tools often let class files with similar lower-case and upper-case names
+ overwrite each other. If you really can't switch to a different operating
+ system, you could consider using ProGuard's <a
+ href="usage.html#dontusemixedcaseclassnames"><code>-dontusemixedcaseclassnames</code></a>
+ option.
+ <p>
+ Also, you should make sure your class files are in directories that
+ correspond to their package names. ProGuard will read misplaced class
+ files, but it will currently not write their processed versions. Notably,
+ class files that are in the <code>WEB-INF/classes</code> directory in a
+ war should be packaged in a jar and put in the <code>WEB-INF/lib</code>
+ directory.</dd>
+
+<dt><a name="notkept"><b>Classes or class members not being kept</b></a></dt>
+
+<dd>If ProGuard is not keeping the right classes or class members, make sure
+ you are using fully qualified class names. If the package name of some
+ class is missing, ProGuard won't match the elements that you might be
+ expecting. It may help to double-check for typos too. You can use the <a
+ href="usage.html#printseeds"><code>-printseeds</code></a> option to see
+ which elements are being kept exactly.
+ <p>
+ If you are using marker interfaces to keep other classes, the marker
+ interfaces themselves are probably being removed in the shrinking step.
+ You should therefore always explicitly keep any marker interfaces, with
+ an option like "<code>-keep interface MyMarkerInterface</code>".
+ <p>
+ Similarly, if you are keeping classes based on annotations, you may have
+ to avoid that the annotation classes themselves are removed in the
+ shrinking step. You should package the annotation classes as a library, or
+ explicitly keep them in your program code with an option like "<code>-keep
+ @interface *</code>".</dd>
+
+<dt><a name="notobfuscated"><b>Variable names not being obfuscated</b></a></dt>
+
+<dd>If the names of the local variables and parameters in your obfuscated code
+ don't look obfuscated, because they suspiciously resemble the names of
+ their types, it's probably because the decompiler that you are using is
+ coming up with those names. ProGuard's obfuscation step does remove the
+ original names entirely, unless you explicitly keep the
+ <code>LocalVariableTable</code> or <code>LocalVariableTypeTable</code>
+ attributes.</dd>
+
+</dl>
+
+<h2><a name="dalvik">Problems while converting to Android Dalvik bytecode</a></h2>
+
+If ProGuard seems to run fine, but the dx tool in the Android SDK subsequently
+fails with an error:
+
+<dl>
+<dt><a name="simexception"><b>SimException: local variable type mismatch</b></a></dt>
+
+<dd>This error indicates that ProGuard's optimization step has not been able
+ to maintain the correct debug information about local variables. This can
+ happen if some code is optimized radically. Possible work-arounds: let the
+ java compiler not produce debug information (<code>-g:none</code>), or let
+ ProGuard's obfuscation step remove the debug information again
+ (by <i>not</i> keeping the attributes <code>LocalVariableTable</code>
+ and <code>LocalVariableTypeTable</code>
+ with <a href="usage.html#keepattributes"><code>-keepattributes</code></a>),
+ or otherwise just disable optimization
+ (<a href="usage.html#dontoptimize"><code>-dontoptimize</code></a>).</dd>
+
+<dt><a name="conversionerror"><b>Conversion to Dalvik format failed with error 1</b></a></dt>
+
+<dd>This error may have various causes, but if dx is tripping over some code
+ processed by ProGuard, you should make sure that you are using the latest
+ version of ProGuard. You can just copy the ProGuard jars
+ to <code>android-sdk/tools/proguard/lib</code>. If that doesn't help,
+ please report the problem, preferably with the simplest example that still
+ brings out the error.</dd>
+
+</dl>
+
+<h2><a name="preverifying">Problems while preverifying for Java Micro Edition</a></h2>
+
+If ProGuard seems to run fine, but the external preverifier subsequently
+produces errors, it's usually for a single reason:
+
+<dl>
+<dt><a name="invalidclassexception1"><b>InvalidClassException</b>, <b>class loading error</b>, or <b>verification error</b></a></dt>
+
+<dd>If you get any such message from the preverifier, you are probably working
+ on a platform with a case-insensitive file system, such as Windows. The
+ <code>preverify</code> tool always unpacks the jars, so class files with
+ similar lower-case and upper-case names overwrite each other. You can use
+ ProGuard's <a
+ href="usage.html#dontusemixedcaseclassnames"><code>-dontusemixedcaseclassnames</code></a>
+ option to work around this problem.
+ <p>
+ If the above doesn't help, there is probably a bug in the optimization
+ step of ProGuard. Make sure you are using the latest version. You should
+ be able to work around the problem by using the <a
+ href="usage.html#dontoptimize"><code>-dontoptimize</code></a> option. You
+ can check the bug database to see if it is a known problem (often with a
+ fix). Otherwise, please report it, preferably with the simplest example on
+ which you can find ProGuard to fail.</dd>
+
+</dl>
+
+Note that it is no longer necessary to use an external preverifier. With the
+<a href="usage.html#microedition"><code>-microedition</code></a> option,
+ProGuard will preverify the class files for Java Micro Edition.
+<p>
+
+<h2><a name="runtime">Problems at run-time</a></h2>
+
+If ProGuard runs fine, but your processed application doesn't work, there
+might be several reasons:
+
+<dl>
+<dt><a name="stacktraces"><b>Stack traces without class names or line numbers</b></a></dt>
+
+<dd>If your stack traces don't contain any class names or lines numbers,
+ even though you are keeping the proper attributes, make sure this debugging
+ information is present in your compiled code to start with. Notably the Ant
+ javac task has debugging information switched off by default.</dd>
+
+<dt><a name="noclassdeffounderror"><b>NoClassDefFoundError</b></a></dt>
+
+<dd>Your class path is probably incorrect. It should at least contain all
+ library jars and, of course, your processed program jar.</dd>
+
+<dt><a name="classnotfoundexception"><b>ClassNotFoundException</b></a></dt>
+
+<dd>Your code is probably calling <code>Class.forName</code>, trying to create
+ the missing class dynamically. ProGuard can only detect constant name
+ arguments, like <code>Class.forName("mypackage.MyClass")</code>. For
+ variable name arguments like <code>Class.forName(someClass)</code>, you
+ have to keep all possible classes using the appropriate <a
+ href="usage.html#keep"><code>-keep</code></a> option, e.g. "<code>-keep
+ class mypackage.MyClass</code>" or "<code>-keep class * implements
+ mypackage.MyInterface</code>".</dd>
+
+<dt><a name="nosuchfieldexception"><b>NoSuchFieldException</b></a></dt>
+
+<dd>Your code is probably calling something like
+ <code>myClass.getField</code>, trying to find some field dynamically.
+ Since ProGuard can't always detect this automatically, you have to keep
+ the missing field in using the
+ appropriate <a href="usage.html#keep"><code>-keep</code></a> option, e.g.
+ "<code>-keepclassmembers class mypackage.MyClass { int myField;
+ }</code>".</dd>
+
+<dt><a name="nosuchmethodexception"><b>NoSuchMethodException</b></a></dt>
+
+<dd>Your code is probably calling something like
+ <code>myClass.getMethod</code>, trying to find some method dynamically.
+ Since ProGuard can't always detect this automatically, you have to keep
+ the missing method in using the
+ appropriate <a href="usage.html#keep"><code>-keep</code></a> option, e.g.
+ "<code>-keepclassmembers class mypackage.MyClass { void myMethod();
+ }</code>".
+ <p>
+ More specifically, if the method reported as missing is
+ <code>values</code> or <code>valueOf</code>, you probably have to keep
+ some methods related to <a
+ href="examples.html#enumerations">enumerations</a>.</dd>
+
+<dt><a name="missingresourceexception"><b>MissingResourceException</b> or <b>NullPointerException</b></a></dt>
+
+<dd>Your processed code may be unable to find some resource files. ProGuard
+ simply copies resource files over from the input jars to the output jars.
+ Their names and contents remain unchanged, unless you specify the options
+ <a
+ href="usage.html#adaptresourcefilenames"><code>-adaptresourcefilenames</code></a>
+ and/or <a
+ href="usage.html#adaptresourcefilecontents"><code>-adaptresourcefilecontents</code></a>.
+ <p>
+ Furthermore, directory entries in jar files aren't copied, unless you
+ specify the option <a
+ href="usage.html#keepdirectories"><code>-keepdirectories</code></a>.
+ Note that Sun advises against calling <code>Class.getResource()</code> for
+ directories (<a href="http://bugs.sun.com/view_bug.do?bug_id=4761949">Sun
+ Bug #4761949</a>).</dd>
+
+<dt><a name="disappearingannotations"><b>Disappearing annotations</b></a></dt>
+
+<dd>By default, the obfuscation step removes all annotations. If your
+ application relies on annotations to function properly, you should
+ explicitly keep them with
+ <code><a href="usage.html#keepattributes">-keepattributes</a>
+ *Annotation*</code>.</dd>
+
+<dt><a name="invalidjarfile"><b>Invalid or corrupt jarfile</b></a></dt>
+
+<dd>You are probably starting your application with the java option
+ <code>-jar</code> instead of the option <code>-classpath</code>. The java
+ virtual machine returns with this error message if your jar doesn't
+ contain a manifest file (<code>META-INF/MANIFEST.MF</code>), if the
+ manifest file doesn't specify a main class (<code>Main-Class:</code> ...),
+ or if the jar doesn't contain this main class. You should then make sure
+ that the input jar contains a valid manifest file to start with, that this
+ manifest file is the one that is copied (the first manifest file that is
+ encountered), and that the main class is kept in your configuration,</dd>
+
+<dt><a name="invalidjarindexexception"><b>InvalidJarIndexException: Invalid index</b></a></dt>
+
+<dd>At least one of your processed jar files contains an index file
+ <code>META-INF/INDEX.LIST</code>, listing all class files in the jar.
+ ProGuard by default copies files like these unchanged. ProGuard may however
+ remove or rename classes, thus invalidating the file. You should filter the
+ index file out of the input
+ (<code>-injars in.jar(!META-INF/INDEX.LIST)</code>) or update the file
+ after having applied ProGuard (<code>jar -i out.jar</code>).
+ </dd>
+
+<dt><a name="invalidclassexception2"><b>InvalidClassException</b>, <b>class loading error</b>, or <b>verification error</b> (in Java Micro Edition)</a></dt>
+
+<dd>If you get such an error in Java Micro Edition, you may have forgotten to
+ specify the <a
+ href="usage.html#microedition"><code>-microedition</code></a> option, so
+ the processed class files are preverified properly.</dd>
+
+<dt><a name="nosuchfieldormethod"><b>Error: No Such Field or Method</b>, <b>Error verifying method</b> (in a Java Micro Edition emulator)</a></dt>
+
+<dd>If you get such a message in a Motorola or Sony Ericsson phone emulator,
+ it's because these emulators don't like packageless classes and/or
+ overloaded fields and methods. You can work around it by not using the
+ options <code><a href="usage.html#repackageclasses">-repackageclasses</a>
+ ''</code> and <a
+ href="usage.html#overloadaggressively"><code>-overloadaggressively</code></a>.
+ If you're using the JME WTK plugin, you can adapt the configuration
+ <code>proguard/wtk/default.pro</code> that's inside the
+ <code>proguard.jar</code>.</dd>
+
+<dt><a name="failingmidlets"><b>Failing midlets</b> (on a Java Micro Edition device)</a></dt>
+
+<dd>If your midlet runs in an emulator and on some devices, but not on some
+ other devices, this is probably due to a bug in the latter devices. For
+ some older Motorola and Nokia phones, you might try specifying the <a
+ href="usage.html#useuniqueclassmembernames"><code>-useuniqueclassmembernames</code></a>
+ option. It avoids overloading class member names, which triggers a bug in
+ their java virtual machine.
+ <p>
+ You might also try using the <a
+ href="usage.html#dontusemixedcaseclassnames"><code>-dontusemixedcaseclassnames</code></a>
+ option. Even if the midlet has been properly processed and then
+ preverified on a case-sensitive file system, the device itself might not
+ like the mixed-case class names. Notably, the Nokia N-Gage emulator works
+ fine, but the actual device seems to exhibit this problem.</dd>
+
+<dt><a name="disappearingloops"><b>Disappearing loops</b></a></dt>
+
+<dd>If your code contains empty busy-waiting loops, ProGuard's optimization
+ step may remove them. More specifically, this happens if a loop
+ continuously checks the value of a non-volatile field that is changed in a
+ different thread. The specifications of the Java Virtual Machine require
+ that you always mark fields that are accessed across different threads
+ without further synchronization as <code>volatile</code>. If this is not
+ possible for some reason, you'll have to switch off optimization using the
+ <a href="usage.html#dontoptimize"><code>-dontoptimize</code></a>
+ option.</dd>
+
+<dt><a name="securityexception"><b>SecurityException: SHA1 digest error</b></a></dt>
+
+<dd>You may have forgotten to sign your program jar <i>after</i> having
+ processed it with ProGuard.</dd>
+
+<dt><a name="classcastexception"><b>ClassCastException: class not an enum</b>, or <br /><b>IllegalArgumentException: class not an enum type</b></a></dt>
+
+<dd>You should make sure you're preserving the special methods of enumeration
+ types, which the run-time environment calls by introspection. The required
+ options are shown in the <a
+ href="examples.html#enumerations">examples</a>.</dd>
+
+<dt><a name="arraystoreexception"><b>ArrayStoreException: sun.reflect.annotation.EnumConstantNotPresentExceptionProxy</b></a></dt>
+
+<dd>You are probably processing annotations involving enumerations. Again, you
+ should make sure you're preserving the special methods of the enumeration
+ type, as shown in the examples.</dd>
+
+<dt><a name="illegalargumentexception"><b>IllegalArgumentException: methods with same signature but incompatible return types</b></a></dt>
+
+<dd>You are probably running some code that has been obfuscated
+ with the <a
+ href="usage.html#overloadaggressively"><code>-overloadaggressively</code></a>
+ option. The class <code>java.lang.reflect.Proxy</code> can't handle
+ classes that contain methods with the same names and signatures, but
+ different return types. Its method <code>newProxyInstance</code> then
+ throws this exception. You can avoid the problem by not using the
+ option.</dd>
+
+<dt><a name="compilererror"><b>CompilerError: duplicate addition</b></a></dt>
+
+<dd>You are probably compiling or running some code that has been obfuscated
+ with the <a
+ href="usage.html#overloadaggressively"><code>-overloadaggressively</code></a>
+ option. This option triggers a bug in
+ <code>sun.tools.java.MethodSet.add</code> in Sun's JDK 1.2.2, which is
+ used for (dynamic) compilation. You should then avoid this option.</dd>
+
+<dt><a name="classformaterror1"><b>ClassFormatError: repetitive field name/signature</b></a></dt>
+
+<dd>You are probably processing some code that has been obfuscated before with
+ the <a
+ href="usage.html#overloadaggressively"><code>-overloadaggressively</code></a>
+ option. You should then use the same option again in the second processing
+ round.</dd>
+
+<dt><a name="classformaterror2"><b>ClassFormatError: Invalid index in LocalVariableTable in class file</b></a></dt>
+
+<dd>If you are keeping the <code>LocalVariableTable</code> or
+ <code>LocalVariableTypeTable</code> attributes, ProGuard's optimizing step
+ is sometimes unable to update them consistently. You should then let the
+ obfuscation step remove these attributes or disable the optimization
+ step.</dd>
+
+<dt><a name="nosuchmethoderror"><b>NoSuchMethodError</b> or <b>AbstractMethodError</b></a></dt>
+
+<dd>You should make sure you're not writing your output class files to a
+ directory on a platform with a case-insensitive file system, such as
+ Windows. Please refer to the section about <a
+ href="#disappearingclasses">disappearing classes</a> for details.
+ <p>
+ Furthermore, you should check whether you have specified your program jars
+ and library jars properly. Program classes can refer to library classes,
+ but not the other way around.
+ <p>
+ If all of this seems ok, perhaps there's a bug in ProGuard (gasp!). If so,
+ please report it, preferably with the simplest example on which you can
+ find ProGuard to fail.</dd>
+
+<dt><a name="verifyerror"><b>VerifyError</b></a></dt>
+
+<dd>Verification errors when executing a program are almost certainly the
+ result of a bug in the optimization step of ProGuard. Make sure you are
+ using the latest version. You should be able to work around the problem by
+ using the <a href="usage.html#dontoptimize"><code>-dontoptimize</code></a>
+ option. You can check the bug database to see if it is a known problem
+ (often with a fix). Otherwise, please report it, preferably with the
+ simplest example on which ProGuard fails.</dd>
+
+</dl>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/usage.html b/third_party/java/proguard/proguard5.3.3/docs/manual/usage.html
new file mode 100644
index 0000000000..5ed5e6654c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/usage.html
@@ -0,0 +1,1271 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Usage</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/usage.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/usage.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Usage</h2>
+
+To run ProGuard, just type:
+<p class="code">
+<code><b>java -jar proguard.jar </b></code><i>options</i> ...
+</p>
+You can find the ProGuard jar in the <code>lib</code> directory of the
+ProGuard distribution. Alternatively, the <code>bin</code> directory contains
+some short Linux and Windows scripts containing this command. Typically, you'll
+put most options in a configuration file (say, <code>myconfig.pro</code>), and
+just call:
+<p class="code">
+<code><b>java -jar proguard.jar @myconfig.pro</b></code>
+</p>
+You can combine command line options and options from configuration files. For
+instance:
+<p class="code">
+<code><b>java -jar proguard.jar @myconfig.pro -verbose</b></code>
+</p>
+<p>
+You can add comments in a configuration file, starting with a
+<code><b>#</b></code> character and continuing until the end of the line.
+<p>
+Extra whitespace between words and delimiters is ignored. File names with
+spaces or special characters should be quoted with single or double quotes.
+<p>
+Options can be grouped arbitrarily in arguments on the command line and in
+lines in configuration files. This means that you can quote arbitrary sections
+of command line options, to avoid shell expansion of special characters, for
+instance.
+<p>
+The order of the options is generally irrelevant. For quick experiments, you
+can abbreviate them to their first unique characters.
+<p>
+
+The sections below provide more details:
+<ul>
+<li><a href="#iooptions">Input/Output Options</a></li>
+<li><a href="#keepoptions">Keep Options</a></li>
+<li><a href="#shrinkingoptions">Shrinking Options</a></li>
+<li><a href="#optimizationoptions">Optimization Options</a></li>
+<li><a href="#obfuscationoptions">Obfuscation Options</a></li>
+<li><a href="#preverificationoptions">Preverification Options</a></li>
+<li><a href="#generaloptions">General Options</a></li>
+<li><a href="#classpath">Class Paths</a></li>
+<li><a href="#filename">File Names</a></li>
+<li><a href="#filefilters">File Filters</a></li>
+<li><a href="#filters">Filters</a></li>
+<li><a href="#keepoverview">Overview of <code>Keep</code> Options</a></li>
+<li><a href="#keepoptionmodifiers">Keep Option Modifiers</a></li>
+<li><a href="#classspecification">Class Specifications</a></li>
+</ul>
+
+<h2><a name="iooptions">Input/Output Options</a></h2>
+
+<dl>
+<dt><a name="at"><code><b>@</b></code></a><a href="#filename"><i>filename</i></a></dt>
+
+<dd>Short for '<a href="#include"><code>-include</code></a>
+ <a href="#filename"><i>filename</i></a>'.</dd>
+
+<dt><a name="include"><code><b>-include</b></code></a>
+ <a href="#filename"><i>filename</i></a></dt>
+
+<dd>Recursively reads configuration options from the given file
+ <i>filename</i>.</dd>
+
+<dt><a name="basedirectory"><code><b>-basedirectory</b></code></a>
+ <a href="#filename"><i>directoryname</i></a></dt>
+
+<dd>Specifies the base directory for all subsequent relative file names in
+ these configuration arguments or this configuration file.</dd>
+
+<dt><a name="injars"><code><b>-injars</b></code></a>
+ <a href="#classpath"><i>class_path</i></a></dt>
+
+<dd>Specifies the input jars (or aars, wars, ears, zips, apks, or directories)
+ of the application to be processed. The class files in these jars will be
+ processed and written to the output jars. By default, any non-class files
+ will be copied without changes. Please be aware of any temporary files
+ (e.g. created by IDEs), especially if you are reading your input files
+ straight from directories. The entries in the class path can be filtered,
+ as explained in the <a href="#filefilters">filters</a> section. For better
+ readability, class path entries can be specified using multiple
+ <code>-injars</code> options.</dd>
+
+<dt><a name="outjars"><code><b>-outjars</b></code></a>
+ <a href="#classpath"><i>class_path</i></a></dt>
+
+<dd>Specifies the names of the output jars (or aars, wars, ears, zips, apks,
+ or directories). The processed input of the preceding <code>-injars</code>
+ options will be written to the named jars. This allows you to collect the
+ contents of groups of input jars into corresponding groups of output jars.
+ In addition, the output entries can be filtered, as explained in
+ the <a href="#filefilters">filters</a> section. Each processed class file
+ or resource file is then written to the first output entry with a matching
+ filter, within the group of output jars.
+ <p>
+ You must avoid letting the output files overwrite any input files. For
+ better readability, class path entries can be specified using multiple
+ <code>-outjars</code> options. Without any <code>-outjars</code> options,
+ no jars will be written.</dd>
+
+<dt><a name="libraryjars"><code><b>-libraryjars</b></code></a>
+ <a href="#classpath"><i>class_path</i></a></dt>
+
+<dd>Specifies the library jars (or aars, wars, ears, zips, apks, or
+ directories) of the application to be processed. The files in these jars
+ will not be included in the output jars. The specified library jars should
+ at least contain the class files that are <i>extended</i> by application
+ class files. Library class files that are only <i>called</i> needn't be
+ present, although their presence can improve the results of the
+ optimization step. The entries in the class path can be filtered, as
+ explained in the <a href="#filefilters">filters</a> section. For better
+ readability, class path entries can be specified using
+ multiple <code>-libraryjars</code> options.
+ <p>
+ Please note that the boot path and the class path set for running ProGuard
+ are not considered when looking for library classes. This means that you
+ explicitly have to specify the run-time jar that your code will use.
+ Although this may seem cumbersome, it allows you to process applications
+ targeted at different run-time environments. For example, you can process
+ <a href="examples.html#application">J2SE applications</a> as well as <a
+ href="examples.html#midlet">JME midlets</a> or <a
+ href="examples.html#androidapplication">Android apps</a>, just by
+ specifying the appropriate run-time jar.</dd>
+
+<dt><a name="skipnonpubliclibraryclasses"><code><b>-skipnonpubliclibraryclasses</b></code></a></dt>
+
+<dd>Specifies to skip non-public classes while reading library jars, to speed
+ up processing and reduce memory usage of ProGuard. By default, ProGuard
+ reads non-public and public library classes alike. However, non-public
+ classes are often not relevant, if they don't affect the actual program
+ code in the input jars. Ignoring them then speeds up ProGuard, without
+ affecting the output. Unfortunately, some libraries, including recent JSE
+ run-time libraries, contain non-public library classes that are extended
+ by public library classes. You then can't use this option. ProGuard will
+ print out warnings if it can't find classes due to this option being
+ set.</dd>
+
+<dt><a name="dontskipnonpubliclibraryclasses"><code><b>-dontskipnonpubliclibraryclasses</b></code></a></dt>
+
+<dd>Specifies not to ignore non-public library classes. As of version 4.5, this
+ is the default setting.</dd>
+
+<dt><a name="dontskipnonpubliclibraryclassmembers"><code><b>-dontskipnonpubliclibraryclassmembers</b></code></a></dt>
+
+<dd>Specifies not to ignore package visible library class members (fields and
+ methods). By default, ProGuard skips these class members while parsing
+ library classes, as program classes will generally not refer to them.
+ Sometimes however, program classes reside in the same packages as library
+ classes, and they do refer to their package visible class members. In
+ those cases, it can be useful to actually read the class members, in order
+ to make sure the processed code remains consistent.</dd>
+
+<dt><a name="keepdirectories"><code><b>-keepdirectories</b></code></a>
+ [<i><a href="#filefilters">directory_filter</a></i>]</dt>
+
+<dd>Specifies the directories to be kept in the output jars (or aars, wars,
+ ears, zips, apks, or directories). By default, directory entries are
+ removed. This reduces the jar size, but it may break your program if the
+ code tries to find them with constructs like
+ "<code>mypackage.MyClass.class.getResource("")</code>". You'll then want
+ to keep the directory corresponding to the package,
+ "<code>-keepdirectories mypackage</code>". If the option is specified
+ without a filter, all directories are kept. With a filter, only matching
+ directories are kept. For instance,
+ "<code>-keepdirectories mydirectory</code>" matches the specified
+ directory, "<code>-keepdirectories mydirectory/*</code>" matches its
+ immediate subdirectories, and
+ "<code>-keepdirectories mydirectory/**</code>" matches all of its
+ subdirectories.</dd>
+
+<dt><a name="target"><code><b>-target</b></code></a> <i>version</i></dt>
+
+<dd>Specifies the version number to be set in the processed class files. The
+ version number can be one of <code>1.0</code>, <code>1.1</code>,
+ <code>1.2</code>, <code>1.3</code>, <code>1.4</code>, <code>1.5</code> (or
+ just <code>5</code>), <code>1.6</code> (or just <code>6</code>),
+ <code>1.7</code> (or just <code>7</code>), or <code>1.8</code> (or
+ just <code>8</code>). By default, the version numbers of the class files
+ are left unchanged. For example, you may want to
+ <a href="examples.html#upgrade">upgrade class files to Java 6</a>, by
+ changing their version numbers and having them preverified. You probably
+ shouldn't downgrade the version numbers of class files, since the code
+ may contain constructs that are not supported in older versions.</dd>
+
+<dt><a name="forceprocessing"><code><b>-forceprocessing</b></code></a></dt>
+
+<dd>Specifies to process the input, even if the output seems up to date. The
+ up-to-dateness test is based on a comparison of the date stamps of the
+ specified input, output, and configuration files or directories.</dd>
+
+</dl>
+<p>
+
+<h2><a name="keepoptions">Keep Options</a></h2>
+
+<dl>
+<dt><a name="keep"><code><b>-keep</b></code></a>
+ [<a href="#keepoptionmodifiers">,<i>modifier</i></a>,...]
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+
+<dd>Specifies classes and class members (fields and methods) to be preserved
+ as entry points to your code. For example, in order to <a
+ href="examples.html#application">keep an application</a>, you can specify
+ the main class along with its main method. In order to <a
+ href="examples.html#library">process a library</a>, you should specify all
+ publicly accessible elements.</dd>
+
+<dt><a name="keepclassmembers"><code><b>-keepclassmembers</b></code></a>
+ [<a href="#keepoptionmodifiers">,<i>modifier</i></a>,...]
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+
+<dd>Specifies class members to be preserved, if their classes are preserved as
+ well. For example, you may want to <a
+ href="examples.html#serializable">keep all serialization fields and
+ methods</a> of classes that implement the <code>Serializable</code>
+ interface.</dd>
+
+<dt><a name="keepclasseswithmembers"><code><b>-keepclasseswithmembers</b></code></a>
+ [<a href="#keepoptionmodifiers">,<i>modifier</i></a>,...]
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+
+<dd>Specifies classes and class members to be preserved, on the condition that
+ all of the specified class members are present. For example, you may want
+ to <a href="examples.html#applications">keep all applications</a> that
+ have a main method, without having to list them explicitly.</dd>
+
+<dt><a name="keepnames"><code><b>-keepnames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+
+<dd>Short for <a href="#keep"><code>-keep</code></a>,<a href="#allowshrinking"><code>allowshrinking</code></a>
+ <a href="#classspecification"><i>class_specification</i></a>
+ <p>
+ Specifies classes and class members whose names are to be preserved, if
+ they aren't removed in the shrinking phase. For example, you may want to
+ <a href="examples.html#serializable">keep all class names</a> of classes
+ that implement the <code>Serializable</code> interface, so that the
+ processed code remains compatible with any originally serialized classes.
+ Classes that aren't used at all can still be removed. Only applicable when
+ obfuscating.</dd>
+
+<dt><a name="keepclassmembernames"><code><b>-keepclassmembernames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+
+<dd>Short for <a href="#keepclassmembers"><code>-keepclassmembers</code></a>,<a href="#allowshrinking"><code>allowshrinking</code></a>
+ <a href="#classspecification"><i>class_specification</i></a>
+ <p>
+ Specifies class members whose names are to be preserved, if they aren't
+ removed in the shrinking phase. For example, you may want to preserve the
+ name of the synthetic <code>class$</code> methods
+ when <a href="examples.html#library">processing a library</a> compiled by
+ JDK 1.2 or older, so obfuscators can detect it again when processing an
+ application that uses the processed library (although ProGuard itself
+ doesn't need this). Only applicable when obfuscating.</dd>
+
+<dt><a name="keepclasseswithmembernames"><code><b>-keepclasseswithmembernames</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+
+<dd>Short for <a href="#keepclasseswithmembers"><code>-keepclasseswithmembers</code></a>,<a href="#allowshrinking"><code>allowshrinking</code></a>
+ <a href="#classspecification"><i>class_specification</i></a>
+ <p>
+ Specifies classes and class members whose names are to be preserved, on
+ the condition that all of the specified class members are present after
+ the shrinking phase. For example, you may want to <a
+ href="examples.html#native">keep all native method names</a> and the names
+ of their classes, so that the processed code can still link with the
+ native library code. Native methods that aren't used at all can still be
+ removed. If a class file is used, but none of its native methods are, its
+ name will still be obfuscated. Only applicable when obfuscating.</dd>
+
+<dt><a name="printseeds"><code><b>-printseeds</b></code></a>
+ [<a href="#filename"><i>filename</i></a>]</dt>
+
+<dd>Specifies to exhaustively list classes and class members matched by the
+ various <code>-keep</code> options. The list is printed to the standard
+ output or to the given file. The list can be useful to verify if the
+ intended class members are really found, especially if you're using
+ wildcards. For example, you may want to list all the <a
+ href="examples.html#applications">applications</a> or all the <a
+ href="examples.html#applets">applets</a> that you are keeping.</dd>
+
+</dl>
+<p>
+
+<h2><a name="shrinkingoptions">Shrinking Options</a></h2>
+
+<dl>
+<dt><a name="dontshrink"><code><b>-dontshrink</b></code></a></dt>
+
+<dd>Specifies not to shrink the input class files. By default, shrinking is
+ applied; all classes and class members are removed, except for the ones
+ listed by the various <code>-keep</code> options, and the ones on which
+ they depend, directly or indirectly. A shrinking step is also applied
+ after each optimization step, since some optimizations may open the
+ possibility to remove more classes and class members.</dd>
+
+<dt><a name="printusage"><code><b>-printusage</b></code></a>
+ [<a href="#filename"><i>filename</i></a>]</dt>
+
+<dd>Specifies to list dead code of the input class files. The list is printed
+ to the standard output or to the given file. For example, you can <a
+ href="examples.html#deadcode">list the unused code of an application</a>.
+ Only applicable when shrinking.</dd>
+
+<dt><a name="whyareyoukeeping"><code><b>-whyareyoukeeping</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+
+<dd>Specifies to print details on why the given classes and class members are
+ being kept in the shrinking step. This can be useful if you are wondering
+ why some given element is present in the output. In general, there can be
+ many different reasons. This option prints the shortest chain of methods
+ to a specified seed or entry point, for each specified class and class
+ member. <i>In the current implementation, the shortest chain that is
+ printed out may sometimes contain circular deductions -- these do not
+ reflect the actual shrinking process.</i> If the <a
+ href="#verbose"><code>-verbose</code></a> option if specified, the traces
+ include full field and method signatures. Only applicable when
+ shrinking.</dd>
+
+</dl>
+<p>
+
+<h2><a name="optimizationoptions">Optimization Options</a></h2>
+
+<dl>
+<dt><a name="dontoptimize"><code><b>-dontoptimize</b></code></a></dt>
+
+<dd>Specifies not to optimize the input class files. By default, optimization
+ is enabled; all methods are optimized at a bytecode level.</dd>
+
+<dt><a name="optimizations"><code><b>-optimizations</b></code></a>
+ <a href="optimizations.html"><i>optimization_filter</i></a></dt>
+
+<dd>Specifies the optimizations to be enabled and disabled, at a more
+ fine-grained level. Only applicable when optimizing. <i>This is an expert
+ option.</i></dd>
+
+<dt><a name="optimizationpasses"><code><b>-optimizationpasses</b></code></a> <i>n</i></dt>
+
+<dd>Specifies the number of optimization passes to be performed. By default, a
+ single pass is performed. Multiple passes may result in further
+ improvements. If no improvements are found after an optimization pass, the
+ optimization is ended. Only applicable when optimizing.</dd>
+
+<dt><a name="assumenosideeffects"><code><b>-assumenosideeffects</b></code></a>
+ <a href="#classspecification"><i>class_specification</i></a></dt>
+
+<dd>Specifies methods that don't have any side effects (other than maybe
+ returning a value). In the optimization step, ProGuard will then remove
+ calls to such methods, if it can determine that the return values aren't
+ used. ProGuard will analyze your program code to find such methods
+ automatically. It will not analyze library code, for which this option can
+ therefore be useful. For example, you could specify the method
+ <code>System.currentTimeMillis()</code>, so that any idle calls to it will
+ be removed. With some care, you can also use the option to
+ <a href="examples.html#logging">remove logging code</a>. Note that
+ ProGuard applies the option to the entire hierarchy of the specified
+ methods. Only applicable when optimizing. In general, making assumptions
+ can be dangerous; you can easily break the processed code. <i>Only use
+ this option if you know what you're doing!</i></dd>
+
+<dt><a name="allowaccessmodification"><code><b>-allowaccessmodification</b></code></a></dt>
+
+<dd>Specifies that the access modifiers of classes and class members may be
+ broadened during processing. This can improve the results of the
+ optimization step. For instance, when inlining a public getter, it may be
+ necessary to make the accessed field public too. Although Java's binary
+ compatibility specifications formally do not require this (cfr. <a href=
+ "http://docs.oracle.com/javase/specs/jls/se5.0/html/j3TOC.html"
+ >The Java Language Specification, Third Edition</a>, <a href=
+ "http://docs.oracle.com/javase/specs/jls/se5.0/html/binaryComp.html#13.4.6"
+ >Section 13.4.6</a>), some virtual machines would have problems with the
+ processed code otherwise. Only applicable when optimizing (and when
+ obfuscating with the <a
+ href="#repackageclasses"><code>-repackageclasses</code></a> option).
+ <p>
+ <i>Counter-indication:</i> you probably shouldn't use this option when
+ processing code that is to be used as a library, since classes and class
+ members that weren't designed to be public in the API may become
+ public.</dd>
+
+<dt><a name="mergeinterfacesaggressively"><code><b>-mergeinterfacesaggressively</b></code></a></dt>
+
+<dd>Specifies that interfaces may be merged, even if their implementing
+ classes don't implement all interface methods. This can reduce the size of
+ the output by reducing the total number of classes. Note that Java's
+ binary compatibility specifications allow such constructs (cfr. <a href=
+ "http://docs.oracle.com/javase/specs/jls/se5.0/html/j3TOC.html"
+ >The Java Language Specification, Third Edition</a>, <a href=
+ "http://docs.oracle.com/javase/specs/jls/se5.0/html/binaryComp.html#13.5.3"
+ >Section 13.5.3</a>), even if they are not allowed in the Java language
+ (cfr. <a href=
+ "http://docs.oracle.com/javase/specs/jls/se5.0/html/j3TOC.html"
+ >The Java Language Specification, Third Edition</a>, <a href=
+ "http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#8.1.4"
+ >Section 8.1.4</a>). Only applicable when optimizing.
+ <p>
+ <i>Counter-indication:</i> setting this option can reduce the performance
+ of the processed code on some JVMs, since advanced just-in-time
+ compilation tends to favor more interfaces with fewer implementing
+ classes. Worse, some JVMs may not be able to handle the resulting code.
+ Notably:
+ <ul>
+ <li>Sun's JRE 1.3 may throw an <code>InternalError</code> when
+ encountering more than 256 <i>Miranda</i> methods (interface methods
+ without implementations) in a class.</li>
+ </ul></dd>
+
+</dl>
+<p>
+
+<h2><a name="obfuscationoptions">Obfuscation Options</a></h2>
+
+<dl>
+<dt><a name="dontobfuscate"><code><b>-dontobfuscate</b></code></a></dt>
+
+<dd>Specifies not to obfuscate the input class files. By default, obfuscation
+ is applied; classes and class members receive new short random names,
+ except for the ones listed by the various <code>-keep</code> options.
+ Internal attributes that are useful for debugging, such as source files
+ names, variable names, and line numbers are removed.</dd>
+
+<dt><a name="printmapping"><code><b>-printmapping</b></code></a>
+ [<a href="#filename"><i>filename</i></a>]</dt>
+
+<dd>Specifies to print the mapping from old names to new names for classes and
+ class members that have been renamed. The mapping is printed to the
+ standard output or to the given file. For example, it is required for
+ subsequent <a href="examples.html#incremental">incremental
+ obfuscation</a>, or if you ever want to make sense again of <a
+ href="examples.html#stacktrace">obfuscated stack traces</a>. Only
+ applicable when obfuscating.</dd>
+
+<dt><a name="applymapping"><code><b>-applymapping</b></code></a>
+ <a href="#filename"><i>filename</i></a></dt>
+
+<dd>Specifies to reuse the given name mapping that was printed out in a
+ previous obfuscation run of ProGuard. Classes and class members that are
+ listed in the mapping file receive the names specified along with them.
+ Classes and class members that are not mentioned receive new names. The
+ mapping may refer to input classes as well as library classes. This option
+ can be useful for <a href="examples.html#incremental">incremental
+ obfuscation</a>, i.e. processing add-ons or small patches to an existing
+ piece of code. If the structure of the code changes fundamentally,
+ ProGuard may print out warnings that applying a mapping is causing
+ conflicts. You may be able to reduce this risk by specifying the option <a
+ href="#useuniqueclassmembernames"><code>-useuniqueclassmembernames</code></a>
+ in both obfuscation runs. Only a single mapping file is allowed. Only
+ applicable when obfuscating.</dd>
+
+<dt><a name="obfuscationdictionary"><code><b>-obfuscationdictionary</b></code></a>
+ <a href="#filename"><i>filename</i></a></dt>
+
+<dd>Specifies a text file from which all valid words are used as obfuscated
+ field and method names. By default, short names like 'a', 'b', etc. are
+ used as obfuscated names. With an obfuscation dictionary, you can specify
+ a list of reserved key words, or identifiers with foreign characters, for
+ instance. White space, punctuation characters, duplicate words, and
+ comments after a <code><b>#</b></code> sign are ignored. Note that an
+ obfuscation dictionary hardly improves the obfuscation. Decent compilers
+ can automatically replace them, and the effect can fairly simply be undone
+ by obfuscating again with simpler names. The most useful application is
+ specifying strings that are typically already present in class files (such
+ as 'Code'), thus reducing the class file sizes just a little bit more.
+ Only applicable when obfuscating.</dd>
+
+<dt><a name="classobfuscationdictionary"><code><b>-classobfuscationdictionary</b></code></a>
+ <a href="#filename"><i>filename</i></a></dt>
+
+<dd>Specifies a text file from which all valid words are used as obfuscated
+ class names. The obfuscation dictionary is similar to the one of the
+ option <a
+ href="#obfuscationdictionary"><code>-obfuscationdictionary</code></a>.
+ Only applicable when obfuscating.</dd>
+
+<dt><a name="packageobfuscationdictionary"><code><b>-packageobfuscationdictionary</b></code></a>
+ <a href="#filename"><i>filename</i></a></dt>
+
+<dd>Specifies a text file from which all valid words are used as obfuscated
+ package names. The obfuscation dictionary is similar to the one of the
+ option <a
+ href="#obfuscationdictionary"><code>-obfuscationdictionary</code></a>.
+ Only applicable when obfuscating.</dd>
+
+<dt><a name="overloadaggressively"><code><b>-overloadaggressively</b></code></a></dt>
+
+<dd>Specifies to apply aggressive overloading while obfuscating. Multiple
+ fields and methods can then get the same names, as long as their arguments
+ and return types are different, as required by Java bytecode (not just
+ their arguments, as required by the Java language). This option can make
+ the processed code even smaller (and less comprehensible). Only applicable
+ when obfuscating.
+ <p>
+ <i>Counter-indication:</i> the resulting class files fall within the Java
+ bytecode specification (cfr. <a href=
+ "http://docs.oracle.com/javase/specs/jvms/se5.0/html/VMSpecTOC.doc.html"
+ >The Java Virtual Machine Specification, Second Edition</a>, first
+ paragraphs of <a href=
+ "http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#2877"
+ >Section 4.5</a> and <a href=
+ "http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#1513"
+ >Section 4.6</a>), even though this kind of overloading is not allowed in
+ the Java language (cfr. <a href=
+ "http://docs.oracle.com/javase/specs/jls/se5.0/html/j3TOC.html"
+ >The Java Language Specification, Third Edition</a>, <a href=
+ "http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#8.3"
+ >Section 8.3</a> and <a href=
+ "http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#8.4.5"
+ >Section 8.4.5</a>). Still, some tools have problems with it. Notably:
+ <ul>
+ <li>Sun's JDK 1.2.2 <code>javac</code> compiler produces an exception when
+ compiling with such a library (cfr. <a href=
+ "http://bugs.sun.com/view_bug.do?bug_id=4216736">Bug #4216736</a>).
+ You probably shouldn't use this option for processing libraries.</li>
+ <li>Sun's JRE 1.4 and later fail to serialize objects with overloaded
+ primitive fields.</li>
+ <li>Sun's JRE 1.5 <code>pack200</code> tool reportedly has problems with
+ overloaded class members.</li>
+ <li>The class <code>java.lang.reflect.Proxy</code> can't handle overloaded
+ methods.</li>
+ <li>Google's Dalvik VM can't handle overloaded static fields.</li>
+ </ul></dd>
+
+<dt><a name="useuniqueclassmembernames"><code><b>-useuniqueclassmembernames</b></code></a></dt>
+
+<dd>Specifies to assign the same obfuscated names to class members that have
+ the same names, and different obfuscated names to class members that have
+ different names (for each given class member signature). Without the
+ option, more class members can be mapped to the same short names like 'a',
+ 'b', etc. The option therefore increases the size of the resulting code
+ slightly, but it ensures that the saved obfuscation name mapping can
+ always be respected in subsequent incremental obfuscation steps.
+ <p>
+ For instance, consider two distinct interfaces containing methods with the
+ same name and signature. Without this option, these methods may get
+ different obfuscated names in a first obfuscation step. If a patch is then
+ added containing a class that implements both interfaces, ProGuard will
+ have to enforce the same method name for both methods in an incremental
+ obfuscation step. The original obfuscated code is changed, in order to
+ keep the resulting code consistent. With this option <i>in the initial
+ obfuscation step</i>, such renaming will never be necessary.
+ <p>
+ This option is only applicable when obfuscating. In fact, if you are
+ planning on performing incremental obfuscation, you probably want to avoid
+ shrinking and optimization altogether, since these steps could remove or
+ modify parts of your code that are essential for later additions.</dd>
+
+<dt><a name="dontusemixedcaseclassnames"><code><b>-dontusemixedcaseclassnames</b></code></a></dt>
+
+<dd>Specifies not to generate mixed-case class names while obfuscating. By
+ default, obfuscated class names can contain a mix of upper-case characters
+ and lower-case characters. This creates perfectly acceptable and usable
+ jars. Only if a jar is unpacked on a platform with a case-insensitive
+ filing system (say, Windows), the unpacking tool may let similarly named
+ class files overwrite each other. Code that self-destructs when it's
+ unpacked! Developers who really want to unpack their jars on Windows can
+ use this option to switch off this behavior. Obfuscated jars will become
+ slightly larger as a result. Only applicable when obfuscating.</dd>
+
+<dt><a name="keeppackagenames"><code><b>-keeppackagenames</b></code></a>
+ [<i><a href="#filters">package_filter</a></i>]</dt>
+
+<dd>Specifies not to obfuscate the given package names. The optional filter is
+ a comma-separated list of package names. Package names can contain
+ <b>?</b>, <b>*</b>, and <b>**</b> wildcards, and they can be preceded by
+ the <b>!</b> negator. Only applicable when obfuscating.</dd>
+
+<dt><a name="flattenpackagehierarchy"><code><b>-flattenpackagehierarchy</b></code></a>
+ [<i>package_name</i>]</dt>
+
+<dd>Specifies to repackage all packages that are renamed, by moving them into
+ the single given parent package. Without argument or with an empty string
+ (''), the packages are moved into the root package. This option is one
+ example of further <a href="examples.html#repackaging">obfuscating package
+ names</a>. It can make the processed code smaller and less comprehensible.
+ Only applicable when obfuscating.</dd>
+
+<dt><a name="repackageclasses"><code><b>-repackageclasses</b></code></a>
+ [<i>package_name</i>]</dt>
+
+<dd>Specifies to repackage all class files that are renamed, by moving them
+ into the single given package. Without argument or with an empty string
+ (''), the package is removed completely. This option overrides the
+ <a
+ href="#flattenpackagehierarchy"><code>-flattenpackagehierarchy</code></a>
+ option. It is another example of further <a
+ href="examples.html#repackaging">obfuscating package names</a>. It can
+ make the processed code even smaller and less comprehensible. Its
+ deprecated name is <code>-defaultpackage</code>. Only applicable when
+ obfuscating.
+ <p>
+ <i>Counter-indication:</i> classes that look for resource files in their
+ package directories will no longer work properly if they are moved
+ elsewhere. When in doubt, just leave the packaging untouched by not using
+ this option.</dd>
+
+<dt><a name="keepattributes"><code><b>-keepattributes</b></code></a>
+ [<i><a href="attributes.html">attribute_filter</a></i>]</dt>
+
+<dd>Specifies any optional attributes to be preserved. The attributes can be
+ specified with one or more <code>-keepattributes</code> directives. The
+ optional filter is a comma-separated list
+ of <a href="attributes.html">attribute names</a> that Java virtual
+ machines and ProGuard support. Attribute names can
+ contain <b>?</b>, <b>*</b>, and <b>**</b> wildcards, and they can be
+ preceded by the <b>!</b> negator. For example, you should at least keep
+ the <code>Exceptions</code>, <code>InnerClasses</code>, and
+ <code>Signature</code> attributes when
+ <a href="examples.html#library">processing a library</a>. You should also
+ keep the <code>SourceFile</code> and <code>LineNumberTable</code>
+ attributes for <a href="examples.html#stacktrace">producing useful
+ obfuscated stack traces</a>. Finally, you may want
+ to <a href="examples.html#annotations">keep annotations</a> if your code
+ depends on them. Only applicable when obfuscating.</dd>
+
+<dt><a name="keepparameternames"><code><b>-keepparameternames</b></code></a></dt>
+
+<dd>Specifies to keep the parameter names and types of methods that are kept.
+ This option actually keeps trimmed versions of the debugging attributes
+ <code>LocalVariableTable</code> and
+ <code>LocalVariableTypeTable</code>. It can be useful when
+ <a href="examples.html#library">processing a library</a>. Some IDEs can
+ use the information to assist developers who use the library, for example
+ with tool tips or autocompletion. Only applicable when obfuscating.</dd>
+
+<dt><a name="renamesourcefileattribute"><code><b>-renamesourcefileattribute</b></code></a>
+ [<i>string</i>]</dt>
+
+<dd>Specifies a constant string to be put in the <code>SourceFile</code>
+ attributes (and <code>SourceDir</code> attributes) of the class files.
+ Note that the attribute has to be present to start with, so it also has to
+ be preserved explicitly using the <code>-keepattributes</code> directive.
+ For example, you may want to have your processed libraries and
+ applications produce <a href="examples.html#stacktrace">useful obfuscated
+ stack traces</a>. Only applicable when obfuscating.</dd>
+
+<dt><a name="adaptclassstrings"><code><b>-adaptclassstrings</b></code></a>
+ [<i><a href="#filters">class_filter</a></i>]</dt>
+
+<dd>Specifies that string constants that correspond to class names should be
+ obfuscated as well. Without a filter, all string constants that correspond
+ to class names are adapted. With a filter, only string constants in
+ classes that match the filter are adapted. For example, if your code
+ contains a large number of hard-coded strings that refer to classes, and
+ you prefer not to keep their names, you may want to use this option.
+ Primarily applicable when obfuscating, although corresponding classes are
+ automatically kept in the shrinking step too.</dd>
+
+<dt><a name="adaptresourcefilenames"><code><b>-adaptresourcefilenames</b></code></a>
+ [<i><a href="#filefilters">file_filter</a></i>]</dt>
+
+<dd>Specifies the resource files to be renamed, based on the obfuscated names
+ of the corresponding class files (if any). Without a filter, all resource
+ files that correspond to class files are renamed. With a filter, only
+ matching files are renamed. For example, see <a
+ href="examples.html#resourcefiles">processing resource files</a>. Only
+ applicable when obfuscating.</dd>
+
+<dt><a name="adaptresourcefilecontents"><code><b>-adaptresourcefilecontents</b></code></a>
+ [<i><a href="#filefilters">file_filter</a></i>]</dt>
+
+<dd>Specifies the resource files whose contents are to be updated. Any class
+ names mentioned in the resource files are renamed, based on the obfuscated
+ names of the corresponding classes (if any). Without a filter, the
+ contents of all resource files updated. With a filter, only matching files
+ are updated. The resource files are parsed and written using the
+ platform's default character set. You can change this default character set
+ by setting the environment variable <code>LANG</code> or the Java system
+ property <code>file.encoding</code>. For an example,
+ see <a href="examples.html#resourcefiles">processing resource files</a>.
+ Only applicable when obfuscating.
+ <p>
+ <i>Caveat:</i> You probably only want to apply this option to text files,
+ since parsing and adapting binary files as text files can cause unexpected
+ problems. Therefore, make sure that you specify a sufficiently narrow
+ filter.</dd>
+
+
+</dl>
+<p>
+
+<h2><a name="preverificationoptions">Preverification Options</a></h2>
+
+<dl>
+<dt><a name="dontpreverify"><code><b>-dontpreverify</b></code></a></dt>
+
+<dd>Specifies not to preverify the processed class files. By default, class
+ files are preverified if they are targeted at Java Micro Edition or at
+ Java 6 or higher. For Java Micro Edition, preverification is required, so
+ you will need to run an external preverifier on the processed code if you
+ specify this option. For Java 6, preverification is optional, but as of
+ Java 7, it is required. Only when eventually targeting Android, it is not
+ necessary, so you can then switch it off to reduce the processing time a
+ bit.</dd>
+
+<dt><a name="microedition"><code><b>-microedition</b></code></a></dt>
+
+<dd>Specifies that the processed class files are targeted at Java Micro
+ Edition. The preverifier will then add the appropriate StackMap
+ attributes, which are different from the default StackMapTable attributes
+ for Java Standard Edition. For example, you will need this option if you
+ are <a href="examples.html#midlets">processing midlets</a>.</dd>
+
+</dl>
+<p>
+
+<h2><a name="generaloptions">General Options</a></h2>
+
+<dl>
+<dt><a name="verbose"><code><b>-verbose</b></code></a></dt>
+
+<dd>Specifies to write out some more information during processing. If the
+ program terminates with an exception, this option will print out the entire
+ stack trace, instead of just the exception message.</dd>
+
+<dt><a name="dontnote"><code><b>-dontnote</b></code></a>
+ [<i><a href="#filters">class_filter</a></i>]</dt>
+
+<dd>Specifies not to print notes about potential mistakes or omissions in the
+ configuration, such as typos in class names or missing options that
+ might be useful. The optional filter is a regular expression; ProGuard
+ doesn't print notes about classes with matching names.</dd>
+
+<dt><a name="dontwarn"><code><b>-dontwarn</b></code></a>
+ [<i><a href="#filters">class_filter</a></i>]</dt>
+
+<dd>Specifies not to warn about unresolved references and other important
+ problems at all. The optional filter is a regular expression; ProGuard
+ doesn't print warnings about classes with matching names. Ignoring
+ warnings can be dangerous. For instance, if the unresolved classes or
+ class members are indeed required for processing, the processed code will
+ not function properly. <i>Only use this option if you know what you're
+ doing!</i></dd>
+
+<dt><a name="ignorewarnings"><code><b>-ignorewarnings</b></code></a></dt>
+
+<dd>Specifies to print any warnings about unresolved references and other
+ important problems, but to continue processing in any case. Ignoring
+ warnings can be dangerous. For instance, if the unresolved classes or
+ class members are indeed required for processing, the processed code will
+ not function properly. <i>Only use this option if you know what you're
+ doing!</i></dd>
+
+<dt><a name="printconfiguration"><code><b>-printconfiguration</b></code></a>
+ [<a href="#filename"><i>filename</i></a>]</dt>
+
+<dd>Specifies to write out the entire configuration that has been parsed, with
+ included files and replaced variables. The structure is printed to the
+ standard output or to the given file. This can sometimes be useful for
+ debugging configurations, or for converting XML configurations into a more
+ readable format.</dd>
+
+<dt><a name="dump"><code><b>-dump</b></code></a>
+ [<a href="#filename"><i>filename</i></a>]</dt>
+
+<dd>Specifies to write out the internal structure of the class files, after
+ any processing. The structure is printed to the standard output or to the
+ given file. For example, you may want to <a
+ href="examples.html#structure">write out the contents of a given jar
+ file</a>, without processing it at all.</dd>
+
+</dl>
+<p>
+
+<h2><a name="classpath">Class Paths</a></h2>
+
+ProGuard accepts a generalization of class paths to specify input files and
+output files. A class path consists of entries, separated by the traditional
+path separator (e.g. '<b>:</b>' on Unix, or '<b>;</b>' on Windows platforms).
+The order of the entries determines their priorities, in case of duplicates.
+<p>
+Each input entry can be:
+<ul>
+<li>A class file or resource file,</li>
+<li>An apk file, containing any of the above,</li>
+<li>A jar file, containing any of the above,</li>
+<li>An aar file, containing any of the above,</li>
+<li>A war file, containing any of the above,</li>
+<li>An ear file, containing any of the above,</li>
+<li>A zip file, containing any of the above,</li>
+<li>A directory (structure), containing any of the above.</li>
+</ul>
+<p>
+The paths of directly specified class files and resource files is ignored, so
+class files should generally be part of a jar file, an aar file, a war file,
+an ear file, a zip file, or a directory. In addition, the paths of class files
+should not have any additional directory prefixes inside the archives or
+directories.
+
+<p>
+Each output entry can be:
+<ul>
+<li>An apk file, in which all class files and resource files will be
+ collected.</li>
+<li>A jar file, in which any and all of the above will be collected,</li>
+<li>An aar file, in which any and all of the above will be collected,</li>
+<li>A war file, in which any and all of the above will be collected,</li>
+<li>An ear file, in which any and all of the above will be collected,</li>
+<li>A zip file, in which any and all of the above will be collected,</li>
+<li>A directory, in which any and all of the above will be collected.</li>
+</ul>
+<p>
+When writing output entries, ProGuard will generally package the results in a
+sensible way, reconstructing the input entries as much as required. Writing
+everything to an output directory is the most straightforward option: the
+output directory will contain a complete reconstruction of the input entries.
+The packaging can be almost arbitrarily complex though: you could process an
+entire application, packaged in a zip file along with its documentation,
+writing it out as a zip file again. The Examples section shows a few ways
+to <a href="examples.html#restructuring">restructure output archives</a>.
+<p>
+Files and directories can be specified as discussed in the section on <a
+href="#filename">file names</a> below.
+<p>
+In addition, ProGuard provides the possibility to filter the class path
+entries and their contents, based on their full relative file names. Each
+class path entry can be followed by up to 7 types of <a
+href="#filefilters">file filters</a> between parentheses, separated by
+semi-colons:
+<ul>
+<li>A filter for all aar names that are encountered,</li>
+<li>A filter for all apk names that are encountered,</li>
+<li>A filter for all zip names that are encountered,</li>
+<li>A filter for all ear names that are encountered,</li>
+<li>A filter for all war names that are encountered,</li>
+<li>A filter for all jar names that are encountered,</li>
+<li>A filter for all class file names and resource file names that are
+ encountered.</li>
+</ul>
+<p>
+If fewer than 7 filters are specified, they are assumed to be the latter
+filters. Any empty filters are ignored. More formally, a filtered class path
+entry looks like this:
+<pre>
+<i>classpathentry</i><b>(</b>[[[[[[<i>aarfilter</i><b>;</b>]<i>apkfilter</i><b>;</b>]<i>zipfilter</i><b>;</b>]<i>earfilter</i><b>;</b>]<i>warfilter</i><b>;</b>]<i>jarfilter</i><b>;</b>]<i>filefilter</i><b>)</b>
+</pre>
+<p>
+Square brackets "[]" mean that their contents are optional.
+<p>
+For example, "<code>rt.jar(java/**.class,javax/**.class)</code>" matches all
+class files in the <code>java</code> and <code>javax</code> directories inside
+the <code>rt</code> jar.
+<p>
+For example, "<code>input.jar(!**.gif,images/**)</code>" matches all files in
+the <code>images</code> directory inside the <code>input</code> jar, except
+gif files.
+<p>
+The different filters are applied to all corresponding file types, irrespective
+of their nesting levels in the input; they are orthogonal.
+<p>
+For example,
+"<code>input.war(lib/**.jar,support/**.jar;**.class,**.gif)</code>" only
+considers jar files in the <code>lib</code> and <code>support</code>
+directories in the <code>input</code> war, not any other jar files. It then
+matches all class files and gif files that are encountered.
+<p>
+The filters allow for an almost infinite number of packaging and repackaging
+possibilities. The Examples section provides a few more examples
+for <a href="examples.html#filtering">filtering input and output</a>.
+<p>
+
+<h2><a name="filename">File Names</a></h2>
+
+ProGuard accepts absolute paths and relative paths for the various file names
+and directory names. A relative path is interpreted as follows:
+<ul>
+<li>relative to the base directory, if set, or otherwise</li>
+<li>relative to the configuration file in which it is specified, if any, or
+ otherwise</li>
+<li>relative to the working directory.</li>
+</ul>
+<p>
+The names can contain Java system properties (or Ant properties, when using
+Ant), delimited by angular brackets, '<b>&lt;</b>' and '<b>&gt;</b>'. The
+properties are automatically replaced by their corresponding values.
+<p>
+For example, <code>&lt;java.home&gt;/lib/rt.jar</code> is automatically
+expanded to something like <code>/usr/local/java/jdk/jre/lib/rt.jar</code>.
+Similarly, <code>&lt;user.home&gt;</code> is expanded to the user's home
+directory, and <code>&lt;user.dir&gt;</code> is expanded to the current
+working directory.
+<p>
+Names with special characters like spaces and parentheses must be quoted with
+single or double quotes. Each file name in a list of names has to be quoted
+individually. Note that the quotes themselves may need to be escaped when used
+on the command line, to avoid them being gobbled by the shell.
+<p>
+For example, on the command line, you could use an option like <code>'-injars
+"my program.jar":"/your directory/your program.jar"'</code>.
+<p>
+
+<h2><a name="filefilters">File Filters</a></h2>
+
+Like general <a href="#filters">filters</a>, a file filter is a
+comma-separated list of file names that can contain wildcards. Only files with
+matching file names are read (in the case of input jars), or written (in the
+case of output jars). The following wildcards are supported:
+
+<table cellspacing="10">
+<tr><td valign="top"><code><b>?</b></code></td>
+ <td>matches any single character in a file name.</td></tr>
+<tr><td valign="top"><code><b>*</b></code></td>
+ <td>matches any part of a filename not containing the directory
+ separator.</td></tr>
+<tr><td valign="top"><code><b>**</b></code></td>
+ <td>matches any part of a filename, possibly containing any number of
+ directory separators.</td></tr>
+</table>
+
+For example, "<code>java/**.class,javax/**.class</code>" matches all
+class files in the <code>java</code> and <code>javax</code>.
+<p>
+
+Furthermore, a file name can be preceded by an exclamation mark '<b>!</b>' to
+<i>exclude</i> the file name from further attempts to match with
+<i>subsequent</i> file names.
+<p>
+For example, "<code>!**.gif,images/**</code>" matches all files in the
+<code>images</code> directory, except gif files.
+<p>
+The Examples section provides a few more examples for <a
+href="examples.html#filtering">filtering input and output</a>.
+
+<h2><a name="filters">Filters</a></h2>
+
+ProGuard offers options with filters for many different aspects of the
+configuration: names of files, directories, classes, packages, attributes,
+optimizations, etc.
+<p>
+A filter is a list of comma-separated names that can contain wildcards. Only
+names that match an item on the list pass the filter. The supported wildcards
+depend on the type of names for which the filter is being used, but the
+following wildcards are typical:
+
+<table cellspacing="10">
+<tr><td valign="top"><code><b>?</b></code></td>
+ <td>matches any single character in a name.</td></tr>
+<tr><td valign="top"><code><b>*</b></code></td>
+ <td>matches any part of a name not containing the package separator or
+ directory separator.</td></tr>
+<tr><td valign="top"><code><b>**</b></code></td>
+ <td>matches any part of a name, possibly containing any number of
+ package separators or directory separators.</td></tr>
+</table>
+
+For example, "<code>foo,*bar</code>" matches the name <code>foo</code> and
+all names ending with <code>bar</code>.
+<p>
+
+Furthermore, a name can be preceded by a negating exclamation mark '<b>!</b>'
+to <i>exclude</i> the name from further attempts to match
+with <i>subsequent</i> names. So, if a name matches an item in the filter, it
+is accepted or rejected right away, depending on whether the item has a
+negator. If the name doesn't match the item, it is tested against the next
+item, and so on. It if doesn't match any items, it is accepted or rejected,
+depending on the whether the last item has a negator or not.
+<p>
+For example, "<code>!foobar,*bar</code>" matches all names ending with
+<code>bar</code>, except <code>foobar</code>.
+<p>
+
+<h2><a name="keepoverview">Overview of <code>Keep</code> Options</a></h2>
+
+The various <code>-keep</code> options for shrinking and obfuscation may seem
+a bit confusing at first, but there's actually a pattern behind them. The
+following table summarizes how they are related:
+<p>
+
+<table cellpadding="5">
+
+<tr>
+<th>Keep</th>
+<td>From being removed or renamed</td>
+<td>From being renamed</td>
+</tr>
+
+<tr>
+<td>Classes and class members</td>
+<td bgcolor="#E0E0E0"><a href="#keep"><code>-keep</code></a></td>
+<td bgcolor="#E0E0E0"><a href="#keepnames"><code>-keepnames</code></a></td>
+</tr>
+
+<tr>
+<td>Class members only</td>
+<td bgcolor="#E0E0E0"><a href="#keepclassmembers"><code>-keepclassmembers</code></a></td>
+<td bgcolor="#E0E0E0"><a href="#keepclassmembernames"><code>-keepclassmembernames</code></a></td>
+</tr>
+
+<tr>
+<td>Classes and class members, if class members present</td>
+<td bgcolor="#E0E0E0"><a href="#keepclasseswithmembers"><code>-keepclasseswithmembers</code></a></td>
+<td bgcolor="#E0E0E0"><a href="#keepclasseswithmembernames"><code>-keepclasseswithmembernames</code></a></td>
+</tr>
+
+</table>
+<p>
+
+Each of these <code>-keep</code> options is of course followed by a
+<a href="#classspecification">specification</a> of the classes and class
+members (fields and methods) to which it should be applied.
+<p>
+If you're not sure which option you need, you should probably simply use
+<code>-keep</code>. It will make sure the specified classes and class members
+are not removed in the shrinking step, and not renamed in the obfuscation step.
+<p>
+<img class="float" src="attention.gif" width="64" height="64" alt="attention" />
+<ul class="shifted">
+<li>If you specify a class, without class members, ProGuard only preserves the
+ class and its parameterless constructor as entry points. It may
+ still remove, optimize, or obfuscate its other class members.</li>
+<li>If you specify a method, ProGuard only preserves the method as an entry
+ point. Its code may still be optimized and adapted.</li>
+</ul>
+<p>
+
+<h2><a name="keepoptionmodifiers">Keep Option Modifiers</a></h2>
+
+<dl>
+<dt><a name="includedescriptorclasses"><code><b>includedescriptorclasses</b></code></a></dt>
+
+<dd>Specifies that any classes in the type descriptors of the methods and
+ fields that the <a href="#keep">-keep</a> option keeps should be kept as
+ well. This is typically useful when <a href="examples.html#native">keeping
+ native method names</a>, to make sure that the parameter types of native
+ methods aren't renamed either. Their signatures then remain completely
+ unchanged and compatible with the native libraries.</dd>
+
+<dt><a name="allowshrinking"><code><b>allowshrinking</b></code></a></dt>
+
+<dd>Specifies that the entry points specified in the <a href="#keep">-keep</a>
+ option may be shrunk, even if they have to be preserved otherwise. That
+ is, the entry points may be removed in the shrinking step, but if they are
+ necessary after all, they may not be optimized or obfuscated.</dd>
+
+<dt><a name="allowoptimization"><code><b>allowoptimization</b></code></a></dt>
+
+<dd>Specifies that the entry points specified in the <a href="#keep">-keep</a>
+ option may be optimized, even if they have to be preserved otherwise. That
+ is, the entry points may be altered in the optimization step, but they may
+ not be removed or obfuscated. This modifier is only useful for achieving
+ unusual requirements.</dd>
+
+<dt><a name="allowobfuscation"><code><b>allowobfuscation</b></code></a></dt>
+
+<dd>Specifies that the entry points specified in the <a href="#keep">-keep</a>
+ option may be obfuscated, even if they have to be preserved otherwise. That
+ is, the entry points may be renamed in the obfuscation step, but they may
+ not be removed or optimized. This modifier is only useful for achieving
+ unusual requirements.</dd>
+
+</dl>
+<p>
+
+<h2><a name="classspecification">Class Specifications</a></h2>
+
+A class specification is a template of classes and class members (fields and
+methods). It is used in the various <code>-keep</code> options and in the
+<code>-assumenosideeffects</code> option. The corresponding option is only
+applied to classes and class members that match the template.
+<p>
+The template was designed to look very Java-like, with some extensions for
+wildcards. To get a feel for the syntax, you should probably look at the <a
+href="examples.html">examples</a>, but this is an attempt at a complete formal
+definition:
+<p>
+
+<pre>
+[<b>@</b><i>annotationtype</i>] [[<b>!</b>]<b>public</b>|<b>final</b>|<b>abstract</b>|<b>@</b> ...] [<b>!</b>]<b>interface</b>|<b>class</b>|<b>enum</b> <i>classname</i>
+ [<b>extends</b>|<b>implements</b> [<b>@</b><i>annotationtype</i>] <i>classname</i>]
+[<b>{</b>
+ [<b>@</b><i>annotationtype</i>] [[<b>!</b>]<b>public</b>|<b>private</b>|<b>protected</b>|<b>static</b>|<b>volatile</b>|<b>transient</b> ...] <b>&lt;fields&gt;</b> |
+ (<i>fieldtype fieldname</i>)<b>;</b>
+ [<b>@</b><i>annotationtype</i>] [[<b>!</b>]<b>public</b>|<b>private</b>|<b>protected</b>|<b>static</b>|<b>synchronized</b>|<b>native</b>|<b>abstract</b>|<b>strictfp</b> ...] <b>&lt;methods&gt;</b> |
+ <b>&lt;init&gt;(</b><i>argumenttype,...</i><b>)</b> |
+ <i>classname</i><b>(</b><i>argumenttype,...</i><b>)</b> |
+ (<i>returntype methodname</i><b>(</b><i>argumenttype,...</i><b>)</b>)<b>;</b>
+ [<b>@</b><i>annotationtype</i>] [[<b>!</b>]<b>public</b>|<b>private</b>|<b>protected</b>|<b>static</b> ... ] <b>*;</b>
+ ...
+<b>}</b>]
+</pre>
+<p>
+Square brackets "[]" mean that their contents are optional. Ellipsis dots
+"..." mean that any number of the preceding items may be specified. A vertical
+bar "|" delimits two alternatives. Non-bold parentheses "()" just group parts
+of the specification that belong together. The indentation tries to clarify
+the intended meaning, but white-space is irrelevant in actual configuration
+files.
+<p>
+<ul class="spacious">
+
+<li>The <code><b>class</b></code> keyword refers to any interface or class.
+ The <code><b>interface</b></code> keyword restricts matches to interface
+ classes. The <code><b>enum</b></code> keyword restricts matches to
+ enumeration classes. Preceding the <code><b>interface</b></code> or
+ <code><b>enum</b></code> keywords by a <code><b>!</b></code> restricts
+ matches to classes that are not interfaces or enumerations,
+ respectively.</li>
+
+<li>Every <i>classname</i> must be fully qualified, e.g.
+ <code>java.lang.String</code>. Inner classes are separated by a dollar sign
+ "<code>$</code>", e.g. <code>java.lang.Thread$State</code>. Class names
+ may be specified as regular
+ expressions containing the following wildcards:
+
+<table cellspacing="10">
+
+<tr><td valign="top"><code><b>?</b></code></td>
+
+<td>matches any single character in a class name, but not the package
+ separator. For example, "<code>mypackage.Test?</code>" matches
+ "<code>mypackage.Test1</code>" and "<code>mypackage.Test2</code>", but not
+ "<code>mypackage.Test12</code>".</td></tr>
+
+<tr><td valign="top"><code><b>*</b></code></td>
+
+<td>matches any part of a class name not containing the package separator. For
+ example, "<code>mypackage.*Test*</code>" matches
+ "<code>mypackage.Test</code>" and
+ "<code>mypackage.YourTestApplication</code>", but not
+ "<code>mypackage.mysubpackage.MyTest</code>". Or, more generally,
+ "<code>mypackage.*</code>" matches all classes in
+ "<code>mypackage</code>", but not in its subpackages.</td></tr>
+
+<tr><td valign="top"><code><b>**</b></code></td>
+
+<td>matches any part of a class name, possibly containing any number of
+ package separators. For example, "<code>**.Test</code>" matches all
+ <code>Test</code> classes in all packages except the root package. Or,
+ "<code>mypackage.**</code>" matches all classes in
+ "<code>mypackage</code>" and in its subpackages.</td></tr>
+
+</table>
+
+ For additional flexibility, class names can actually be comma-separated
+ lists of class names, with optional <code><b>!</b></code> negators, just
+ like file name filters. This notation doesn't look very Java-like, so it
+ should be used with moderation.
+ <p>
+ For convenience and for backward compatibility, the class name
+ <code><b>*</b></code> refers to any class, irrespective of its package.</li>
+
+<li>The <code><b>extends</b></code> and <code><b>implements</b></code>
+ specifications are typically used to restrict classes with wildcards. They
+ are currently equivalent, specifying that only classes extending or
+ implementing the given class qualify. Note that the given class itself is
+ not included in this set. If required, it should be specified in a
+ separate option.</li>
+
+<li>The <code><b>@</b></code> specifications can be used to restrict classes
+ and class members to the ones that are annotated with the specified
+ annotation types. An <i>annotationtype</i> is specified just like a
+ <i>classname</i>.</li>
+
+<li>Fields and methods are specified much like in Java, except that method
+ argument lists don't contain argument names (just like in other tools
+ like <code>javadoc</code> and <code>javap</code>). The specifications can
+ also contain the following catch-all wildcards:
+
+<table cellspacing="10">
+
+<tr><td valign="top"><code><b>&lt;init&gt;</b></code></td>
+<td>matches any constructor.</td></tr>
+
+<tr><td valign="top"><code><b>&lt;fields&gt;</b></code></td>
+<td>matches any field.</td></tr>
+
+<tr><td valign="top"><code><b>&lt;methods&gt;</b></code></td>
+<td>matches any method.</td></tr>
+
+<tr><td valign="top"><code><b>*</b></code></td>
+<td>matches any field or method.</td></tr>
+
+</table>
+
+ Note that the above wildcards don't have return types. Only the
+ <code><b>&lt;init&gt;</b></code> wildcard has an argument list.
+ <p>
+
+ Fields and methods may also be specified using regular expressions. Names
+ can contain the following wildcards:
+
+<table cellspacing="10">
+<tr><td valign="top"><code><b>?</b></code></td>
+ <td>matches any single character in a method name.</td></tr>
+<tr><td valign="top"><code><b>*</b></code></td>
+ <td>matches any part of a method name.</td></tr>
+</table>
+
+ Types in descriptors can contain the following wildcards:
+
+<table cellspacing="10">
+<tr><td valign="top"><code><b>%</b></code></td>
+ <td>matches any primitive type ("<code>boolean</code>", "<code>int</code>",
+ etc, but not "<code>void</code>").</td></tr>
+<tr><td valign="top"><code><b>?</b></code></td>
+ <td>matches any single character in a class name.</td></tr>
+<tr><td valign="top"><code><b>*</b></code></td>
+ <td>matches any part of a class name not containing the package separator.</td></tr>
+<tr><td valign="top"><code><b>**</b></code></td>
+ <td>matches any part of a class name, possibly containing any number of
+ package separators.</td></tr>
+<tr><td valign="top"><code><b>***</b></code></td>
+ <td>matches any type (primitive or non-primitive, array or
+ non-array).</td></tr>
+<tr><td valign="top"><code><b>...</b></code></td>
+ <td>matches any number of arguments of any type.</td></tr>
+
+</table>
+
+ Note that the <code>?</code>, <code>*</code>, and <code>**</code>
+ wildcards will never match primitive types. Furthermore, only the
+ <code>***</code> wildcards will match array types of any dimension. For
+ example, "<code>** get*()</code>" matches "<code>java.lang.Object
+ getObject()</code>", but not "<code>float getFloat()</code>", nor
+ "<code>java.lang.Object[] getObjects()</code>".</li>
+
+<li>Constructors can also be specified using their short class names (without
+ package) or using their full class names. As in the Java language, the
+ constructor specification has an argument list, but no return type.</li>
+
+<li>The class access modifiers and class member access modifiers are typically
+ used to restrict wildcarded classes and class members. They specify that
+ the corresponding access flags have to be set for the member to match. A
+ preceding <code><b>!</b></code> specifies that the corresponding access
+ flag should be unset.
+ <p>
+ Combining multiple flags is allowed (e.g. <code>public static</code>). It
+ means that both access flags have to be set (e.g. <code>public</code>
+ <i>and</i> <code>static</code>), except when they are conflicting, in
+ which case at least one of them has to be set (e.g. at least
+ <code>public</code>
+ <i>or</i> <code>protected</code>).
+ <p>
+ ProGuard supports the additional modifiers <code><b>synthetic</b></code>,
+ <code><b>bridge</b></code>, and <code><b>varargs</b></code>, which may be
+ set by compilers.</li>
+
+</ul>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/manual/wtk.html b/third_party/java/proguard/proguard5.3.3/docs/manual/wtk.html
new file mode 100644
index 0000000000..2787a1a6b9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/manual/wtk.html
@@ -0,0 +1,71 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard JME Wireless Toolkit Integration</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="../index.html#manual/wtk.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="../index.html#manual/wtk.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>JME Wireless Toolkit Integration</h2>
+
+<b>ProGuard</b> can be seamlessly integrated in Oracle's Wireless Toolkit (WTK)
+for Java Micro Edition (JME).
+<p>
+
+The WTK already comes with a plug-in for ProGuard. Alternatively, ProGuard
+offers its own plug-in. This latter implementation is recommended, as it more
+up to date and it solves some problems. It is also somewhat more efficient,
+invoking the ProGuard engine directly, instead of writing out a configuration
+file and running ProGuard in a separate virtual machine.
+<p>
+
+In order to integrate this plug-in in the toolkit, you'll have to put the
+following lines in the file
+{j2mewtk.dir}<code>/wtklib/Linux/ktools.properties</code> or
+{j2mewtk.dir}<code>\wtklib\Windows\ktools.properties</code> (whichever is
+applicable).
+<p>
+
+<pre>
+obfuscator.runner.class.name: proguard.wtk.ProGuardObfuscator
+obfuscator.runner.classpath: /usr/local/java/proguard/lib/proguard.jar
+</pre>
+<p>
+
+Please make sure the class path is set correctly for your system.
+<p>
+
+Once ProGuard has been set up, you can apply it to your projects as part of
+the build process. The build process is started from the WTK menu bar:
+<p>
+<center><b>Project -> Package -> Create Obfuscated Package</b></center>
+<p>
+This option will compile, shrink, obfuscate, verify, and install your midlets
+for testing.
+<p>
+Should you ever need to customize your ProGuard configuration for the JME WTK,
+you can adapt the configuration file <code>proguard/wtk/default.pro</code>
+that's inside the <code>proguard.jar</code>.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/proguard.appdata.xml b/third_party/java/proguard/proguard5.3.3/docs/proguard.appdata.xml
new file mode 100644
index 0000000000..c2168d1105
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/proguard.appdata.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2012-2017 Eric Lafortune @ GuardSquare -->
+<application>
+ <id type="desktop">proguard.desktop</id>
+ <metadata_license>CC-BY-SA-3.0</metadata_license>
+ <project_license>GPL-2.0</project_license>
+ <name>ProGuard</name>
+ <summary>Java optimizer and obfuscator</summary>
+ <description>
+ <p>
+ ProGuard is a free Java class file shrinker, optimizer, obfuscator, and
+ preverifier. It detects and removes unused classes, fields, methods, and
+ attributes. It optimizes bytecode and removes unused instructions. It
+ renames the remaining classes, fields, and methods using short meaningless
+ names. Finally, it preverifies the processed code for Java 6 or for Java
+ Micro Edition.
+ </p>
+ <p>
+ ProGuard is useful for making code more compact and more efficient, on the
+ desktop, on tablets, on smartphones, and on embedded devices. It also
+ makes code more difficult to reverse engineer.Power Statistics is a
+ program used to view historical and current battery information and will
+ show programs running on your computer using power.
+ </p>
+ </description>
+ <screenshots>
+ <screenshot type="default" width="918" height="671">http://proguard.sourceforge.net/screenshot_gui1.gif</screenshot>
+ <screenshot width="755" height="633">http://proguard.sourceforge.net/screenshot_console.gif</screenshot>
+ </screenshots>
+ <url type="homepage">http://proguard.sourceforge.net/</url>
+ <updatecontact>eric@graphics.cornell.edu</updatecontact>
+</application>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/quality.html b/third_party/java/proguard/proguard5.3.3/docs/quality.html
new file mode 100644
index 0000000000..5e85728417
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/quality.html
@@ -0,0 +1,57 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Quality</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="index.html#quality.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="index.html#quality.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Quality</h2>
+
+In order to get a feel for the quality of the <b>ProGuard</b> code, it is run
+through a regular automatic build process. This process produces numerous
+statistics on the source code, Java lint comments, Java documentation
+comments, the Java documentation itself, html lint comments on the Java
+documentation, spell checks, compilation results, an output jar, dead code
+analysis, a shrunk and obfuscated jar (using ProGuard itself!), test runs with
+memory and performance analyses, etc. Most analyses are produced using freely
+available tools. The results are poured into a convenient set of web pages
+using bash/sed/awk scripts. You're welcome to have a look at an uploaded
+snapshot of one of these runs:
+<p>
+<center><a href="http://proguard.sourceforge.net/quality/"
+target="other">Automated Code Analysis and Testing Pages</a> (at <a
+href="http://sourceforge.net/projects/proguard/"
+target="other">SourceForge</a>)</center>
+<p>
+The pages will appear in a new window, which you probably want to view at
+full-screen size.
+<p>
+
+In addition, <b>ProGuard</b> is tested against a constantly growing test suite
+(more than 1800 tests at this time of writing). These small programs contain a
+wide range of common and uncommon constructs, in order to detect any regression
+problems as soon as possible.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/results.html b/third_party/java/proguard/proguard5.3.3/docs/results.html
new file mode 100644
index 0000000000..a43a0c2540
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/results.html
@@ -0,0 +1,170 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Results</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="index.html#results.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="index.html#results.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Results</h2>
+
+<b>ProGuard</b> successfully processes any Java bytecode, ranging from small
+Android applications to entire run-time libraries. It primarily reduces the
+size of the processed code, with some potential increase in efficiency as an
+added bonus. The improvements obviously depend on the original code. The table
+below presents some typical results:
+<p>
+
+<table>
+
+<tr>
+<th width="28%">Input Program</th>
+<th width="12%">Original size</th>
+<th width="12%">After shrinking</th>
+<th width="12%">After optim.</th>
+<th width="12%">After obfusc.</th>
+<th width="12%">Total reduction</th>
+<th width="12%">Time</th>
+<th width="12%">Memory usage</th>
+</tr>
+
+<tr>
+<td><a target="other" href="http://www.oracle.com/technetwork/java/javame/index.html">Worm</a>, a sample midlet from Oracle's JME</td>
+<td align="center">10.3 K</td>
+<td align="center">9.8 K</td>
+<td align="center">9.6 K</td>
+<td align="center">8.5 K</td>
+<td align="center">18 %</td>
+<td align="center">2 s</td>
+<td align="center">19 M</td>
+</tr>
+
+<tr>
+<td><a target="other" href="http://www.javadocking.com/">Javadocking</a>, a docking library</td>
+<td align="center">290 K</td>
+<td align="center">281 K</td>
+<td align="center">270 K</td>
+<td align="center">201 K</td>
+<td align="center">30 %</td>
+<td align="center">12 s</td>
+<td align="center">32 M</td>
+</tr>
+
+<tr>
+<td><b>ProGuard</b> itself</td>
+<td align="center">648 K</td>
+<td align="center">579 K</td>
+<td align="center">557 K</td>
+<td align="center">348 K</td>
+<td align="center">46 %</td>
+<td align="center">28 s</td>
+<td align="center">66 M</td>
+</tr>
+
+<tr>
+<td><a target="other" href="http://www.clarkware.com/software/JDepend.html">JDepend</a>, a Java quality metrics tool</td>
+<td align="center">57 K</td>
+<td align="center">36 K</td>
+<td align="center">33 K</td>
+<td align="center">28 K</td>
+<td align="center">51 %</td>
+<td align="center">6 s</td>
+<td align="center">24 M</td>
+</tr>
+
+<tr>
+<td><a target="other" href="ihttp://www.oracle.com/technetwork/java/javase/overview/index.html">the run-time classes</a> from Oracle's Java 6</td>
+<td align="center">53 M</td>
+<td align="center">23 M</td>
+<td align="center">22 M</td>
+<td align="center">18 M</td>
+<td align="center">66 %</td>
+<td align="center">16 min</td>
+<td align="center">270 M</td>
+</tr>
+
+<tr>
+<td><a target="other" href="http://tomcat.apache.org/">Tomcat</a>, the Apache servlet container</td>
+<td align="center">1.1 M</td>
+<td align="center">466 K</td>
+<td align="center">426 K</td>
+<td align="center">295 K</td>
+<td align="center">74 %</td>
+<td align="center">17 s</td>
+<td align="center">44 M</td>
+</tr>
+
+<tr>
+<td><a target="other" href="http://javancss.codehaus.org/">JavaNCSS</a>, a Java source metrics tool</td>
+<td align="center">632 K</td>
+<td align="center">242 K</td>
+<td align="center">212 K</td>
+<td align="center">152 K</td>
+<td align="center">75 %</td>
+<td align="center">20 s</td>
+<td align="center">36 M</td>
+</tr>
+
+<tr>
+<td><a target="other" href="http://ant.apache.org/">Ant</a>, the Apache build tool</td>
+<td align="center">2.4 M</td>
+<td align="center">401 K</td>
+<td align="center">325 K</td>
+<td align="center">242 K</td>
+<td align="center">90 %</td>
+<td align="center">23 s</td>
+<td align="center">61 M</td>
+</tr>
+
+</table>
+<p>
+Results were measured with ProGuard 4.0 on a 2.6 GHz Pentium 4 with 512 MB
+of memory, using Sun JDK 1.5.0 in Fedora Core 3 Linux. All of this technology
+and software has evolved since, but the gist of the results remains the same.
+<p>
+The program sizes include companion libraries. The shrinking step produces the
+best results for programs that use only small parts of their libraries. The
+obfuscation step can significantly shrink large programs even further, since
+the identifiers of their many internal references can be replaced by short
+identifiers.
+<p>
+The Java 6 run-time classes are the most complex example. The classes perform
+a lot of introspection, interacting with the native code of the virtual
+machine. The 1500+ lines of configuration were largely composed by automated
+analysis, complemented by a great deal of trial and error. The configuration
+is probably not complete, but the resulting library successfully serves as a
+run-time environment for running applications like ProGuard and the ProGuard
+GUI.
+<p>
+For small inputs, timings are governed by the reading and parsing of the jars.
+For large inputs, the optimization step becomes more important. For instance,
+processing the Java 6 run-time classes without optimization only takes 2
+minutes.
+<p>
+Memory usage (the amount of physical memory used by ProGuard while processing)
+is governed by the basic java virtual machine and by the total size of the
+library jars and program jars.
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshot_console.gif b/third_party/java/proguard/proguard5.3.3/docs/screenshot_console.gif
new file mode 100644
index 0000000000..8aea61e11a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshot_console.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshot_console_small.gif b/third_party/java/proguard/proguard5.3.3/docs/screenshot_console_small.gif
new file mode 100644
index 0000000000..3f55f5b676
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshot_console_small.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui1.gif b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui1.gif
new file mode 100644
index 0000000000..233e18006c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui1.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui2.gif b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui2.gif
new file mode 100644
index 0000000000..aecdb35f23
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui2.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui3.gif b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui3.gif
new file mode 100644
index 0000000000..17950eed49
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui3.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui4.gif b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui4.gif
new file mode 100644
index 0000000000..31e60fa541
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui4.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui5.gif b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui5.gif
new file mode 100644
index 0000000000..1313db22b3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui5.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui6.gif b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui6.gif
new file mode 100644
index 0000000000..c200b97a49
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui6.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui7.gif b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui7.gif
new file mode 100644
index 0000000000..bc5d6ed932
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui7.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui8.gif b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui8.gif
new file mode 100644
index 0000000000..95a1a30b06
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshot_gui8.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshots.html b/third_party/java/proguard/proguard5.3.3/docs/screenshots.html
new file mode 100644
index 0000000000..9c36c808b9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshots.html
@@ -0,0 +1,68 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Screenshots</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="index.html#screenshots.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="index.html#screenshots.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Screenshots</h2>
+
+<table><tr><td>
+<a href="screenshot_gui1.gif" target="other">
+<img src="screenshots_gui_small.gif" width="320" height="223" align="right"
+ alt="GUI screenshot" usemap="#guimap" /></a>
+
+<map id="guimap" name="guimap">
+<area shape="rect" coords="2,7,46,16" alt="ProGuard" href="screenshot_gui1.gif" target="other">
+<area shape="rect" coords="2,17,46,27" alt="Input/Output" href="screenshot_gui2.gif" target="other">
+<area shape="rect" coords="2,28,46,37" alt="Shrinking" href="screenshot_gui3.gif" target="other">
+<area shape="rect" coords="2,38,46,48" alt="Optimization" href="screenshot_gui4.gif" target="other">
+<area shape="rect" coords="2,49,46,58" alt="Obfuscation" href="screenshot_gui5.gif" target="other">
+<area shape="rect" coords="2,59,46,69" alt="Information" href="screenshot_gui6.gif" target="other">
+<area shape="rect" coords="2,70,46,79" alt="Process" href="screenshot_gui7.gif" target="other">
+<area shape="rect" coords="2,80,46,90" alt="ReTrace" href="screenshot_gui8.gif" target="other">
+</map>
+
+The graphical user interface to <b>ProGuard</b> works like a wizard. It allows
+you to browse through the presented tabs and fill them out.
+<p>
+You can click on the small tab buttons to see the full-size versions of the
+tabs.
+
+</td></tr>
+<tr><td>
+<a href="screenshot_console.gif" target="other">
+<img src="screenshot_console_small.gif" width="320" height="268" align="left"
+ alt="Console screenshot" /></a>
+
+Of course, real developers don't need all this point-and-click fluff. They
+write short configuration files using their favorite text editors and invoke
+<b>ProGuard</b> from the command-line.
+<p>
+You can click on the image to see the full-size version.
+
+</td></tr></table>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/screenshots_gui_small.gif b/third_party/java/proguard/proguard5.3.3/docs/screenshots_gui_small.gif
new file mode 100644
index 0000000000..bc32ccbb85
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/screenshots_gui_small.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/sections.html b/third_party/java/proguard/proguard5.3.3/docs/sections.html
new file mode 100644
index 0000000000..ac29c55a00
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/sections.html
@@ -0,0 +1,49 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-script-type" content="text/javascript">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>Sections</title>
+</head>
+<body class="navigation">
+
+<ul class="navigation">
+<li><a target="main" href="main.html">Main</a></li>
+<li><a target="main" href="results.html">Results</a></li>
+<li><a target="main" href="FAQ.html">FAQ</a></li>
+<li><a href="manual/sections.html">Manual</a></li>
+<li><a target="main" href="quality.html">Quality</a></li>
+<li><a target="main" href="screenshots.html">Screenshots</a></li>
+<li><a target="main" href="testimonials.html">Testimonials</a></li>
+<li><a target="main" href="license.html">License</a></li>
+<li><a target="main" href="downloads.html">Downloads</a></li>
+<li><a target="main" href="feedback.html">Feedback</a></li>
+<li><a target="main" href="acknowledgements.html">Ack'ments</a></li>
+<li><a target="main" href="alternatives.html">Alternatives</a></li>
+</ul>
+
+<p>
+<center>
+<small>More Android app protection:</small>
+<p>
+<a href="http://www.guardsquare.com/dexguard" target="_top">
+<img src="dexguard.png" width="88" height="55" alt="DexGuard" /></a>
+
+<p>
+<small>With support of</small>
+
+<p>
+<a href="http://www.guardsquare.com/" target="_top">
+<img src="guardsquare.png" width="88" height="25" alt="GuardSquare" /></a>
+
+<p>
+<a href="http://sourceforge.net/projects/proguard/" target="other">
+<img src="sflogo.png" width="88" height="31" alt="SourceForge" /></a>
+
+</center>
+
+
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/sflogo.png b/third_party/java/proguard/proguard5.3.3/docs/sflogo.png
new file mode 100644
index 0000000000..142a6f99ab
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/sflogo.png
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/steel.gif b/third_party/java/proguard/proguard5.3.3/docs/steel.gif
new file mode 100644
index 0000000000..307b57abe7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/steel.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/style.css b/third_party/java/proguard/proguard5.3.3/docs/style.css
new file mode 100644
index 0000000000..ce7e995678
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/style.css
@@ -0,0 +1,278 @@
+@charset "iso-8859-1";
+
+/* Fonts. */
+
+@font-face
+{
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: url('fonts/OpenSans-Regular.eot');
+ src: local('Open Sans'),
+ local('OpenSans'),
+ url('fonts/OpenSans-Regular.eot?#iefix') format('embedded-opentype'),
+ url('fonts/OpenSans-Regular.woff') format('woff'),
+ url('fonts/OpenSans-Regular.ttf') format('truetype'),
+ url('fonts/OpenSans-Regular.svg#OpenSansRegular') format('svg');
+}
+
+@font-face
+{
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: url('fonts/OpenSans-Bold.eot');
+ src: local('Open Sans Bold'),
+ local('OpenSans-Bold'),
+ url('fonts/OpenSans-Bold.eot?#iefix') format('embedded-opentype'),
+ url('fonts/OpenSans-Bold.woff') format('woff'),
+ url('fonts/OpenSans-Bold.ttf') format('truetype'),
+ url('fonts/OpenSans-Bold.svg#OpenSansBold') format('svg');
+}
+
+@font-face
+{
+ font-family: 'Open Sans';
+ font-style: italic;
+ font-weight: 400;
+ src: url('fonts/OpenSans-Italic.eot');
+ src: local('Open Sans Italic'),
+ local('OpenSans-Italic'),
+ url('fonts/OpenSans-Italic.eot?#iefix') format('embedded-opentype'),
+ url('fonts/OpenSans-Italic.woff') format('woff'),
+ url('fonts/OpenSans-Italic.ttf') format('truetype'),
+ url('fonts/OpenSans-Italic.svg#OpenSansItalic') format('svg');
+}
+
+/* Global settings. */
+
+body
+{
+ background: #FFFFFF;
+ font-family: "Open Sans",Verdana,sans-serif;
+}
+
+h1
+{
+ text-align: center;
+}
+
+h2
+{
+ text-align: center;
+}
+
+h3
+{
+ background: #EEEEFF;
+ padding: 10px;
+}
+
+h3 div
+{
+ font-weight: normal;
+ font-size: 80%;
+ float: right;
+}
+
+table
+{
+ width: 100%;
+}
+
+th
+{
+ padding: 4px;
+}
+
+tr.disappeared td
+{
+ background: #EEEEEE;
+}
+
+td
+{
+ background: #EEEEFF;
+ padding: 8px;
+}
+
+ul.spacious li
+{
+ padding: 8px;
+}
+
+a
+{
+ text-decoration: none;
+}
+
+img
+{
+ border: none;
+}
+
+a.button {
+ color: #000000;
+ text-decoration: none;
+ background: #E0E0E0;
+ border: 1px outset #FFFFFF;
+ float: right;
+}
+
+a.largebutton {
+ font-weight: bold;
+ color: #000000;
+ margin: 0px;
+ padding: 10px;
+ background: url("steel.gif");
+ text-decoration: none;
+ border: 1px outset #FFFFFF;
+}
+
+/* Settings for the introductory paragraph. */
+
+p.intro
+{
+ background: #EEEEFF;
+ padding: 10px;
+ border: 1px solid #000000;
+}
+
+/* Settings for the title frame. */
+
+body.title
+{
+ margin: 0px;
+ padding: 0px;
+ background: #C0C0C0;
+}
+
+div.title
+{
+ height: 48px;
+ margin: 0px;
+ padding: 0px;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #FFFFFF #808080 #808080 #FFFFFF;
+ background: url("steel.gif");
+}
+
+div.title h1
+{
+ margin: 0px;
+ padding: 0px;
+ padding-top: 8px;
+ padding-left: 40%;
+ float: left;
+}
+
+div.title div
+{
+ margin: 0px;
+ padding: 0px;
+ padding-top: 12px;
+ padding-right: 20px;
+ float: right;
+}
+
+/* Settings for the section frames. */
+
+body.navigation
+{
+ margin: 0px;
+ padding: 0px;
+ background: #F8F8F8;
+}
+
+ul.navigation
+{
+ margin: 0px;
+ padding: 0px;
+ list-style: none;
+ text-align: center;
+ background: url("steel.gif");
+}
+
+ul.navigation li
+{
+ margin: 0px;
+ padding: 0px;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #FFFFFF #808080 #808080 #FFFFFF;
+ color: #000000;
+ font-weight: bold;
+}
+
+ul.navigation li.title
+{
+ margin: 0px;
+ padding: 4px 10px;
+ background: #E0E0E0;
+}
+
+ul.navigation li a
+{
+ margin: 0px;
+ padding: 6px 0px;
+ background: transparent;
+ color: #000000;
+ text-decoration: none;
+ display: block;
+}
+
+ul.navigation li a:hover,
+ul.navigation li a:focus
+{
+ background: #FFFFFF;
+}
+
+/* Settings for the yellow note tables. */
+
+table.note
+{
+ width: 408px;
+ border: none;
+ border-spacing: 0px;
+}
+
+td.shadow8
+{
+ width: 8px;
+ padding: 0px;
+ margin: 0px;
+ vertical-align: bottom;
+ background: transparent;
+}
+
+td.shadow400
+{
+ width: 400px;
+ padding: 0px;
+ margin: 0px;
+ text-align: right;
+ background: transparent;
+}
+
+td.note
+{
+ width: 380px;
+ background: #FFFFC0;
+ padding: 0px;
+ margin: 0px;
+}
+
+p.note
+{
+ padding: 0px;
+ margin: 0px 10px;
+ text-align: center;
+}
+
+p.author
+{
+ padding: 0px;
+ margin: 0px 10px;
+ text-align: right;
+}
diff --git a/third_party/java/proguard/proguard5.3.3/docs/testimonials.html b/third_party/java/proguard/proguard5.3.3/docs/testimonials.html
new file mode 100644
index 0000000000..c5dd9e8130
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/testimonials.html
@@ -0,0 +1,132 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard Testimonials</title>
+</head>
+<body>
+
+<script type="text/javascript" language="JavaScript">
+<!--
+if (window.self==window.top)
+ document.write('<a class="largebutton" target="_top" href="index.html#testimonials.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>')
+//-->
+</script>
+<noscript>
+<a class="largebutton" target="_top" href="index.html#testimonials.html">ProGuard index</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a>
+<a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a>
+<a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>
+</noscript>
+
+<h2>Testimonials</h2>
+
+And now for some shameless self-glorification and name-dropping...
+<p>
+<b>ProGuard</b> is probably the most popular java shrinker, optimizer, and
+obfuscator world-wide. It is being used by developers at companies and
+organizations like IBM, HP, Siemens, Nokia, Google, Intel, and NATO. It is the
+default tool in many development environments like Oracle's Wireless Toolkit,
+Netbeans, EclipseME, Google's Android SDK, and more. Although the quotes below
+probably don't represent official views of any kind, encouragements like these
+do keep me happy.
+<p>
+
+<center><table class="note">
+<tr><td class="note"><p class="note"><cite>
+ProGuard is <b>the</b> ultimate java obfuscator!
+</cite></p>
+<p class="author">P.S, IBM</p></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
+</tr></table></center>
+<p>
+
+From the Android Developers presentation on "<a target="other"
+href="https://www.youtube.com/watch?v=5frxLkO4oTM">Removing Unused Code</a>":
+<p>
+<center><table class="note">
+<tr><td class="note"><p class="note"><cite>
+ProGuard is a seriously sweet tool.
+</cite></p>
+<p class="author">D.E., Google</p></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
+</tr></table></center>
+<p>
+
+Also:
+<center><table class="note">
+<tr><td class="note"><p class="note"><cite>
+ProGuard is pure quality - powerful and trouble-free.
+</cite></p>
+<p class="author">M.B., Statestep</p></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
+</tr></table></center>
+<p>
+
+And:
+<center><table class="note">
+<tr><td class="note"><p class="note"><cite>
+It is the simplest and most robust obfuscator we have ever used.
+</cite></p>
+<p class="author">I.I., Hewlett-Packard</p></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
+</tr></table></center>
+<p>
+
+And indeed:
+<center><table class="note">
+<tr><td class="note"><p class="note"><cite>
+ProGuard rules. Much easier to use than the commercial alternatives.
+</cite></p>
+<p class="author">B.G., Quiotix Corp.</p></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
+</tr></table></center>
+<p>
+
+Straight from <b>ProGuard</b>'s open discussion forum:
+<p>
+<center><table class="note">
+<tr><td class="note"><p class="note"><cite>
+After searching for, trying to trial, and futzing with numerous other
+obfuscators and shrinkers, ProGuard stands out as the simplest, most robust,
+and accurate shrinker of them all.
+</cite></p>
+<p class="author">D.J., Joot</p></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
+</tr></table></center>
+<p>
+
+And, of course, the price is stunning:
+<p>
+<center><table class="note">
+<tr><td class="note"><p class="note"><cite>
+You could've been rich.
+</cite></p>
+<p class="author">My mother</p></td>
+<td class="shadow8"><img src="drop2.gif" width="8" height="100" /></td></tr><tr>
+<td class="shadow400"><img src="drop1.gif" width="400" height="8" /></td>
+<td class="shadow8"><img src="drop3.gif" width="8" height="8" /></td>
+</tr></table></center>
+
+<hr />
+<address>
+Copyright &copy; 2002-2017
+<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>.
+</address>
+
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/docs/title.gif b/third_party/java/proguard/proguard5.3.3/docs/title.gif
new file mode 100644
index 0000000000..5e6ca26147
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/title.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/docs/title.html b/third_party/java/proguard/proguard5.3.3/docs/title.html
new file mode 100644
index 0000000000..4779bd590a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/docs/title.html
@@ -0,0 +1,17 @@
+<!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="content-style-type" content="text/css">
+<link rel="stylesheet" type="text/css" href="style.css">
+<title>ProGuard</title>
+</head>
+<body class="title">
+
+<div class="title">
+<h1><img src="title.gif" width="154" height="29" alt="ProGuard" /></h1>
+<div>Version 5.3</div>
+</div>
+
+</body>
+</html>
diff --git a/third_party/java/proguard/proguard5.3.3/examples/android.pro b/third_party/java/proguard/proguard5.3.3/examples/android.pro
new file mode 100644
index 0000000000..10aa8053f8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/android.pro
@@ -0,0 +1,174 @@
+#
+# This ProGuard configuration file illustrates how to process Android
+# applications.
+# Usage:
+# java -jar proguard.jar @android.pro
+#
+# If you're using the Android SDK, the Ant release build and Eclipse export
+# already take care of the proper settings. You only need to enable ProGuard
+# by commenting in the corresponding line in project.properties. You can still
+# add project-specific configuration in proguard-project.txt.
+#
+# This configuration file is for custom, stand-alone builds.
+
+# Specify the input jars, output jars, and library jars.
+# Note that ProGuard works with Java bytecode (.class),
+# before the dex compiler converts it into Dalvik code (.dex).
+
+-injars bin/classes
+-injars libs
+-outjars bin/classes-processed.jar
+
+-libraryjars /usr/local/android-sdk/platforms/android-9/android.jar
+#-libraryjars /usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar
+# ...
+
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on.
+
+-printmapping bin/classes-processed.map
+
+# You can print out the seeds that are matching the keep options below.
+
+#-printseeds bin/classes-processed.seeds
+
+# Preverification is irrelevant for the dex compiler and the Dalvik VM.
+
+-dontpreverify
+
+# Reduce the size of the output some more.
+
+-repackageclasses ''
+-allowaccessmodification
+
+# Switch off some optimizations that trip older versions of the Dalvik VM.
+
+-optimizations !code/simplification/arithmetic
+
+# Keep a fixed source file attribute and all line number tables to get line
+# numbers in the stack traces.
+# You can comment this out if you're not interested in stack traces.
+
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
+
+# RemoteViews might need annotations.
+
+-keepattributes *Annotation*
+
+# Preserve all fundamental application classes.
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+
+# Preserve all View implementations, their special context constructors, and
+# their setters.
+
+-keep public class * extends android.view.View {
+ public <init>(android.content.Context);
+ public <init>(android.content.Context, android.util.AttributeSet);
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+ public void set*(...);
+}
+
+# Preserve all classes that have special context constructors, and the
+# constructors themselves.
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+# Preserve all classes that have special context constructors, and the
+# constructors themselves.
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+# Preserve all possible onClick handlers.
+
+-keepclassmembers class * extends android.content.Context {
+ public void *(android.view.View);
+ public void *(android.view.MenuItem);
+}
+
+# Preserve the special fields of all Parcelable implementations.
+
+-keepclassmembers class * implements android.os.Parcelable {
+ static android.os.Parcelable$Creator CREATOR;
+}
+
+# Preserve static fields of inner classes of R classes that might be accessed
+# through introspection.
+
+-keepclassmembers class **.R$* {
+ public static <fields>;
+}
+
+# Preserve annotated Javascript interface methods.
+
+-keepclassmembers class * {
+ @android.webkit.JavascriptInterface <methods>;
+}
+
+# Preserve the required interface from the License Verification Library
+# (but don't nag the developer if the library is not used at all).
+
+-keep public interface com.android.vending.licensing.ILicensingService
+
+-dontnote com.android.vending.licensing.ILicensingService
+
+# The Android Compatibility library references some classes that may not be
+# present in all versions of the API, but we know that's ok.
+
+-dontwarn android.support.**
+
+# Preserve all native method names and the names of their classes.
+
+-keepclasseswithmembernames,includedescriptorclasses class * {
+ native <methods>;
+}
+
+# Preserve the special static methods that are required in all enumeration
+# classes.
+
+-keepclassmembers,allowoptimization enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# Explicitly preserve all serialization members. The Serializable interface
+# is only a marker interface, so it wouldn't save them.
+# You can comment this out if your application doesn't use serialization.
+# If your code contains serializable classes that have to be backward
+# compatible, please refer to the manual.
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+
+# Your application may contain more items that need to be preserved;
+# typically classes that are dynamically created using Class.forName:
+
+# -keep public class mypackage.MyClass
+# -keep public interface mypackage.MyInterface
+# -keep public class * implements mypackage.MyInterface
+
+# If you wish, you can let the optimization step remove Android logging calls.
+
+#-assumenosideeffects class android.util.Log {
+# public static boolean isLoggable(java.lang.String, int);
+# public static int v(...);
+# public static int i(...);
+# public static int w(...);
+# public static int d(...);
+# public static int e(...);
+#}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/examples.pro b/third_party/java/proguard/proguard5.3.3/examples/annotations/examples.pro
new file mode 100644
index 0000000000..d2b212c733
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/examples.pro
@@ -0,0 +1,60 @@
+#
+# This ProGuard configuration file illustrates how to use annotations for
+# specifying which classes and class members should be kept.
+# Usage:
+# java -jar proguard.jar @examples.pro
+#
+
+# Specify the input, output, and library jars.
+# This is assuming the code has been compiled in the examples directory.
+
+-injars examples(*.class)
+-outjars out
+
+-libraryjars <java.home>/lib/rt.jar
+
+# Some important configuration is based on the annotations in the code.
+# We have to specify what the annotations mean to ProGuard.
+
+-include lib/annotations.pro
+
+#
+# We can then still add any other options that might be useful.
+#
+
+# Print out a list of what we're preserving.
+
+-printseeds
+
+# Preserve all annotations themselves.
+
+-keepattributes *Annotation*
+
+# Preserve all native method names and the names of their classes.
+
+-keepclasseswithmembernames,includedescriptorclasses class * {
+ native <methods>;
+}
+
+# Preserve the special static methods that are required in all enumeration
+# classes.
+
+-keepclassmembers,allowoptimization enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# Explicitly preserve all serialization members. The Serializable interface
+# is only a marker interface, so it wouldn't save them.
+# You can comment this out if your application doesn't use serialization.
+# If your code contains serializable classes that have to be backward
+# compatible, please refer to the manual.
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Applet.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Applet.java
new file mode 100644
index 0000000000..e5b7accac4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Applet.java
@@ -0,0 +1,23 @@
+import proguard.annotation.*;
+
+/**
+ * This applet illustrates the use of annotations for configuring ProGuard.
+ *
+ * You can compile it with:
+ * javac -classpath ../lib/annotations.jar Applet.java
+ * You can then process it with:
+ * java -jar ../../../lib/proguard.jar @ ../examples.pro
+ *
+ * The annotation will preserve the class and its essential methods,
+ * as a result of the specifications in lib/annotations.pro.
+ */
+@Keep
+public class Applet extends java.applet.Applet
+{
+ // Implementations for Applet.
+
+ public void init()
+ {
+ // ...
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Application.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Application.java
new file mode 100644
index 0000000000..777d2865a7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Application.java
@@ -0,0 +1,21 @@
+import proguard.annotation.KeepApplication;
+
+/**
+ * This application illustrates the use of annotations for configuring ProGuard.
+ *
+ * You can compile it with:
+ * javac -classpath ../lib/annotations.jar Application.java
+ * You can then process it with:
+ * java -jar ../../../lib/proguard.jar @ ../examples.pro
+ *
+ * The annotation will preserve the class and its main method,
+ * as a result of the specifications in lib/annotations.pro.
+ */
+@KeepApplication
+public class Application
+{
+ public static void main(String[] args)
+ {
+ System.out.println("The answer is 42");
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Bean.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Bean.java
new file mode 100644
index 0000000000..aacb501671
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/Bean.java
@@ -0,0 +1,57 @@
+import proguard.annotation.*;
+
+/**
+ * This bean illustrates the use of annotations for configuring ProGuard.
+ *
+ * You can compile it with:
+ * javac -classpath ../lib/annotations.jar Bean.java
+ * You can then process it with:
+ * java -jar ../../../lib/proguard.jar @ ../examples.pro
+ *
+ * The annotations will preserve the class and its public getters and setters,
+ * as a result of the specifications in lib/annotations.pro.
+ */
+@Keep
+@KeepPublicGettersSetters
+public class Bean
+{
+ public boolean booleanProperty;
+ public int intProperty;
+ public String stringProperty;
+
+
+ public boolean isBooleanProperty()
+ {
+ return booleanProperty;
+ }
+
+
+ public void setBooleanProperty(boolean booleanProperty)
+ {
+ this.booleanProperty = booleanProperty;
+ }
+
+
+ public int getIntProperty()
+ {
+ return intProperty;
+ }
+
+
+ public void setIntProperty(int intProperty)
+ {
+ this.intProperty = intProperty;
+ }
+
+
+ public String getStringProperty()
+ {
+ return stringProperty;
+ }
+
+
+ public void setStringProperty(String stringProperty)
+ {
+ this.stringProperty = stringProperty;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/NativeCallBack.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/NativeCallBack.java
new file mode 100644
index 0000000000..a4e5583e18
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/examples/NativeCallBack.java
@@ -0,0 +1,52 @@
+import proguard.annotation.*;
+
+/**
+ * This application illustrates the use of annotations for configuring ProGuard.
+ *
+ * You can compile it with:
+ * javac -classpath ../lib/annotations.jar NativeCallBack.java
+ * You can then process it with:
+ * java -jar ../../../lib/proguard.jar @ ../examples.pro
+ *
+ * The annotation will preserve the class and its main method,
+ * as a result of the specifications in lib/annotations.pro.
+ */
+@KeepApplication
+public class NativeCallBack
+{
+ /**
+ * Suppose this is a native method that computes an answer.
+ *
+ * The -keep option for native methods in the regular ProGuard
+ * configuration will make sure it is not removed or renamed when
+ * processing this code.
+ */
+ public native int computeAnswer();
+
+
+ /**
+ * Suppose this method is called back from the above native method.
+ *
+ * ProGuard would remove it, because it is not referenced from java.
+ * The annotation will make sure it is preserved anyhow.
+ */
+ @Keep
+ public int getAnswer()
+ {
+ return 42;
+ }
+
+
+ /**
+ * The main entry point of the application.
+ *
+ * The @KeepApplication annotation of this class will make sure it is not
+ * removed or renamed when processing this code.
+ */
+ public static void main(String[] args)
+ {
+ int answer = new NativeCallBack().computeAnswer();
+
+ System.out.println("The answer is " + answer);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/lib/annotations.jar b/third_party/java/proguard/proguard5.3.3/examples/annotations/lib/annotations.jar
new file mode 100644
index 0000000000..671c57c324
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/lib/annotations.jar
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/lib/annotations.pro b/third_party/java/proguard/proguard5.3.3/examples/annotations/lib/annotations.pro
new file mode 100644
index 0000000000..f704af2dd4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/lib/annotations.pro
@@ -0,0 +1,118 @@
+#
+# This ProGuard configuration file specifies how annotations can be used
+# to configure the processing of other code.
+# Usage:
+# java -jar proguard.jar @annotations.pro -libraryjars annotations.jar ...
+#
+# Note that the other input/output options still have to be specified.
+# If you specify them in a separate file, you can simply include this file:
+# -include annotations.pro
+#
+# You can add any other options that are required. For instance, if you are
+# processing a library, you can still include the options from library.pro.
+
+
+# The annotations are defined in the accompanying jar. For now, we'll start
+# with these. You can always define your own annotations, if necessary.
+-libraryjars annotations.jar
+
+
+# The following annotations can be specified with classes and with class
+# members.
+
+# @Keep specifies not to shrink, optimize, or obfuscate the annotated class
+# or class member as an entry point.
+
+-keep @proguard.annotation.Keep class *
+
+-keepclassmembers class * {
+ @proguard.annotation.Keep *;
+}
+
+
+# @KeepName specifies not to optimize or obfuscate the annotated class or
+# class member as an entry point.
+
+-keepnames @proguard.annotation.KeepName class *
+
+-keepclassmembernames class * {
+ @proguard.annotation.KeepName *;
+}
+
+
+# The following annotations can only be specified with classes.
+
+# @KeepImplementations and @KeepPublicImplementations specify to keep all,
+# resp. all public, implementations or extensions of the annotated class as
+# entry points. Note the extension of the java-like syntax, adding annotations
+# before the (wild-carded) interface name.
+
+-keep class * implements @proguard.annotation.KeepImplementations *
+-keep public class * implements @proguard.annotation.KeepPublicImplementations *
+
+# @KeepApplication specifies to keep the annotated class as an application,
+# together with its main method.
+
+-keepclasseswithmembers @proguard.annotation.KeepApplication public class * {
+ public static void main(java.lang.String[]);
+}
+
+# @KeepClassMembers, @KeepPublicClassMembers, and
+# @KeepPublicProtectedClassMembers specify to keep all, all public, resp.
+# all public or protected, class members of the annotated class from being
+# shrunk, optimized, or obfuscated as entry points.
+
+-keepclassmembers @proguard.annotation.KeepClassMembers class * {
+ *;
+}
+
+-keepclassmembers @proguard.annotation.KeepPublicClassMembers class * {
+ public *;
+}
+
+-keepclassmembers @proguard.annotation.KeepPublicProtectedClassMembers class * {
+ public protected *;
+}
+
+# @KeepClassMemberNames, @KeepPublicClassMemberNames, and
+# @KeepPublicProtectedClassMemberNames specify to keep all, all public, resp.
+# all public or protected, class members of the annotated class from being
+# optimized or obfuscated as entry points.
+
+-keepclassmembernames @proguard.annotation.KeepClassMemberNames class * {
+ *;
+}
+
+-keepclassmembernames @proguard.annotation.KeepPublicClassMemberNames class * {
+ public *;
+}
+
+-keepclassmembernames @proguard.annotation.KeepPublicProtectedClassMemberNames class * {
+ public protected *;
+}
+
+# @KeepGettersSetters and @KeepPublicGettersSetters specify to keep all, resp.
+# all public, getters and setters of the annotated class from being shrunk,
+# optimized, or obfuscated as entry points.
+
+-keepclassmembers @proguard.annotation.KeepGettersSetters class * {
+ void set*(***);
+ void set*(int, ***);
+
+ boolean is*();
+ boolean is*(int);
+
+ *** get*();
+ *** get*(int);
+}
+
+-keepclassmembers @proguard.annotation.KeepPublicGettersSetters class * {
+ public void set*(***);
+ public void set*(int, ***);
+
+ public boolean is*();
+ public boolean is*(int);
+
+ public *** get*();
+ public *** get*(int);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/Keep.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/Keep.java
new file mode 100644
index 0000000000..2e5ad04984
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/Keep.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies not to optimize or obfuscate the annotated class or
+ * class member as an entry point.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface Keep {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepApplication.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepApplication.java
new file mode 100644
index 0000000000..072a80db5b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepApplication.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies to keep the annotated class as an application,
+ * together with its a main method.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepApplication {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepClassMemberNames.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepClassMemberNames.java
new file mode 100644
index 0000000000..4adb5ec35e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepClassMemberNames.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies to keep all class members of the annotated class
+ * from being optimized or obfuscated as entry points.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepClassMemberNames {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepClassMembers.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepClassMembers.java
new file mode 100644
index 0000000000..9cdfc6798b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepClassMembers.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies to keep all class members of the annotated class
+ * from being shrunk, optimized, or obfuscated as entry points.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepClassMembers {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepGettersSetters.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepGettersSetters.java
new file mode 100644
index 0000000000..37d7cc7756
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepGettersSetters.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies to keep all getters and setters of the annotated
+ * class from being shrunk, optimized, or obfuscated as entry points.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepGettersSetters {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepImplementations.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepImplementations.java
new file mode 100644
index 0000000000..b2bce128e8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepImplementations.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies to keep all implementations or extensions of the
+ * annotated class as entry points.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepImplementations {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepName.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepName.java
new file mode 100644
index 0000000000..ec1574bb21
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepName.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies not to optimize or obfuscate the annotated class or
+ * class member as an entry point.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepName {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicClassMemberNames.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicClassMemberNames.java
new file mode 100644
index 0000000000..e951f19750
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicClassMemberNames.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies to keep all public class members of the annotated
+ * class from being optimized or obfuscated as entry points.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepPublicClassMemberNames {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicClassMembers.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicClassMembers.java
new file mode 100644
index 0000000000..480c03641f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicClassMembers.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies to keep all public class members of the annotated
+ * class from being shrunk, optimized, or obfuscated as entry points.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepPublicClassMembers {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicGettersSetters.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicGettersSetters.java
new file mode 100644
index 0000000000..3b6f8e6aed
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicGettersSetters.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies to keep all public getters and setters of the
+ * annotated class from being shrunk, optimized, or obfuscated as entry points.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepPublicGettersSetters {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicImplementations.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicImplementations.java
new file mode 100644
index 0000000000..c777d9be27
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicImplementations.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies to keep all public implementations or extensions
+ * of the annotated class as entry points.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepPublicImplementations {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicProtectedClassMemberNames.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicProtectedClassMemberNames.java
new file mode 100644
index 0000000000..f4511ea037
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicProtectedClassMemberNames.java
@@ -0,0 +1,18 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies to keep all public or protected class members of
+ * the annotated class from being optimized or obfuscated as entry points.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepPublicProtectedClassMemberNames {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicProtectedClassMembers.java b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicProtectedClassMembers.java
new file mode 100644
index 0000000000..5b195bbfc8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/annotations/src/proguard/annotation/KeepPublicProtectedClassMembers.java
@@ -0,0 +1,19 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ */
+package proguard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation specifies to keep all public or protected class members of
+ * the annotated class from being shrunk, optimized, or obfuscated as entry
+ * points.
+ *
+ * @author Eric Lafortune
+ */
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface KeepPublicProtectedClassMembers {}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/ant/applets.xml b/third_party/java/proguard/proguard5.3.3/examples/ant/applets.xml
new file mode 100644
index 0000000000..5666f965b2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/ant/applets.xml
@@ -0,0 +1,88 @@
+<!-- This Ant build file illustrates how to process applets.
+ Usage: ant -f applets.xml -->
+
+<project name="Applets" default="obfuscate" basedir="../..">
+
+<target name="obfuscate">
+ <taskdef resource="proguard/ant/task.properties"
+ classpath="lib/proguard.jar" />
+
+ <proguard printseeds="on"
+ printmapping="out.map"
+ renamesourcefileattribute="SourceFile">
+
+ <!-- Specify the input jars, output jars, and library jars. -->
+
+ <injar file="in.jar" />
+ <outjar file="out.jar" />
+
+ <libraryjar file="${java.home}/lib/rt.jar" />
+
+ <!-- Optionally preserve line numbers in the obfuscated stack traces.
+ <keepattribute name="LineNumberTable">
+ <keepattribute name="SourceFile">
+ -->
+
+ <!-- Preserve all annotations. -->
+
+ <keepattribute name="*Annotation*" />
+
+ <!-- Preserve all public applets. -->
+
+ <keep access="public" extends="java.applet.Applet" />
+
+ <!-- Preserve all native method names and the names of their classes. -->
+
+ <keepclasseswithmembernames includedescriptorclasses="true">
+ <method access="native" />
+ </keepclasseswithmembernames>
+
+ <!-- Preserve the methods that are required in all enumeration classes. -->
+
+ <keepclassmembers allowoptimization="true" type="enum">
+ <method access="public static"
+ type="**[]"
+ name="values"
+ parameters="" />
+ <method access="public static"
+ type="**"
+ name="valueOf"
+ parameters="java.lang.String" />
+ </keepclassmembers>
+
+ <!-- Explicitly preserve all serialization members. The Serializable
+ interface is only a marker interface, so it wouldn't save them.
+ You can comment this out if your library doesn't use serialization.
+ If your code contains serializable classes that have to be backward
+ compatible, please refer to the manual. -->
+
+ <keepclassmembers implements="java.io.Serializable">
+ <field access ="static final"
+ type ="long"
+ name ="serialVersionUID" />
+ <field access ="static final"
+ type ="java.io.ObjectStreamField[]"
+ name ="serialPersistentFields" />
+ <method access ="private"
+ type ="void"
+ name ="writeObject"
+ parameters="java.io.ObjectOutputStream" />
+ <method access ="private"
+ type ="void"
+ name ="readObject"
+ parameters="java.io.ObjectInputStream" />
+ <method type ="java.lang.Object"
+ name ="writeReplace"
+ parameters="" />
+ <method type ="java.lang.Object"
+ name ="readResolve"
+ parameters="" />
+ </keepclassmembers>
+
+ <!-- Your application may contain more items that need to be preserved;
+ typically classes that are dynamically created using Class.forName -->
+
+ </proguard>
+</target>
+
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/examples/ant/applications1.xml b/third_party/java/proguard/proguard5.3.3/examples/ant/applications1.xml
new file mode 100644
index 0000000000..6df5789eb0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/ant/applications1.xml
@@ -0,0 +1,15 @@
+<!-- This Ant build file illustrates how to process applications,
+ by including a ProGuard-style configuration file.
+ Usage: ant -f applications1.xml -->
+
+<project name="Applications" default="obfuscate" basedir="../..">
+
+<target name="obfuscate">
+ <taskdef resource="proguard/ant/task.properties"
+ classpath="lib/proguard.jar" />
+
+ <proguard configuration="examples/applications.pro" />
+
+</target>
+
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/examples/ant/applications2.xml b/third_party/java/proguard/proguard5.3.3/examples/ant/applications2.xml
new file mode 100644
index 0000000000..664a9ee86f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/ant/applications2.xml
@@ -0,0 +1,74 @@
+<!-- This Ant build file illustrates how to process applications,
+ by including ProGuard-style configuration options.
+ Usage: ant -f applications2.xml -->
+
+<project name="Applications" default="obfuscate" basedir="../..">
+
+<target name="obfuscate">
+ <taskdef resource="proguard/ant/task.properties"
+ classpath="lib/proguard.jar" />
+
+ <proguard>
+
+ <!-- Specify the input jars, output jars, and library jars. -->
+
+ -injars in.jar
+ -outjars out.jar
+
+ -libraryjars ${java.home}/lib/rt.jar
+ <!-- -libraryjars junit.jar -->
+ <!-- -libraryjars servlet.jar -->
+ <!-- -libraryjars jai_core.jar -->
+ <!-- ... -->
+
+ <!-- Save the obfuscation mapping to a file, and preserve line numbers. -->
+
+ -printmapping out.map
+ -renamesourcefileattribute SourceFile
+ -keepattributes SourceFile,LineNumberTable
+
+ <!-- Preserve all annotations. -->
+
+ -keepattributes *Annotation*
+
+ <!-- Preserve all public applications. -->
+
+ -keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+ }
+
+ <!-- Preserve all native method names and the names of their classes. -->
+
+ -keepclasseswithmembernames class * {
+ native &lt;methods&gt;;
+ }
+
+ <!-- Preserve the methods that are required in all enumeration classes. -->
+
+ -keepclassmembers,allowoptimization enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+ }
+
+ <!-- Explicitly preserve all serialization members. The Serializable
+ interface is only a marker interface, so it wouldn't save them.
+ You can comment this out if your library doesn't use serialization.
+ If your code contains serializable classes that have to be backward
+ compatible, please refer to the manual. -->
+
+ -keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+ }
+
+ <!-- Your application may contain more items that need to be preserved;
+ typically classes that are dynamically created using Class.forName -->
+
+ </proguard>
+</target>
+
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/examples/ant/applications3.xml b/third_party/java/proguard/proguard5.3.3/examples/ant/applications3.xml
new file mode 100644
index 0000000000..023c2bef9a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/ant/applications3.xml
@@ -0,0 +1,98 @@
+<!-- This Ant build file illustrates how to process applications,
+ using a full-blown XML configuration.
+ Usage: ant -f applications3.xml -->
+
+<project name="Applications" default="obfuscate" basedir="../..">
+
+<target name="obfuscate">
+ <taskdef resource="proguard/ant/task.properties"
+ classpath="lib/proguard.jar" />
+
+ <proguard printseeds="on"
+ printmapping="out.map"
+ renamesourcefileattribute="SourceFile">
+
+ <!-- Specify the input jars, output jars, and library jars. -->
+
+ <injar file="in.jar" />
+ <outjar file="out.jar" />
+
+ <libraryjar file="${java.home}/lib/rt.jar" />
+ <!-- libraryjar file="junit.jar" / -->
+ <!-- libraryjar file="servlet.jar" / -->
+ <!-- libraryjar file="jai_core.jar" / -->
+ <!-- ... / -->
+
+ <!-- Preserve line numbers in the obfuscated stack traces. -->
+
+ <keepattribute name="LineNumberTable" />
+ <keepattribute name="SourceFile" />
+
+ <!-- Preserve all annotations. -->
+
+ <keepattribute name="*Annotation*" />
+
+ <!-- Preserve all public applications. -->
+
+ <keepclasseswithmembers access="public">
+ <method access ="public static"
+ type ="void"
+ name ="main"
+ parameters="java.lang.String[]" />
+ </keepclasseswithmembers>
+
+ <!-- Preserve all native method names and the names of their classes. -->
+
+ <keepclasseswithmembernames includedescriptorclasses="true">
+ <method access="native" />
+ </keepclasseswithmembernames>
+
+ <!-- Preserve the methods that are required in all enumeration classes. -->
+
+ <keepclassmembers allowoptimization="true" type="enum">
+ <method access="public static"
+ type="**[]"
+ name="values"
+ parameters="" />
+ <method access="public static"
+ type="**"
+ name="valueOf"
+ parameters="java.lang.String" />
+ </keepclassmembers>
+
+ <!-- Explicitly preserve all serialization members. The Serializable
+ interface is only a marker interface, so it wouldn't save them.
+ You can comment this out if your library doesn't use serialization.
+ If your code contains serializable classes that have to be backward
+ compatible, please refer to the manual. -->
+
+ <keepclassmembers implements="java.io.Serializable">
+ <field access ="static final"
+ type ="long"
+ name ="serialVersionUID" />
+ <field access ="static final"
+ type ="java.io.ObjectStreamField[]"
+ name ="serialPersistentFields" />
+ <method access ="private"
+ type ="void"
+ name ="writeObject"
+ parameters="java.io.ObjectOutputStream" />
+ <method access ="private"
+ type ="void"
+ name ="readObject"
+ parameters="java.io.ObjectInputStream" />
+ <method type ="java.lang.Object"
+ name ="writeReplace"
+ parameters="" />
+ <method type ="java.lang.Object"
+ name ="readResolve"
+ parameters="" />
+ </keepclassmembers>
+
+ <!-- Your application may contain more items that need to be preserved;
+ typically classes that are dynamically created using Class.forName -->
+
+ </proguard>
+</target>
+
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/examples/ant/library.xml b/third_party/java/proguard/proguard5.3.3/examples/ant/library.xml
new file mode 100644
index 0000000000..37ceb1a8da
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/ant/library.xml
@@ -0,0 +1,102 @@
+<!-- This Ant build file illustrates how to process a program library,
+ such that it remains usable as a library.
+ Usage: ant -f library.xml -->
+
+<project name="Library" default="obfuscate" basedir="../..">
+
+<target name="obfuscate">
+ <taskdef resource="proguard/ant/task.properties"
+ classpath="lib/proguard.jar" />
+
+ <proguard printmapping="out.map"
+ renamesourcefileattribute="SourceFile">
+
+ <!-- Specify the input jars, output jars, and library jars. -->
+
+ <injar file="library.jar" />
+ <outjar file="library_out.jar" />
+
+ <libraryjar file="${java.home}/lib/rt.jar" />
+
+ <!-- Keep some useful attributes. -->
+
+ <keepattribute name="InnerClasses" />
+ <keepattribute name="SourceFile" />
+ <keepattribute name="LineNumberTable" />
+ <keepattribute name="Deprecated" />
+ <keepattribute name="*Annotation*" />
+
+ <!-- Preserve all public classes, and their public and protected fields
+ and methods. -->
+
+ <keep access="public">
+ <field access="public protected" />
+ <method access="public protected" />
+ </keep>
+
+ <!-- Preserve all .class method names. -->
+
+ <keepclassmembernames access="public">
+ <method type ="java.lang.Class"
+ name ="class$"
+ parameters="java.lang.String" />
+ <method type ="java.lang.Class"
+ name ="class$"
+ parameters="java.lang.String,boolean" />
+ </keepclassmembernames>
+
+ <!-- Preserve all native method names and the names of their classes. -->
+
+ <keepclasseswithmembernames includedescriptorclasses="true">
+ <method access="native" />
+ </keepclasseswithmembernames>
+
+ <!-- Preserve the methods that are required in all enumeration classes. -->
+
+ <keepclassmembers allowoptimization="true" type="enum">
+ <method access="public static"
+ type="**[]"
+ name="values"
+ parameters="" />
+ <method access="public static"
+ type="**"
+ name="valueOf"
+ parameters="java.lang.String" />
+ </keepclassmembers>
+
+ <!-- Explicitly preserve all serialization members. The Serializable
+ interface is only a marker interface, so it wouldn't save them.
+ You can comment this out if your library doesn't use serialization.
+ If your code contains serializable classes that have to be backward
+ compatible, please refer to the manual. -->
+
+ <keepclassmembers implements="java.io.Serializable">
+ <field access ="final"
+ type ="long"
+ name ="serialVersionUID" />
+ <field access ="static final"
+ type ="java.io.ObjectStreamField[]"
+ name ="serialPersistentFields" />
+ <method access ="private"
+ type ="void"
+ name ="writeObject"
+ parameters="java.io.ObjectOutputStream" />
+ <method access ="private"
+ type ="void"
+ name ="readObject"
+ parameters="java.io.ObjectInputStream" />
+ <method type ="java.lang.Object"
+ name ="writeReplace"
+ parameters="" />
+ <method type ="java.lang.Object"
+ name ="readResolve"
+ parameters="" />
+ </keepclassmembers>
+
+ <!-- Your application may contain more items that need to be preserved;
+ typically classes that are dynamically created using Class.forName -->
+
+ </proguard>
+</target>
+
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/examples/ant/midlets.xml b/third_party/java/proguard/proguard5.3.3/examples/ant/midlets.xml
new file mode 100644
index 0000000000..fe17277a37
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/ant/midlets.xml
@@ -0,0 +1,52 @@
+<!-- This Ant build file illustrates how to process J2ME midlets.
+ Usage: ant -f midlets.xml -->
+
+<project name="Midlets" default="obfuscate" basedir="../..">
+
+<target name="obfuscate">
+ <taskdef resource="proguard/ant/task.properties"
+ classpath="lib/proguard.jar" />
+
+ <proguard microedition="on"
+ printseeds="on"
+ printmapping="out.map"
+ overloadaggressively="on"
+ repackageclasses=""
+ allowaccessmodification="on"
+ renamesourcefileattribute="SourceFile">
+
+ <!-- On Windows, you can't use mixed case class names,
+ should you still want to use the preverify tool.
+ usemixedcaseclassnames="false">
+ -->
+
+ <!-- Specify the input jars, output jars, and library jars. -->
+
+ <injar file="in.jar" />
+ <outjar file="out.jar" />
+
+ <libraryjar file="/usr/local/java/wtk2.5.2/lib/midpapi20.jar" />
+ <libraryjar file="/usr/local/java/wtk2.5.2/lib/cldcapi11.jar" />
+
+ <!-- Optionally preserve line numbers in the obfuscated stack traces.
+ <keepattribute name="LineNumberTable">
+ <keepattribute name="SourceFile">
+ -->
+
+ <!-- Preserve all public midlets. -->
+
+ <keep access="public" extends="javax.microedition.midlet.MIDlet" />
+
+ <!-- Preserve all native method names and the names of their classes. -->
+
+ <keepclasseswithmembernames includedescriptorclasses="true">
+ <method access="native" />
+ </keepclasseswithmembernames>
+
+ <!-- Your application may contain more items that need to be preserved;
+ typically classes that are dynamically created using Class.forName -->
+
+ </proguard>
+</target>
+
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/examples/ant/proguard.xml b/third_party/java/proguard/proguard5.3.3/examples/ant/proguard.xml
new file mode 100644
index 0000000000..f37c266aa0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/ant/proguard.xml
@@ -0,0 +1,89 @@
+<!-- This Ant build file illustrates how to process ProGuard (including its
+ main application, its GUI, its Ant task, and its WTK plugin), and the
+ ReTrace tool, all in one go.
+ Usage: ant -f proguard.xml -->
+
+<project name="ProGuard" default="obfuscate" basedir="../..">
+
+<target name="obfuscate">
+ <taskdef resource="proguard/ant/task.properties"
+ classpath="lib/proguard.jar" />
+
+ <proguard printmapping="proguard.map"
+ overloadaggressively="on"
+ repackageclasses=""
+ renamesourcefileattribute="SourceFile">
+
+ <!-- Specify the input jars, output jars, and library jars. -->
+
+ <injar file="lib/proguard.jar" />
+ <injar file="lib/proguardgui.jar" filter="!META-INF/**" />
+ <injar file="lib/retrace.jar" filter="!META-INF/**" />
+
+ <outjar file="examples/ant/proguard_out.jar" />
+
+ <libraryjar file="${java.home}/lib/rt.jar" />
+ <libraryjar file="/usr/local/java/ant/lib/ant.jar" />
+ <libraryjar file="/usr/local/java/gradle-2.12/lib/plugins/gradle-plugins-2.12.jar" />
+ <libraryjar file="/usr/local/java/gradle-2.12/lib/gradle-base-services-2.12.jar" />
+ <libraryjar file="/usr/local/java/gradle-2.12/lib/gradle-base-services-groovy-2.12.jar" />
+ <libraryjar file="/usr/local/java/gradle-2.12/lib/gradle-core-2.12.jar" />
+ <libraryjar file="/usr/local/java/gradle-2.12/lib/groovy-all-2.4.4.jar" />
+ <libraryjar file="/usr/local/java/wtk2.5.2/wtklib/kenv.zip" />
+
+ <!-- Adapt the resource file names, based on the corresponding obfuscated
+ class names. -->
+
+ <adaptresourcefilenames filter="**.properties,**.gif,**.jpg" />
+ <adaptresourcefilecontents filter="proguard/ant/task.properties" />
+
+ <!-- Optionally preserve line numbers in the obfuscated stack traces.
+ <keepattribute name="LineNumberTable">
+ <keepattribute name="SourceFile">
+ -->
+
+ <!-- The main seeds: ProGuard and its companion tool ReTrace. -->
+
+ <keep access="public" name="proguard.ProGuard">
+ <method access ="public static"
+ type ="void"
+ name ="main"
+ parameters="java.lang.String[]" />
+ </keep>
+ <keep access="public" name="proguard.gui.ProGuardGUI">
+ <method access ="public static"
+ type ="void"
+ name ="main"
+ parameters="java.lang.String[]" />
+ </keep>
+ <keep access="public" name="proguard.retrace.ReTrace">
+ <method access ="public static"
+ type ="void"
+ name ="main"
+ parameters="java.lang.String[]" />
+ </keep>
+
+ <!-- If we have ant.jar, we can properly process the Ant task. -->
+
+ <keeppackagename name="proguard.ant" />
+ <keep name="proguard.ant.*" allowobfuscation="true" />
+ <keepclassmembers access="public" name="proguard.ant.*">
+ <constructor parameters="org.apache.tools.ant.Project" />
+ <method access="public" type="void" name="set*" parameters="***" />
+ <method access="public" type="void" name="add*" parameters="***" />
+ </keepclassmembers>
+
+ <!-- If we have the Gradle jars, we can properly process the Gradle task. -->
+
+ <keep access="public" name="proguard.gradle.*">
+ <method access="public" />
+ </keep>
+
+ <!-- If we have kenv.zip, we can process the J2ME WTK plugin. -->
+
+ <keep access="public" name="proguard.wtk.ProGuardObfuscator" />
+
+ </proguard>
+</target>
+
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/examples/ant/servlets.xml b/third_party/java/proguard/proguard5.3.3/examples/ant/servlets.xml
new file mode 100644
index 0000000000..33ca6cec9a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/ant/servlets.xml
@@ -0,0 +1,88 @@
+<!-- This Ant build file illustrates how to process servlets.
+ Usage: ant -f servlets.xml -->
+
+<project name="Servlets" default="obfuscate" basedir="../..">
+
+<target name="obfuscate">
+ <taskdef resource="proguard/ant/task.properties"
+ classpath="lib/proguard.jar" />
+
+ <proguard printseeds="on"
+ printmapping="proguard.map"
+ renamesourcefileattribute="SourceFile">
+
+ <!-- Specify the input jars, output jars, and library jars. -->
+
+ <injar file="in.jar" />
+ <outjar file="out.jar" />
+
+ <libraryjar file="${java.home}/lib/rt.jar" />
+
+ <!-- Optionally preserve line numbers in the obfuscated stack traces.
+ <keepattribute name="LineNumberTable">
+ <keepattribute name="SourceFile">
+ -->
+
+ <!-- Preserve all annotations. -->
+
+ <keepattribute name="*Annotation*" />
+
+ <!-- Keep all public servlets. -->
+
+ <keep access="public" implements="javax.servlet.Servlet" />
+
+ <!-- Preserve all native method names and the names of their classes. -->
+
+ <keepclasseswithmembernames includedescriptorclasses="true">
+ <method access="native" />
+ </keepclasseswithmembernames>
+
+ <!-- Preserve the methods that are required in all enumeration classes. -->
+
+ <keepclassmembers allowoptimization="true" type="enum">
+ <method access="public static"
+ type="**[]"
+ name="values"
+ parameters="" />
+ <method access="public static"
+ type="**"
+ name="valueOf"
+ parameters="java.lang.String" />
+ </keepclassmembers>
+
+ <!-- Explicitly preserve all serialization members. The Serializable
+ interface is only a marker interface, so it wouldn't save them.
+ You can comment this out if your library doesn't use serialization.
+ If your code contains serializable classes that have to be backward
+ compatible, please refer to the manual. -->
+
+ <keepclassmembers implements="java.io.Serializable">
+ <field access ="static final"
+ type ="long"
+ name ="serialVersionUID" />
+ <field access ="static final"
+ type ="java.io.ObjectStreamField[]"
+ name ="serialPersistentFields" />
+ <method access ="private"
+ type ="void"
+ name ="writeObject"
+ parameters="java.io.ObjectOutputStream" />
+ <method access ="private"
+ type ="void"
+ name ="readObject"
+ parameters="java.io.ObjectInputStream" />
+ <method type ="java.lang.Object"
+ name ="writeReplace"
+ parameters="" />
+ <method type ="java.lang.Object"
+ name ="readResolve"
+ parameters="" />
+ </keepclassmembers>
+
+ <!-- Your application may contain more items that need to be preserved;
+ typically classes that are dynamically created using Class.forName -->
+
+ </proguard>
+</target>
+
+</project>
diff --git a/third_party/java/proguard/proguard5.3.3/examples/applets.pro b/third_party/java/proguard/proguard5.3.3/examples/applets.pro
new file mode 100644
index 0000000000..75256a0456
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/applets.pro
@@ -0,0 +1,69 @@
+#
+# This ProGuard configuration file illustrates how to process applets.
+# Usage:
+# java -jar proguard.jar @applets.pro
+#
+
+# Specify the input jars, output jars, and library jars.
+
+-injars in.jar
+-outjars out.jar
+
+-libraryjars <java.home>/lib/rt.jar
+
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on. Keep a fixed source file attribute and all line number
+# tables to get line numbers in the stack traces.
+# You can comment this out if you're not interested in stack traces.
+
+-printmapping out.map
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
+
+# Preserve all annotations.
+
+-keepattributes *Annotation*
+
+# You can print out the seeds that are matching the keep options below.
+
+#-printseeds out.seeds
+
+# Preserve all public applets.
+
+-keep public class * extends java.applet.Applet
+
+# Preserve all native method names and the names of their classes.
+
+-keepclasseswithmembernames,includedescriptorclasses class * {
+ native <methods>;
+}
+
+# Preserve the special static methods that are required in all enumeration
+# classes.
+
+-keepclassmembers,allowoptimization enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# Explicitly preserve all serialization members. The Serializable interface
+# is only a marker interface, so it wouldn't save them.
+# You can comment this out if your library doesn't use serialization.
+# If your code contains serializable classes that have to be backward
+# compatible, please refer to the manual.
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+
+# Your application may contain more items that need to be preserved;
+# typically classes that are dynamically created using Class.forName:
+
+# -keep public class mypackage.MyClass
+# -keep public interface mypackage.MyInterface
+# -keep public class * implements mypackage.MyInterface
diff --git a/third_party/java/proguard/proguard5.3.3/examples/applications.pro b/third_party/java/proguard/proguard5.3.3/examples/applications.pro
new file mode 100644
index 0000000000..5424423e61
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/applications.pro
@@ -0,0 +1,75 @@
+#
+# This ProGuard configuration file illustrates how to process applications.
+# Usage:
+# java -jar proguard.jar @applications.pro
+#
+
+# Specify the input jars, output jars, and library jars.
+
+-injars in.jar
+-outjars out.jar
+
+-libraryjars <java.home>/lib/rt.jar
+#-libraryjars junit.jar
+#-libraryjars servlet.jar
+#-libraryjars jai_core.jar
+#...
+
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on. Keep a fixed source file attribute and all line number
+# tables to get line numbers in the stack traces.
+# You can comment this out if you're not interested in stack traces.
+
+-printmapping out.map
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
+
+# Preserve all annotations.
+
+-keepattributes *Annotation*
+
+# You can print out the seeds that are matching the keep options below.
+
+#-printseeds out.seeds
+
+# Preserve all public applications.
+
+-keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+}
+
+# Preserve all native method names and the names of their classes.
+
+-keepclasseswithmembernames,includedescriptorclasses class * {
+ native <methods>;
+}
+
+# Preserve the special static methods that are required in all enumeration
+# classes.
+
+-keepclassmembers,allowoptimization enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# Explicitly preserve all serialization members. The Serializable interface
+# is only a marker interface, so it wouldn't save them.
+# You can comment this out if your application doesn't use serialization.
+# If your code contains serializable classes that have to be backward
+# compatible, please refer to the manual.
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+
+# Your application may contain more items that need to be preserved;
+# typically classes that are dynamically created using Class.forName:
+
+# -keep public class mypackage.MyClass
+# -keep public interface mypackage.MyInterface
+# -keep public class * implements mypackage.MyInterface
diff --git a/third_party/java/proguard/proguard5.3.3/examples/dictionaries/compact.txt b/third_party/java/proguard/proguard5.3.3/examples/dictionaries/compact.txt
new file mode 100644
index 0000000000..5636a3eede
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/dictionaries/compact.txt
@@ -0,0 +1,18 @@
+#
+# This obfuscation dictionary contains strings that are already present
+# in many class files. Since these strings can be shared, the resulting
+# obfuscated class files will generally be a little bit more compact.
+# Usage:
+# java -jar proguard.jar ..... -obfuscationdictionary compact.txt
+#
+
+Code
+V
+I
+Z
+B
+C
+S
+F
+D
+L
diff --git a/third_party/java/proguard/proguard5.3.3/examples/dictionaries/keywords.txt b/third_party/java/proguard/proguard5.3.3/examples/dictionaries/keywords.txt
new file mode 100644
index 0000000000..76f5a7b0ab
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/dictionaries/keywords.txt
@@ -0,0 +1,58 @@
+#
+# This obfuscation dictionary contains reserved Java keywords. They can't
+# be used in Java source files, but they can be used in compiled class files.
+# Note that this hardly improves the obfuscation. Decent decompilers can
+# automatically replace reserved keywords, and the effect can fairly simply be
+# undone by obfuscating again with simpler names.
+# Usage:
+# java -jar proguard.jar ..... -obfuscationdictionary keywords.txt
+#
+
+do
+if
+for
+int
+new
+try
+byte
+case
+char
+else
+goto
+long
+this
+void
+break
+catch
+class
+const
+final
+float
+short
+super
+throw
+while
+double
+import
+native
+public
+return
+static
+switch
+throws
+boolean
+default
+extends
+finally
+package
+private
+abstract
+continue
+strictfp
+volatile
+interface
+protected
+transient
+implements
+instanceof
+synchronized
diff --git a/third_party/java/proguard/proguard5.3.3/examples/dictionaries/shakespeare.txt b/third_party/java/proguard/proguard5.3.3/examples/dictionaries/shakespeare.txt
new file mode 100644
index 0000000000..28b1cd8d55
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/dictionaries/shakespeare.txt
@@ -0,0 +1,23 @@
+#
+# This obfuscation dictionary contains quotes from plays by Shakespeare.
+# It illustrates that any text can be used, for whatever flippant reasons
+# one may have.
+# Usage:
+# java -jar proguard.jar ..... -obfuscationdictionary shakespeare.txt
+#
+
+
+"This thing of darkness I acknowledge mine."
+
+ --From The Tempest (V, i, 275-276)
+
+
+"Though this be madness, yet there is method in 't."
+
+ --From Hamlet (II, ii, 206)
+
+
+"What's in a name? That which we call a rose
+ By any other word would smell as sweet."
+
+ --From Romeo and Juliet (II, ii, 1-2)
diff --git a/third_party/java/proguard/proguard5.3.3/examples/dictionaries/windows.txt b/third_party/java/proguard/proguard5.3.3/examples/dictionaries/windows.txt
new file mode 100644
index 0000000000..fd65dc977d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/dictionaries/windows.txt
@@ -0,0 +1,209 @@
+#
+# This obfuscation dictionary contains names that are not allowed as file names
+# in Windows, not even with extensions like .class or .java. They can however
+# be used without problems in jar archives, which just begs to apply them as
+# obfuscated class names. Trying to unpack the obfuscated archives in Windows
+# will probably generate some sparks.
+# Usage:
+# java -jar proguard.jar ..... -classobfuscationdictionary windows.txt
+# -packageobfuscationdictionary windows.txt
+#
+
+aux
+Aux
+aUx
+AUx
+auX
+AuX
+aUX
+AUX
+AUX
+con
+Con
+cOn
+COn
+coN
+CoN
+cON
+CON
+CON
+nul
+Nul
+nUl
+NUl
+nuL
+NuL
+nUL
+NUL
+NUL
+prn
+Prn
+pRn
+PRn
+prN
+PrN
+pRN
+PRN
+PRN
+com1
+Com1
+cOm1
+COm1
+coM1
+CoM1
+cOM1
+COM1
+COM1
+com2
+Com2
+cOm2
+COm2
+coM2
+CoM2
+cOM2
+COM2
+COM2
+com3
+Com3
+cOm3
+COm3
+coM3
+CoM3
+cOM3
+COM3
+COM3
+com4
+Com4
+cOm4
+COm4
+coM4
+CoM4
+cOM4
+COM4
+COM4
+com5
+Com5
+cOm5
+COm5
+coM5
+CoM5
+cOM5
+COM5
+COM5
+com6
+Com6
+cOm6
+COm6
+coM6
+CoM6
+cOM6
+COM6
+COM6
+com7
+Com7
+cOm7
+COm7
+coM7
+CoM7
+cOM7
+COM7
+COM7
+com8
+Com8
+cOm8
+COm8
+coM8
+CoM8
+cOM8
+COM8
+COM8
+com9
+Com9
+cOm9
+COm9
+coM9
+CoM9
+cOM9
+COM9
+COM9
+lpt1
+Lpt1
+lPt1
+LPt1
+lpT1
+LpT1
+lPT1
+LPT1
+LPT1
+lpt2
+Lpt2
+lPt2
+LPt2
+lpT2
+LpT2
+lPT2
+LPT2
+LPT2
+lpt3
+Lpt3
+lPt3
+LPt3
+lpT3
+LpT3
+lPT3
+LPT3
+LPT3
+lpt4
+Lpt4
+lPt4
+LPt4
+lpT4
+LpT4
+lPT4
+LPT4
+LPT4
+lpt5
+Lpt5
+lPt5
+LPt5
+lpT5
+LpT5
+lPT5
+LPT5
+LPT5
+lpt6
+Lpt6
+lPt6
+LPt6
+lpT6
+LpT6
+lPT6
+LPT6
+LPT6
+lpt7
+Lpt7
+lPt7
+LPt7
+lpT7
+LpT7
+lPT7
+LPT7
+LPT7
+lpt8
+Lpt8
+lPt8
+LPt8
+lpT8
+LpT8
+lPT8
+LPT8
+LPT8
+lpt9
+Lpt9
+lPt9
+LPt9
+lpT9
+LpT9
+lPT9
+LPT9
+LPT9
diff --git a/third_party/java/proguard/proguard5.3.3/examples/gradle/android.gradle b/third_party/java/proguard/proguard5.3.3/examples/gradle/android.gradle
new file mode 100644
index 0000000000..b4fe7191c0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/gradle/android.gradle
@@ -0,0 +1,195 @@
+//
+// This Gradle build file illustrates how to process Android
+// applications.
+// Usage:
+// gradle -b android.gradle proguard
+//
+// If you're using the Android SDK, the Ant release build and Eclipse export
+// already take care of the proper settings. You only need to enable ProGuard
+// by commenting in the corresponding line in project.properties. You can still
+// add project-specific configuration in proguard-project.txt.
+//
+// This configuration file is for custom, stand-alone builds.
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // Note that ProGuard works with Java bytecode (.class),
+ // before the dex compiler converts it into Dalvik code (.dex).
+
+ injars 'bin/classes'
+ injars 'libs'
+ outjars 'bin/classes-processed.jar'
+
+ libraryjars '/usr/local/android-sdk/platforms/android-9/android.jar'
+ //libraryjars '/usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar'
+ // ...
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on.
+
+ printmapping 'bin/classes-processed.map'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'bin/classes-processed.seeds'
+
+ // Preverification is irrelevant for the dex compiler and the Dalvik VM.
+
+ dontpreverify
+
+ // Reduce the size of the output some more.
+
+ repackageclasses ''
+ allowaccessmodification
+
+ // Switch off some optimizations that trip older versions of the Dalvik VM.
+
+ optimizations '!code/simplification/arithmetic'
+
+ // Keep a fixed source file attribute and all line number tables to get line
+ // numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'SourceFile,LineNumberTable'
+
+ // RemoteViews might need annotations.
+
+ keepattributes '*Annotation*'
+
+ // Preserve all fundamental application classes.
+
+ keep 'public class * extends android.app.Activity'
+ keep 'public class * extends android.app.Application'
+ keep 'public class * extends android.app.Service'
+ keep 'public class * extends android.content.BroadcastReceiver'
+ keep 'public class * extends android.content.ContentProvider'
+
+ // Preserve all View implementations, their special context constructors, and
+ // their setters.
+
+ keep 'public class * extends android.view.View { \
+ public <init>(android.content.Context); \
+ public <init>(android.content.Context, android.util.AttributeSet); \
+ public <init>(android.content.Context, android.util.AttributeSet, int); \
+ public void set*(...); \
+ }'
+
+ // Preserve all classes that have special context constructors, and the
+ // constructors themselves.
+
+ keepclasseswithmembers 'class * { \
+ public <init>(android.content.Context, android.util.AttributeSet); \
+ }'
+
+ // Preserve all classes that have special context constructors, and the
+ // constructors themselves.
+
+ keepclasseswithmembers 'class * { \
+ public <init>(android.content.Context, android.util.AttributeSet, int); \
+ }'
+
+ // Preserve all possible onClick handlers.
+
+ keepclassmembers 'class * extends android.content.Context { \
+ public void *(android.view.View); \
+ public void *(android.view.MenuItem); \
+ }'
+
+ // Preserve the special fields of all Parcelable implementations.
+
+ keepclassmembers 'class * implements android.os.Parcelable { \
+ static android.os.Parcelable$Creator CREATOR; \
+ }'
+
+ // Preserve static fields of inner classes of R classes that might be accessed
+ // through introspection.
+
+ keepclassmembers 'class **.R$* { \
+ public static <fields>; \
+ }'
+
+ // Preserve annotated Javascript interface methods.
+
+ keepclassmembers 'class * { \
+ @android.webkit.JavascriptInterface <methods>; \
+ }'
+
+ // Preserve the required interface from the License Verification Library
+ // (but don't nag the developer if the library is not used at all).
+
+ keep 'public interface com.android.vending.licensing.ILicensingService'
+
+ dontnote 'com.android.vending.licensing.ILicensingService'
+
+ // The Android Compatibility library references some classes that may not be
+ // present in all versions of the API, but we know that's ok.
+
+ dontwarn 'android.support.**'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames includedescriptorclasses:true, 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers allowshrinking:true, 'enum * { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your application doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your application may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ //keep 'public class mypackage.MyClass'
+ //keep 'public interface mypackage.MyInterface'
+ //keep 'public class * implements mypackage.MyInterface'
+
+ // If you wish, you can let the optimization step remove Android logging
+ // calls.
+ //assumenosideeffects class android.util.Log {
+ // public static boolean isLoggable(java.lang.String, int);
+ // public static int v(...);
+ // public static int i(...);
+ // public static int w(...);
+ // public static int d(...);
+ // public static int e(...);
+ //}
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/gradle/applets.gradle b/third_party/java/proguard/proguard5.3.3/examples/gradle/applets.gradle
new file mode 100644
index 0000000000..aefe651408
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/gradle/applets.gradle
@@ -0,0 +1,90 @@
+//
+// This Gradle build file illustrates how to process applets.
+// Usage:
+// gradle -b applets.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+
+ injars 'in.jar'
+ outjars 'out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on. Keep a fixed source file attribute and all line number
+ // tables to get line numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ printmapping 'out.map'
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'SourceFile,LineNumberTable'
+
+ // Preserve all annotations.
+
+ keepattributes '*Annotation*'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'out.seeds'
+
+ // Preserve all public applets.
+
+ keep 'public class * extends java.applet.Applet'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames includedescriptorclasses:true, 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers allowshrinking:true, 'enum * { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your library doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your application may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/gradle/applications.gradle b/third_party/java/proguard/proguard5.3.3/examples/gradle/applications.gradle
new file mode 100644
index 0000000000..ffadf91654
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/gradle/applications.gradle
@@ -0,0 +1,96 @@
+//
+// This Gradle build file illustrates how to process applications.
+// Usage:
+// gradle -b applications.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+
+ injars 'in.jar'
+ outjars 'out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+ //libraryjars 'junit.jar'
+ //libraryjars 'servlet.jar'
+ //libraryjars 'jai_core.jar'
+ //...
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on. Keep a fixed source file attribute and all line number
+ // tables to get line numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ printmapping 'out.map'
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'SourceFile,LineNumberTable'
+
+ // Preserve all annotations.
+
+ keepattributes '*Annotation*'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'out.seeds'
+
+ // Preserve all public applications.
+
+ keepclasseswithmembers 'public class * { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames includedescriptorclasses:true, 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers allowshrinking:true, 'enum * { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your application doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your application may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/gradle/library.gradle b/third_party/java/proguard/proguard5.3.3/examples/gradle/library.gradle
new file mode 100644
index 0000000000..8bd137cd2c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/gradle/library.gradle
@@ -0,0 +1,99 @@
+//
+// This Gradle build file illustrates how to process a program
+// library, such that it remains usable as a library.
+// Usage:
+// gradle -b library.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // In this case, the input jar is the program library that we want to process.
+
+ injars 'in.jar'
+ outjars 'out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+ // Save the obfuscation mapping to a file, so we can de-obfuscate any stack
+ // traces later on. Keep a fixed source file attribute and all line number
+ // tables to get line numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ printmapping 'out.map'
+ keepparameternames
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,EnclosingMethod'
+
+ // Preserve all annotations.
+
+ keepattributes '*Annotation*'
+
+ // Preserve all public classes, and their public and protected fields and
+ // methods.
+
+ keep 'public class * { \
+ public protected *; \
+ }'
+
+ // Preserve all .class method names.
+
+ keepclassmembernames 'class * { \
+ java.lang.Class class$(java.lang.String); \
+ java.lang.Class class$(java.lang.String, boolean); \
+ }'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames includedescriptorclasses:true, 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers allowshrinking:true, 'enum * { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your library doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your library may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/gradle/midlets.gradle b/third_party/java/proguard/proguard5.3.3/examples/gradle/midlets.gradle
new file mode 100644
index 0000000000..1e9fb116af
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/gradle/midlets.gradle
@@ -0,0 +1,88 @@
+//
+// This Gradle build file illustrates how to process J2ME midlets.
+// Usage:
+// gradle -b midlets.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+
+ injars 'in.jar'
+ outjars 'out.jar'
+
+ libraryjars '/usr/local/java/wtk2.5.2/lib/midpapi20.jar'
+ libraryjars '/usr/local/java/wtk2.5.2/lib/cldcapi11.jar'
+
+ // Preverify the code suitably for Java Micro Edition.
+
+ microedition
+
+ // Allow methods with the same signature, except for the return type,
+ // to get the same obfuscation name.
+
+ overloadaggressively
+
+ // Put all obfuscated classes into the nameless root package.
+
+ repackageclasses ''
+
+ // Allow classes and class members to be made public.
+
+ allowaccessmodification
+
+ // On Windows, you can't use mixed case class names,
+ // should you still want to use the preverify tool.
+ //
+ // dontusemixedcaseclassnames
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on.
+
+ printmapping 'out.map'
+
+ // You can keep a fixed source file attribute and all line number tables to
+ // get stack traces with line numbers.
+
+ //renamesourcefileattribute 'SourceFile'
+ //keepattributes 'SourceFile,LineNumberTable'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'out.seeds'
+
+ // Preserve all public midlets.
+
+ keep 'public class * extends javax.microedition.midlet.MIDlet'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames includedescriptorclasses:true, 'class * { \
+ native <methods>; \
+ }'
+
+ // Your midlet may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/gradle/proguard.gradle b/third_party/java/proguard/proguard5.3.3/examples/gradle/proguard.gradle
new file mode 100644
index 0000000000..0abb72e89d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/gradle/proguard.gradle
@@ -0,0 +1,92 @@
+//
+// This Gradle build file illustrates how to process ProGuard itself.
+// Configuration files for typical applications will be very similar.
+// Usage:
+// gradle -b proguard.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // We'll filter out the Ant classes, Gradle classes, and WTK classes, keeping
+ // everything else.
+
+ injars '../../lib/proguard.jar', filter: '!proguard/ant/**,!proguard/gradle/**,!proguard/wtk/**'
+ outjars 'proguard_out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+ // Write out an obfuscation mapping file, for de-obfuscating any stack traces
+ // later on, or for incremental obfuscation of extensions.
+
+ printmapping 'proguard.map'
+
+ // Allow methods with the same signature, except for the return type,
+ // to get the same obfuscation name.
+
+ overloadaggressively
+
+ // Put all obfuscated classes into the nameless root package.
+
+ repackageclasses ''
+
+ // Allow classes and class members to be made public.
+
+ allowaccessmodification
+
+ // The entry point: ProGuard and its main method.
+
+ keep 'public class proguard.ProGuard { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ // If you want to preserve the Ant task as well, you'll have to specify the
+ // main ant.jar.
+
+ //libraryjars '/usr/local/java/ant/lib/ant.jar'
+ //adaptresourcefilecontents 'proguard/ant/task.properties'
+ //
+ //keep allowobfuscation: true, 'class proguard.ant.*'
+ //keepclassmembers 'public class proguard.ant.* { \
+ // <init>(org.apache.tools.ant.Project); \
+ // public void set*(***); \
+ // public void add*(***); \
+ //}'
+
+ // If you want to preserve the Gradle task, you'll have to specify the Gradle
+ // jars.
+
+ //libraryjars '/usr/local/java/gradle-2.1/lib/plugins/gradle-plugins-2.1.jar'
+ //libraryjars '/usr/local/java/gradle-2.1/lib/gradle-base-services-2.1.jar'
+ //libraryjars '/usr/local/java/gradle-2.1/lib/gradle-base-services-groovy-2.1.jar'
+ //libraryjars '/usr/local/java/gradle-2.1/lib/gradle-core-2.1.jar'
+ //libraryjars '/usr/local/java/gradle-2.1/lib/groovy-all-2.3.6.jar'
+
+ //keep 'public class proguard.gradle.* { \
+ // public *; \
+ //}'
+
+ // If you want to preserve the WTK obfuscation plug-in, you'll have to specify
+ // the kenv.zip file.
+
+ //libraryjars '/usr/local/java/wtk2.5.2/wtklib/kenv.zip'
+ //keep 'public class proguard.wtk.ProGuardObfuscator'
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/gradle/proguardall.gradle b/third_party/java/proguard/proguard5.3.3/examples/gradle/proguardall.gradle
new file mode 100644
index 0000000000..43c905cdaf
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/gradle/proguardall.gradle
@@ -0,0 +1,94 @@
+//
+// This Gradle build file illustrates how to process ProGuard
+// (including its main application, its GUI, its Ant task, and its WTK plugin),
+// and the ReTrace tool, all in one go.
+// Configuration files for typical applications will be very similar.
+// Usage:
+// gradle -b proguardall.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // We'll read all jars from the lib directory, process them, and write the
+ // processed jars to a new out directory.
+
+ injars '../../lib'
+ outjars 'out'
+
+ // You may have to adapt the paths below.
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+ libraryjars '/usr/local/java/ant/lib/ant.jar'
+ libraryjars '/usr/local/java/gradle-2.1/lib/plugins/gradle-plugins-2.1.jar'
+ libraryjars '/usr/local/java/gradle-2.1/lib/gradle-base-services-2.1.jar'
+ libraryjars '/usr/local/java/gradle-2.1/lib/gradle-base-services-groovy-2.1.jar'
+ libraryjars '/usr/local/java/gradle-2.1/lib/gradle-core-2.1.jar'
+ libraryjars '/usr/local/java/gradle-2.1/lib/groovy-all-2.3.6.jar'
+ libraryjars '/usr/local/java/wtk2.5.2/wtklib/kenv.zip'
+
+ // Allow methods with the same signature, except for the return type,
+ // to get the same obfuscation name.
+
+ overloadaggressively
+
+ // Put all obfuscated classes into the nameless root package.
+
+ repackageclasses ''
+
+ // Adapt the names and contents of the resource files.
+
+ adaptresourcefilenames '**.properties,**.gif,**.jpg'
+ adaptresourcefilecontents 'proguard/ant/task.properties'
+
+ // The main entry points.
+
+ keep 'public class proguard.ProGuard { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ keep 'public class proguard.gui.ProGuardGUI { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ keep 'public class proguard.retrace.ReTrace { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ // If we have ant.jar, we can properly process the Ant task.
+
+ keep allowobfuscation: true, 'class proguard.ant.*'
+ keepclassmembers 'public class proguard.ant.* { \
+ <init>(org.apache.tools.ant.Project); \
+ public void set*(***); \
+ public void add*(***); \
+ }'
+
+ // If we have the Gradle jars, we can properly process the Gradle task.
+
+ keep 'public class proguard.gradle.* { \
+ public *; \
+ }'
+
+ // If we have kenv.zip, we can process the J2ME WTK plugin.
+
+ keep 'public class proguard.wtk.ProGuardObfuscator'
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/gradle/proguardgui.gradle b/third_party/java/proguard/proguard5.3.3/examples/gradle/proguardgui.gradle
new file mode 100644
index 0000000000..7bfebd9db6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/gradle/proguardgui.gradle
@@ -0,0 +1,72 @@
+//
+// This Gradle build file illustrates how to process the ProGuard GUI.
+// Configuration files for typical applications will be very similar.
+// Usage:
+// gradle -b proguardgui.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // The input jars will be merged in a single output jar.
+ // We'll filter out the Ant classes, Gradle classes, and WTK classes, keeping
+ // everything else.
+
+ injars '../../lib/proguardgui.jar'
+ injars '../../lib/proguard.jar', filter: '!META-INF/**,!proguard/ant/**,!proguard/gradle/**,!proguard/wtk/**'
+ injars '../../lib/retrace.jar', filter: '!META-INF/**'
+ outjars 'proguardgui_out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+ // If we wanted to reuse the previously obfuscated proguard_out.jar, we could
+ // perform incremental obfuscation based on its mapping file, and only keep the
+ // additional GUI files instead of all files.
+
+ //applymapping 'proguard.map'
+ //injars '../../lib/proguardgui.jar'
+ //outjars 'proguardgui_out.jar'
+ //libraryjars '../../lib/proguard.jar', filter: '!proguard/ant/**,!proguard/wtk/**'
+ //libraryjars '../../lib/retrace.jar'
+ //libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+
+ // Allow methods with the same signature, except for the return type,
+ // to get the same obfuscation name.
+
+ overloadaggressively
+
+ // Put all obfuscated classes into the nameless root package.
+
+ repackageclasses ''
+
+ // Adapt the names of resource files, based on the corresponding obfuscated
+ // class names. Notably, in this case, the GUI resource properties file will
+ // have to be renamed.
+
+ adaptresourcefilenames '**.properties,**.gif,**.jpg'
+
+ // The entry point: ProGuardGUI and its main method.
+
+ keep 'public class proguard.gui.ProGuardGUI { \
+ public static void main(java.lang.String[]); \
+ }'
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/gradle/retrace.gradle b/third_party/java/proguard/proguard5.3.3/examples/gradle/retrace.gradle
new file mode 100644
index 0000000000..7fe2c7e259
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/gradle/retrace.gradle
@@ -0,0 +1,64 @@
+//
+// This Gradle build file illustrates how to process the ReTrace tool.
+// Configuration files for typical applications will be very similar.
+// Usage:
+// gradle -b retrace.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+ // The input jars will be merged in a single output jar.
+ // We'll filter out the Ant and WTK classes.
+
+ injars '../../lib/retrace.jar'
+ injars '../../lib/proguard.jar(!META-INF/MANIFEST.MF,'
+ !proguard/ant/**,!proguard/wtk/**)
+ outjars 'retrace_out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+
+ // If we wanted to reuse the previously obfuscated proguard_out.jar, we could
+ // perform incremental obfuscation based on its mapping file, and only keep the
+ // additional ReTrace files instead of all files.
+
+ //applymapping 'proguard.map'
+ //outjars 'retrace_out.jar', filter: 'proguard/retrace/**'
+
+ // Allow methods with the same signature, except for the return type,
+ // to get the same obfuscation name.
+
+ overloadaggressively
+
+ // Put all obfuscated classes into the nameless root package.
+
+ repackageclasses ''
+
+ // Allow classes and class members to be made public.
+
+ allowaccessmodification
+
+ // The entry point: ReTrace and its main method.
+
+ keep 'public class proguard.retrace.ReTrace { \
+ public static void main(java.lang.String[]); \
+ }'
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/gradle/scala.gradle b/third_party/java/proguard/proguard5.3.3/examples/gradle/scala.gradle
new file mode 100644
index 0000000000..69be1bb931
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/gradle/scala.gradle
@@ -0,0 +1,153 @@
+//
+// This Gradle build file illustrates how to process Scala
+// applications, including the Scala runtime.
+// Usage:
+// gradle -b scala.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+
+ injars 'in.jar'
+ injars '/usr/local/java/scala-2.9.1/lib/scala-library.jar'
+ //injars '/usr/local/java/scala-2.9.1/lib/scala-compiler.jar', filter: '!META-INF/MANIFEST.MF'
+ //injars '/usr/local/java/scala-2.9.1/lib/jline.jar', filter: '!META-INF/MANIFEST.MF'
+ outjars 'out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+ //libraryjars '/usr/local/java/ant/lib/ant.jar'
+ //...
+
+ // Ignore some compiler artefacts.
+
+ dontwarn 'scala.**'
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on. Keep a fixed source file attribute and all line number
+ // tables to get line numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ printmapping 'out.map'
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'SourceFile,LineNumberTable'
+
+ // Preserve all annotations.
+
+ keepattributes '*Annotation*'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'out.seeds'
+
+ // Preserve all public applications.
+
+ keepclasseswithmembers 'public class * { \
+ public static void main(java.lang.String[]); \
+ }'
+
+ // Preserve some classes and class members that are accessed by means of
+ // introspection.
+
+ keep 'class * implements org.xml.sax.EntityResolver'
+
+ keepclassmembers 'class * { \
+ ** MODULE$; \
+ }'
+
+ keepclassmembernames 'class scala.concurrent.forkjoin.ForkJoinPool { \
+ long eventCount; \
+ int workerCounts; \
+ int runControl; \
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode syncStack; \
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode spareStack; \
+ }'
+
+ keepclassmembernames 'class scala.concurrent.forkjoin.ForkJoinWorkerThread { \
+ int base; \
+ int sp; \
+ int runState; \
+ }'
+
+ keepclassmembernames 'class scala.concurrent.forkjoin.ForkJoinTask { \
+ int status; \
+ }'
+
+ keepclassmembernames 'class scala.concurrent.forkjoin.LinkedTransferQueue { \
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference head; \
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference tail; \
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference cleanMe; \
+ }'
+
+ // Preserve some classes and class members that are accessed by means of
+ // introspection in the Scala compiler library, if it is processed as well.
+
+ //keep 'class * implements jline.Completor'
+ //keep 'class * implements jline.Terminal'
+
+ //keep 'class scala.tools.nsc.Global'
+
+ //keepclasseswithmembers 'class * { \
+ // <init>(scala.tools.nsc.Global); \
+ //}'
+
+ //keepclassmembers 'class * { \
+ // *** scala_repl_value(); \
+ // *** scala_repl_result(); \
+ //}'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames includedescriptorclasses:true, 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers allowshrinking:true, 'enum * { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your application doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your application may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/gradle/servlets.gradle b/third_party/java/proguard/proguard5.3.3/examples/gradle/servlets.gradle
new file mode 100644
index 0000000000..23062ff041
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/gradle/servlets.gradle
@@ -0,0 +1,91 @@
+//
+// This Gradle build file illustrates how to process servlets.
+// Usage:
+// gradle -b servlets.gradle proguard
+//
+
+// Tell Gradle where to find the ProGuard task.
+
+buildscript {
+ repositories {
+ flatDir dirs: '../../lib'
+ }
+ dependencies {
+ classpath ':proguard'
+ }
+}
+
+// Define a ProGuard task.
+
+task proguard(type: proguard.gradle.ProGuardTask) {
+
+ // You should probably import a more compact ProGuard-style configuration
+ // file for all static settings, but we're specifying them all here, for
+ // the sake of the example.
+ //configuration 'configuration.pro'
+
+ // Specify the input jars, output jars, and library jars.
+
+ injars 'in.jar'
+ outjars 'out.jar'
+
+ libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
+ libraryjars '/usr/local/java/servlet/servlet.jar'
+
+ // Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+ // traces later on. Keep a fixed source file attribute and all line number
+ // tables to get line numbers in the stack traces.
+ // You can comment this out if you're not interested in stack traces.
+
+ printmapping 'out.map'
+ renamesourcefileattribute 'SourceFile'
+ keepattributes 'SourceFile,LineNumberTable'
+
+ // Preserve all annotations.
+
+ keepattributes '*Annotation*'
+
+ // You can print out the seeds that are matching the keep options below.
+
+ //printseeds 'out.seeds'
+
+ // Preserve all public servlets.
+
+ keep 'public class * implements javax.servlet.Servlet'
+
+ // Preserve all native method names and the names of their classes.
+
+ keepclasseswithmembernames includedescriptorclasses:true, 'class * { \
+ native <methods>; \
+ }'
+
+ // Preserve the special static methods that are required in all enumeration
+ // classes.
+
+ keepclassmembers allowshrinking:true, 'enum * { \
+ public static **[] values(); \
+ public static ** valueOf(java.lang.String); \
+ }'
+
+ // Explicitly preserve all serialization members. The Serializable interface
+ // is only a marker interface, so it wouldn't save them.
+ // You can comment this out if your library doesn't use serialization.
+ // If your code contains serializable classes that have to be backward
+ // compatible, please refer to the manual.
+
+ keepclassmembers 'class * implements java.io.Serializable { \
+ static final long serialVersionUID; \
+ static final java.io.ObjectStreamField[] serialPersistentFields; \
+ private void writeObject(java.io.ObjectOutputStream); \
+ private void readObject(java.io.ObjectInputStream); \
+ java.lang.Object writeReplace(); \
+ java.lang.Object readResolve(); \
+ }'
+
+ // Your application may contain more items that need to be preserved;
+ // typically classes that are dynamically created using Class.forName:
+
+ // keep 'public class mypackage.MyClass'
+ // keep 'public interface mypackage.MyInterface'
+ // keep 'public class * implements mypackage.MyInterface'
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/library.pro b/third_party/java/proguard/proguard5.3.3/examples/library.pro
new file mode 100644
index 0000000000..4669e79c21
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/library.pro
@@ -0,0 +1,79 @@
+#
+# This ProGuard configuration file illustrates how to process a program
+# library, such that it remains usable as a library.
+# Usage:
+# java -jar proguard.jar @library.pro
+#
+
+# Specify the input jars, output jars, and library jars.
+# In this case, the input jar is the program library that we want to process.
+
+-injars in.jar
+-outjars out.jar
+
+-libraryjars <java.home>/lib/rt.jar
+
+# Save the obfuscation mapping to a file, so we can de-obfuscate any stack
+# traces later on. Keep a fixed source file attribute and all line number
+# tables to get line numbers in the stack traces.
+# You can comment this out if you're not interested in stack traces.
+
+-printmapping out.map
+-keepparameternames
+-renamesourcefileattribute SourceFile
+-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
+ SourceFile,LineNumberTable,EnclosingMethod
+
+# Preserve all annotations.
+
+-keepattributes *Annotation*
+
+# Preserve all public classes, and their public and protected fields and
+# methods.
+
+-keep public class * {
+ public protected *;
+}
+
+# Preserve all .class method names.
+
+-keepclassmembernames class * {
+ java.lang.Class class$(java.lang.String);
+ java.lang.Class class$(java.lang.String, boolean);
+}
+
+# Preserve all native method names and the names of their classes.
+
+-keepclasseswithmembernames,includedescriptorclasses class * {
+ native <methods>;
+}
+
+# Preserve the special static methods that are required in all enumeration
+# classes.
+
+-keepclassmembers,allowoptimization enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# Explicitly preserve all serialization members. The Serializable interface
+# is only a marker interface, so it wouldn't save them.
+# You can comment this out if your library doesn't use serialization.
+# If your code contains serializable classes that have to be backward
+# compatible, please refer to the manual.
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+
+# Your library may contain more items that need to be preserved;
+# typically classes that are dynamically created using Class.forName:
+
+# -keep public class mypackage.MyClass
+# -keep public interface mypackage.MyInterface
+# -keep public class * implements mypackage.MyInterface
diff --git a/third_party/java/proguard/proguard5.3.3/examples/midlets.pro b/third_party/java/proguard/proguard5.3.3/examples/midlets.pro
new file mode 100644
index 0000000000..f2f5f21569
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/midlets.pro
@@ -0,0 +1,67 @@
+#
+# This ProGuard configuration file illustrates how to process J2ME midlets.
+# Usage:
+# java -jar proguard.jar @midlets.pro
+#
+
+# Specify the input jars, output jars, and library jars.
+
+-injars in.jar
+-outjars out.jar
+
+-libraryjars /usr/local/java/wtk2.5.2/lib/midpapi20.jar
+-libraryjars /usr/local/java/wtk2.5.2/lib/cldcapi11.jar
+
+# Preverify the code suitably for Java Micro Edition.
+
+-microedition
+
+# Allow methods with the same signature, except for the return type,
+# to get the same obfuscation name.
+
+-overloadaggressively
+
+# Put all obfuscated classes into the nameless root package.
+
+-repackageclasses ''
+
+# Allow classes and class members to be made public.
+
+-allowaccessmodification
+
+# On Windows, you can't use mixed case class names,
+# should you still want to use the preverify tool.
+#
+# -dontusemixedcaseclassnames
+
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on.
+
+-printmapping out.map
+
+# You can keep a fixed source file attribute and all line number tables to
+# get stack traces with line numbers.
+
+#-renamesourcefileattribute SourceFile
+#-keepattributes SourceFile,LineNumberTable
+
+# You can print out the seeds that are matching the keep options below.
+
+#-printseeds out.seeds
+
+# Preserve all public midlets.
+
+-keep public class * extends javax.microedition.midlet.MIDlet
+
+# Preserve all native method names and the names of their classes.
+
+-keepclasseswithmembernames,includedescriptorclasses class * {
+ native <methods>;
+}
+
+# Your midlet may contain more items that need to be preserved;
+# typically classes that are dynamically created using Class.forName:
+
+# -keep public class mypackage.MyClass
+# -keep public interface mypackage.MyInterface
+# -keep public class * implements mypackage.MyInterface
diff --git a/third_party/java/proguard/proguard5.3.3/examples/proguard.pro b/third_party/java/proguard/proguard5.3.3/examples/proguard.pro
new file mode 100644
index 0000000000..a077df41af
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/proguard.pro
@@ -0,0 +1,70 @@
+#
+# This ProGuard configuration file illustrates how to process ProGuard itself.
+# Configuration files for typical applications will be very similar.
+# Usage:
+# java -jar proguard.jar @proguard.pro
+#
+
+# Specify the input jars, output jars, and library jars.
+# We'll filter out the Ant classes, Gradle classes, and WTK classes, keeping
+# everything else.
+
+-injars ../lib/proguard.jar(!proguard/ant/**,!proguard/gradle/**,!proguard/wtk/**)
+-outjars proguard_out.jar
+
+-libraryjars <java.home>/lib/rt.jar
+
+# Write out an obfuscation mapping file, for de-obfuscating any stack traces
+# later on, or for incremental obfuscation of extensions.
+
+-printmapping proguard.map
+
+# Allow methods with the same signature, except for the return type,
+# to get the same obfuscation name.
+
+-overloadaggressively
+
+# Put all obfuscated classes into the nameless root package.
+
+-repackageclasses ''
+
+# Allow classes and class members to be made public.
+
+-allowaccessmodification
+
+# The entry point: ProGuard and its main method.
+
+-keep public class proguard.ProGuard {
+ public static void main(java.lang.String[]);
+}
+
+# If you want to preserve the Ant task as well, you'll have to specify the
+# main ant.jar.
+
+#-libraryjars /usr/local/java/ant/lib/ant.jar
+#-adaptresourcefilecontents proguard/ant/task.properties
+#
+#-keep,allowobfuscation class proguard.ant.*
+#-keepclassmembers public class proguard.ant.* {
+# <init>(org.apache.tools.ant.Project);
+# public void set*(***);
+# public void add*(***);
+#}
+
+# If you want to preserve the Gradle task, you'll have to specify the Gradle
+# jars.
+
+#-libraryjars /usr/local/java/gradle-2.12/lib/plugins/gradle-plugins-2.12.jar
+#-libraryjars /usr/local/java/gradle-2.12/lib/gradle-base-services-2.12.jar
+#-libraryjars /usr/local/java/gradle-2.12/lib/gradle-core-2.12.jar
+#-libraryjars /usr/local/java/gradle-2.12/lib/groovy-all-2.4.4.jar
+
+#-keep public class proguard.gradle.* {
+# public *;
+#}
+
+# If you want to preserve the WTK obfuscation plug-in, you'll have to specify
+# the kenv.zip file.
+
+#-libraryjars /usr/local/java/wtk2.5.2/wtklib/kenv.zip
+#-keep public class proguard.wtk.ProGuardObfuscator
diff --git a/third_party/java/proguard/proguard5.3.3/examples/proguardall.pro b/third_party/java/proguard/proguard5.3.3/examples/proguardall.pro
new file mode 100644
index 0000000000..c3106f70f6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/proguardall.pro
@@ -0,0 +1,72 @@
+#
+# This ProGuard configuration file illustrates how to process ProGuard
+# (including its main application, its GUI, its Ant task, and its WTK plugin),
+# and the ReTrace tool, all in one go.
+# Configuration files for typical applications will be very similar.
+# Usage:
+# java -jar proguard.jar @proguardall.pro
+#
+
+# Specify the input jars, output jars, and library jars.
+# We'll read all jars from the lib directory, process them, and write the
+# processed jars to a new out directory.
+
+-injars ../lib
+-outjars out
+
+# You may have to adapt the paths below.
+
+-libraryjars <java.home>/lib/rt.jar
+-libraryjars /usr/local/java/ant/lib/ant.jar
+-libraryjars /usr/local/java/gradle-2.12/lib/plugins/gradle-plugins-2.12.jar
+-libraryjars /usr/local/java/gradle-2.12/lib/gradle-base-services-2.12.jar
+-libraryjars /usr/local/java/gradle-2.12/lib/gradle-core-2.12.jar
+-libraryjars /usr/local/java/gradle-2.12/lib/groovy-all-2.4.4.jar
+-libraryjars /usr/local/java/wtk2.5.2/wtklib/kenv.zip
+
+# Allow methods with the same signature, except for the return type,
+# to get the same obfuscation name.
+
+-overloadaggressively
+
+# Put all obfuscated classes into the nameless root package.
+
+-repackageclasses ''
+
+# Adapt the names and contents of the resource files.
+
+-adaptresourcefilenames **.properties,**.gif,**.jpg
+-adaptresourcefilecontents proguard/ant/task.properties
+
+# The main entry points.
+
+-keep public class proguard.ProGuard {
+ public static void main(java.lang.String[]);
+}
+
+-keep public class proguard.gui.ProGuardGUI {
+ public static void main(java.lang.String[]);
+}
+
+-keep public class proguard.retrace.ReTrace {
+ public static void main(java.lang.String[]);
+}
+
+# If we have ant.jar, we can properly process the Ant task.
+
+-keep,allowobfuscation class proguard.ant.*
+-keepclassmembers public class proguard.ant.* {
+ <init>(org.apache.tools.ant.Project);
+ public void set*(***);
+ public void add*(***);
+}
+
+# If we have the Gradle jars, we can properly process the Gradle task.
+
+-keep public class proguard.gradle.* {
+ public *;
+}
+
+# If we have kenv.zip, we can process the J2ME WTK plugin.
+
+-keep public class proguard.wtk.ProGuardObfuscator
diff --git a/third_party/java/proguard/proguard5.3.3/examples/proguardgui.pro b/third_party/java/proguard/proguard5.3.3/examples/proguardgui.pro
new file mode 100644
index 0000000000..78f67dbf60
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/proguardgui.pro
@@ -0,0 +1,51 @@
+#
+# This ProGuard configuration file illustrates how to process the ProGuard GUI.
+# Configuration files for typical applications will be very similar.
+# Usage:
+# java -jar proguard.jar @proguardgui.pro
+#
+
+# Specify the input jars, output jars, and library jars.
+# The input jars will be merged in a single output jar.
+# We'll filter out the Ant classes, Gradle classes, and WTK classes, keeping
+# everything else.
+
+-injars ../lib/proguardgui.jar
+-injars ../lib/proguard.jar(!META-INF/**,!proguard/ant/**,!proguard/gradle/**,!proguard/wtk/**)
+-injars ../lib/retrace.jar (!META-INF/**)
+-outjars proguardgui_out.jar
+
+-libraryjars <java.home>/lib/rt.jar
+
+# If we wanted to reuse the previously obfuscated proguard_out.jar, we could
+# perform incremental obfuscation based on its mapping file, and only keep the
+# additional GUI files instead of all files.
+
+#-applymapping proguard.map
+#-injars ../lib/proguardgui.jar
+#-outjars proguardgui_out.jar
+#-libraryjars ../lib/proguard.jar(!proguard/ant/**,!proguard/wtk/**)
+#-libraryjars ../lib/retrace.jar
+#-libraryjars <java.home>/lib/rt.jar
+
+
+# Allow methods with the same signature, except for the return type,
+# to get the same obfuscation name.
+
+-overloadaggressively
+
+# Put all obfuscated classes into the nameless root package.
+
+-repackageclasses ''
+
+# Adapt the names of resource files, based on the corresponding obfuscated
+# class names. Notably, in this case, the GUI resource properties file will
+# have to be renamed.
+
+-adaptresourcefilenames **.properties,**.gif,**.jpg
+
+# The entry point: ProGuardGUI and its main method.
+
+-keep public class proguard.gui.ProGuardGUI {
+ public static void main(java.lang.String[]);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/retrace.pro b/third_party/java/proguard/proguard5.3.3/examples/retrace.pro
new file mode 100644
index 0000000000..39f5a95c59
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/retrace.pro
@@ -0,0 +1,43 @@
+#
+# This ProGuard configuration file illustrates how to process the ReTrace tool.
+# Configuration files for typical applications will be very similar.
+# Usage:
+# java -jar proguard.jar @retrace.pro
+#
+
+# Specify the input jars, output jars, and library jars.
+# The input jars will be merged in a single output jar.
+# We'll filter out the Ant and WTK classes.
+
+-injars ../lib/retrace.jar
+-injars ../lib/proguard.jar(!META-INF/MANIFEST.MF,
+ !proguard/ant/**,!proguard/wtk/**)
+-outjars retrace_out.jar
+
+-libraryjars <java.home>/lib/rt.jar
+
+# If we wanted to reuse the previously obfuscated proguard_out.jar, we could
+# perform incremental obfuscation based on its mapping file, and only keep the
+# additional ReTrace files instead of all files.
+
+#-applymapping proguard.map
+#-outjars retrace_out.jar(proguard/retrace/**)
+
+# Allow methods with the same signature, except for the return type,
+# to get the same obfuscation name.
+
+-overloadaggressively
+
+# Put all obfuscated classes into the nameless root package.
+
+-repackageclasses ''
+
+# Allow classes and class members to be made public.
+
+-allowaccessmodification
+
+# The entry point: ReTrace and its main method.
+
+-keep public class proguard.retrace.ReTrace {
+ public static void main(java.lang.String[]);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/examples/scala.pro b/third_party/java/proguard/proguard5.3.3/examples/scala.pro
new file mode 100644
index 0000000000..3b69c3c8b4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/scala.pro
@@ -0,0 +1,132 @@
+#
+# This ProGuard configuration file illustrates how to process Scala
+# applications, including the Scala runtime.
+# Usage:
+# java -jar proguard.jar @scala.pro
+#
+
+# Specify the input jars, output jars, and library jars.
+
+-injars in.jar
+-injars /usr/local/java/scala-2.9.1/lib/scala-library.jar
+#-injars /usr/local/java/scala-2.9.1/lib/scala-compiler.jar(!META-INF/MANIFEST.MF)
+#-injars /usr/local/java/scala-2.9.1/lib/jline.jar(!META-INF/MANIFEST.MF)
+-outjars out.jar
+
+-libraryjars <java.home>/lib/rt.jar
+#-libraryjars /usr/local/java/ant/lib/ant.jar
+#...
+
+# Ignore some compiler artefacts.
+
+-dontwarn scala.**
+
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on. Keep a fixed source file attribute and all line number
+# tables to get line numbers in the stack traces.
+# You can comment this out if you're not interested in stack traces.
+
+-printmapping out.map
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
+
+# Preserve all annotations.
+
+-keepattributes *Annotation*
+
+# You can print out the seeds that are matching the keep options below.
+
+#-printseeds out.seeds
+
+# Preserve all public applications.
+
+-keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+}
+
+# Preserve some classes and class members that are accessed by means of
+# introspection.
+
+-keep class * implements org.xml.sax.EntityResolver
+
+-keepclassmembers class * {
+ ** MODULE$;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinPool {
+ long eventCount;
+ int workerCounts;
+ int runControl;
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode syncStack;
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode spareStack;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinWorkerThread {
+ int base;
+ int sp;
+ int runState;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinTask {
+ int status;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.LinkedTransferQueue {
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference head;
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference tail;
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference cleanMe;
+}
+
+# Preserve some classes and class members that are accessed by means of
+# introspection in the Scala compiler library, if it is processed as well.
+
+#-keep class * implements jline.Completor
+#-keep class * implements jline.Terminal
+
+#-keep class scala.tools.nsc.Global
+
+#-keepclasseswithmembers class * {
+# <init>(scala.tools.nsc.Global);
+#}
+
+#-keepclassmembers class * {
+# *** scala_repl_value();
+# *** scala_repl_result();
+#}
+
+# Preserve all native method names and the names of their classes.
+
+-keepclasseswithmembernames,includedescriptorclasses class * {
+ native <methods>;
+}
+
+# Preserve the special static methods that are required in all enumeration
+# classes.
+
+-keepclassmembers,allowoptimization enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# Explicitly preserve all serialization members. The Serializable interface
+# is only a marker interface, so it wouldn't save them.
+# You can comment this out if your application doesn't use serialization.
+# If your code contains serializable classes that have to be backward
+# compatible, please refer to the manual.
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+
+# Your application may contain more items that need to be preserved;
+# typically classes that are dynamically created using Class.forName:
+
+# -keep public class mypackage.MyClass
+# -keep public interface mypackage.MyInterface
+# -keep public class * implements mypackage.MyInterface
+
diff --git a/third_party/java/proguard/proguard5.3.3/examples/servlets.pro b/third_party/java/proguard/proguard5.3.3/examples/servlets.pro
new file mode 100644
index 0000000000..a3f7875b5e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/examples/servlets.pro
@@ -0,0 +1,70 @@
+#
+# This ProGuard configuration file illustrates how to process servlets.
+# Usage:
+# java -jar proguard.jar @servlets.pro
+#
+
+# Specify the input jars, output jars, and library jars.
+
+-injars in.jar
+-outjars out.jar
+
+-libraryjars <java.home>/lib/rt.jar
+-libraryjars /usr/local/java/servlet/servlet.jar
+
+# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
+# traces later on. Keep a fixed source file attribute and all line number
+# tables to get line numbers in the stack traces.
+# You can comment this out if you're not interested in stack traces.
+
+-printmapping out.map
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
+
+# Preserve all annotations.
+
+-keepattributes *Annotation*
+
+# You can print out the seeds that are matching the keep options below.
+
+#-printseeds out.seeds
+
+# Preserve all public servlets.
+
+-keep public class * implements javax.servlet.Servlet
+
+# Preserve all native method names and the names of their classes.
+
+-keepclasseswithmembernames,includedescriptorclasses class * {
+ native <methods>;
+}
+
+# Preserve the special static methods that are required in all enumeration
+# classes.
+
+-keepclassmembers,allowoptimization enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# Explicitly preserve all serialization members. The Serializable interface
+# is only a marker interface, so it wouldn't save them.
+# You can comment this out if your library doesn't use serialization.
+# If your code contains serializable classes that have to be backward
+# compatible, please refer to the manual.
+
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+
+# Your application may contain more items that need to be preserved;
+# typically classes that are dynamically created using Class.forName:
+
+# -keep public class mypackage.MyClass
+# -keep public interface mypackage.MyInterface
+# -keep public class * implements mypackage.MyInterface
diff --git a/third_party/java/proguard/proguard5.3.3/lib/proguard.jar b/third_party/java/proguard/proguard5.3.3/lib/proguard.jar
new file mode 100644
index 0000000000..08f4a4cdd3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/lib/proguard.jar
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/lib/proguardgui.jar b/third_party/java/proguard/proguard5.3.3/lib/proguardgui.jar
new file mode 100644
index 0000000000..163a689e1f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/lib/proguardgui.jar
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/lib/retrace.jar b/third_party/java/proguard/proguard5.3.3/lib/retrace.jar
new file mode 100644
index 0000000000..af114dc94e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/lib/retrace.jar
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ArgumentWordReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ArgumentWordReader.java
new file mode 100644
index 0000000000..172213a3a1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ArgumentWordReader.java
@@ -0,0 +1,111 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.io.*;
+
+
+/**
+ * A <code>WordReader</code> that returns words from an argument list.
+ * Single arguments are split into individual words if necessary.
+ *
+ * @author Eric Lafortune
+ */
+public class ArgumentWordReader extends WordReader
+{
+ private final String[] arguments;
+
+ private int index = 0;
+
+
+// /**
+// * Creates a new ArgumentWordReader for the given arguments.
+// */
+// public ArgumentWordReader(String[] arguments)
+// {
+// this(arguments, null);
+// }
+//
+//
+ /**
+ * Creates a new ArgumentWordReader for the given arguments, with the
+ * given base directory.
+ */
+ public ArgumentWordReader(String[] arguments, File baseDir)
+ {
+ super(baseDir);
+
+ this.arguments = arguments;
+ }
+
+
+ // Implementations for WordReader.
+
+ protected String nextLine() throws IOException
+ {
+ return index < arguments.length ?
+ arguments[index++] :
+ null;
+ }
+
+
+ protected String lineLocationDescription()
+ {
+ return "argument number " + index;
+ }
+
+
+ /**
+ * Test application that prints out the individual words of
+ * the argument list.
+ */
+ public static void main(String[] args) {
+
+ try
+ {
+ WordReader reader = new ArgumentWordReader(args, null);
+
+ try
+ {
+ while (true)
+ {
+ String word = reader.nextWord(false);
+ if (word == null)
+ System.exit(-1);
+
+ System.err.println("["+word+"]");
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ finally
+ {
+ reader.close();
+ }
+ }
+ catch (IOException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/AssumeNoSideEffectsChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/AssumeNoSideEffectsChecker.java
new file mode 100644
index 0000000000..890bc66777
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/AssumeNoSideEffectsChecker.java
@@ -0,0 +1,98 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.util.*;
+
+import java.util.List;
+
+/**
+ * This class checks if the user is specifying to assume no side effects
+ * for a reasonable number of methods in a class: not none and not all.
+ *
+ * @author Eric Lafortune
+ */
+public class AssumeNoSideEffectsChecker
+{
+ private final WarningPrinter notePrinter;
+
+
+ /**
+ * Creates a new KeepClassMemberChecker.
+ */
+ public AssumeNoSideEffectsChecker(WarningPrinter notePrinter)
+ {
+ this.notePrinter = notePrinter;
+ }
+
+
+ /**
+ * Checks if the given class specifications try to assume no side effects
+ * for all methods in a class, printing notes if necessary.
+ */
+ public void checkClassSpecifications(List classSpecifications)
+ {
+ if (classSpecifications != null)
+ {
+ for (int classSpecificationIndex = 0;
+ classSpecificationIndex < classSpecifications.size();
+ classSpecificationIndex++)
+ {
+ ClassSpecification classSpecification =
+ (ClassSpecification)classSpecifications.get(classSpecificationIndex);
+
+ String className = classSpecification.className;
+ if (className == null)
+ {
+ className = classSpecification.extendsClassName;
+ }
+
+ if (className == null ||
+ notePrinter.accepts(className))
+ {
+ List methodSpecifications =
+ classSpecification.methodSpecifications;
+
+ if (methodSpecifications != null)
+ {
+ for (int methodSpecificationIndex = 0;
+ methodSpecificationIndex < methodSpecifications.size();
+ methodSpecificationIndex++)
+ {
+ final MemberSpecification methodSpecification =
+ (MemberSpecification)methodSpecifications.get(methodSpecificationIndex);
+
+ if (methodSpecification.name == null &&
+ methodSpecification.descriptor == null)
+ {
+ notePrinter.print(className,
+ "Note: the configuration specifies that none of the methods of class '" +
+ (className == null ?
+ ConfigurationConstants.ANY_CLASS_KEYWORD :
+ ClassUtil.externalClassName(className)) + "' have any side effects");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ClassMemberChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassMemberChecker.java
new file mode 100644
index 0000000000..2cf95034be
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassMemberChecker.java
@@ -0,0 +1,158 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+import java.util.List;
+
+/**
+ * This class checks if the user has specified non-existent class members.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassMemberChecker
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final ClassPool programClassPool;
+ private final WarningPrinter notePrinter;
+
+
+ /**
+ * Creates a new ClassMemberChecker.
+ */
+ public ClassMemberChecker(ClassPool programClassPool,
+ WarningPrinter notePrinter)
+ {
+ this.programClassPool = programClassPool;
+ this.notePrinter = notePrinter;
+ }
+
+
+ /**
+ * Checks the classes mentioned in the given class specifications, printing
+ * notes if necessary.
+ */
+ public void checkClassSpecifications(List classSpecifications)
+ {
+ if (classSpecifications != null)
+ {
+ for (int index = 0; index < classSpecifications.size(); index++)
+ {
+ ClassSpecification classSpecification =
+ (ClassSpecification)classSpecifications.get(index);
+
+ String className = classSpecification.className;
+ if (className != null &&
+ !containsWildCards(className) &&
+ notePrinter.accepts(className))
+ {
+ Clazz clazz = programClassPool.getClass(className);
+ if (clazz != null)
+ {
+ checkMemberSpecifications(clazz, classSpecification.fieldSpecifications, true);
+ checkMemberSpecifications(clazz, classSpecification.methodSpecifications, false);
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Checks the class members mentioned in the given class member
+ * specifications, printing notes if necessary.
+ */
+ private void checkMemberSpecifications(Clazz clazz,
+ List memberSpecifications,
+ boolean isField)
+ {
+ if (memberSpecifications != null)
+ {
+ String className = clazz.getName();
+
+ for (int index = 0; index < memberSpecifications.size(); index++)
+ {
+ MemberSpecification memberSpecification =
+ (MemberSpecification)memberSpecifications.get(index);
+
+ String memberName = memberSpecification.name;
+ String descriptor = memberSpecification.descriptor;
+ if (memberName != null &&
+ !containsWildCards(memberName) &&
+ descriptor != null &&
+ !containsWildCards(descriptor))
+ {
+ if (isField)
+ {
+ if (clazz.findField(memberName, descriptor) == null)
+ {
+ notePrinter.print(className,
+ "Note: the configuration refers to the unknown field '" +
+ ClassUtil.externalFullFieldDescription(0, memberName, descriptor) + "' in class '" +
+ ClassUtil.externalClassName(className) + "'");
+ }
+ }
+ else
+ {
+ if (clazz.findMethod(memberName, descriptor) == null)
+ {
+ notePrinter.print(className,
+ "Note: the configuration refers to the unknown method '" +
+ ClassUtil.externalFullMethodDescription(className, 0, memberName, descriptor) + "' in class '" +
+ ClassUtil.externalClassName(className) + "'");
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ private static boolean containsWildCards(String string)
+ {
+ return string != null &&
+ (string.indexOf('!') >= 0 ||
+ string.indexOf('*') >= 0 ||
+ string.indexOf('?') >= 0 ||
+ string.indexOf(',') >= 0 ||
+ string.indexOf("///") >= 0);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ System.out.println(" Maybe you meant the field '" +
+ ClassUtil.externalFullFieldDescription(0, programField.getName(programClass), programField.getDescriptor(programClass)) + "'?");
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ System.out.println(" Maybe you meant the method '" +
+ ClassUtil.externalFullMethodDescription(programClass.getName(), 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) + "'?");
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ClassPath.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassPath.java
new file mode 100644
index 0000000000..7001a0d914
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassPath.java
@@ -0,0 +1,94 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.util.*;
+
+
+/**
+ * This class represents a class path, as a list of ClassPathEntry objects.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassPath
+{
+ private final List classPathEntries = new ArrayList();
+
+
+ /**
+ * Returns whether the class path contains any output entries.
+ */
+ public boolean hasOutput()
+ {
+ for (int index = 0; index < classPathEntries.size(); index++)
+ {
+ if (((ClassPathEntry)classPathEntries.get(index)).isOutput())
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ // Delegates to List.
+
+ public void clear()
+ {
+ classPathEntries.clear();
+ }
+
+ public void add(int index, ClassPathEntry classPathEntry)
+ {
+ classPathEntries.add(index, classPathEntry);
+ }
+
+ public boolean add(ClassPathEntry classPathEntry)
+ {
+ return classPathEntries.add(classPathEntry);
+ }
+
+ public boolean addAll(ClassPath classPath)
+ {
+ return classPathEntries.addAll(classPath.classPathEntries);
+ }
+
+ public ClassPathEntry get(int index)
+ {
+ return (ClassPathEntry)classPathEntries.get(index);
+ }
+
+ public ClassPathEntry remove(int index)
+ {
+ return (ClassPathEntry)classPathEntries.remove(index);
+ }
+
+ public boolean isEmpty()
+ {
+ return classPathEntries.isEmpty();
+ }
+
+ public int size()
+ {
+ return classPathEntries.size();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ClassPathEntry.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassPathEntry.java
new file mode 100644
index 0000000000..c1e0fd470e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassPathEntry.java
@@ -0,0 +1,384 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.util.ListUtil;
+
+import java.io.*;
+import java.util.List;
+
+
+/**
+ * This class represents an entry from a class path: an apk, a jar, an aar, a
+ * war, a zip, an ear, or a directory, with a name and a flag to indicates
+ * whether the entry is an input entry or an output entry. Optional filters can
+ * be specified for the names of the contained resource/classes, apks, jars,
+ * aars, wars, ears, and zips.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassPathEntry
+{
+ private File file;
+ private boolean output;
+ private List filter;
+ private List apkFilter;
+ private List jarFilter;
+ private List aarFilter;
+ private List warFilter;
+ private List earFilter;
+ private List zipFilter;
+
+ private String cachedName;
+
+
+ /**
+ * Creates a new ClassPathEntry with the given file and output flag.
+ */
+ public ClassPathEntry(File file, boolean isOutput)
+ {
+ this.file = file;
+ this.output = isOutput;
+ }
+
+
+ /**
+ * Returns the path name of the entry.
+ */
+ public String getName()
+ {
+ if (cachedName == null)
+ {
+ cachedName = getUncachedName();
+ }
+
+ return cachedName;
+ }
+
+
+ /**
+ * Returns the uncached path name of the entry.
+ */
+ private String getUncachedName()
+ {
+ try
+ {
+ return file.getCanonicalPath();
+ }
+ catch (IOException ex)
+ {
+ return file.getPath();
+ }
+ }
+
+
+ /**
+ * Returns the file.
+ */
+ public File getFile()
+ {
+ return file;
+ }
+
+
+ /**
+ * Sets the file.
+ */
+ public void setFile(File file)
+ {
+ this.file = file;
+ this.cachedName = null;
+ }
+
+
+ /**
+ * Returns whether this data entry is an output entry.
+ */
+ public boolean isOutput()
+ {
+ return output;
+ }
+
+
+ /**
+ * Specifies whether this data entry is an output entry.
+ */
+ public void setOutput(boolean output)
+ {
+ this.output = output;
+ }
+
+
+ /**
+ * Returns whether this data entry is a dex file.
+ */
+ public boolean isDex()
+ {
+ return hasExtension(".dex");
+ }
+
+
+ /**
+ * Returns whether this data entry is an apk file.
+ */
+ public boolean isApk()
+ {
+ return hasExtension(".apk") ||
+ hasExtension(".ap_");
+ }
+
+
+ /**
+ * Returns whether this data entry is a jar file.
+ */
+ public boolean isJar()
+ {
+ return hasExtension(".jar");
+ }
+
+
+ /**
+ * Returns whether this data entry is an aar file.
+ */
+ public boolean isAar()
+ {
+ return hasExtension(".aar");
+ }
+
+
+ /**
+ * Returns whether this data entry is a war file.
+ */
+ public boolean isWar()
+ {
+ return hasExtension(".war");
+ }
+
+
+ /**
+ * Returns whether this data entry is a ear file.
+ */
+ public boolean isEar()
+ {
+ return hasExtension(".ear");
+ }
+
+
+ /**
+ * Returns whether this data entry is a zip file.
+ */
+ public boolean isZip()
+ {
+ return hasExtension(".zip");
+ }
+
+
+ /**
+ * Returns whether this data entry has the given extension.
+ */
+ private boolean hasExtension(String extension)
+ {
+ return endsWithIgnoreCase(file.getPath(), extension);
+ }
+
+
+ /**
+ * Returns whether the given string ends with the given suffix, ignoring
+ * its case.
+ */
+ private static boolean endsWithIgnoreCase(String string, String suffix)
+ {
+ int stringLength = string.length();
+ int suffixLength = suffix.length();
+
+ return string.regionMatches(true, stringLength -
+ suffixLength, suffix, 0, suffixLength);
+ }
+
+
+ /**
+ * Returns whether this data entry has any kind of filter.
+ */
+ public boolean isFiltered()
+ {
+ return filter != null ||
+ apkFilter != null ||
+ jarFilter != null ||
+ aarFilter != null ||
+ warFilter != null ||
+ earFilter != null ||
+ zipFilter != null;
+ }
+
+
+ /**
+ * Returns the name filter that is applied to bottom-level files in this entry.
+ */
+ public List getFilter()
+ {
+ return filter;
+ }
+
+ /**
+ * Sets the name filter that is applied to bottom-level files in this entry.
+ */
+ public void setFilter(List filter)
+ {
+ this.filter = filter == null || filter.size() == 0 ? null : filter;
+ }
+
+
+ /**
+ * Returns the name filter that is applied to apk files in this entry, if any.
+ */
+ public List getApkFilter()
+ {
+ return apkFilter;
+ }
+
+ /**
+ * Sets the name filter that is applied to apk files in this entry, if any.
+ */
+ public void setApkFilter(List filter)
+ {
+ this.apkFilter = filter == null || filter.size() == 0 ? null : filter;
+ }
+
+
+ /**
+ * Returns the name filter that is applied to jar files in this entry, if any.
+ */
+ public List getJarFilter()
+ {
+ return jarFilter;
+ }
+
+ /**
+ * Sets the name filter that is applied to jar files in this entry, if any.
+ */
+ public void setJarFilter(List filter)
+ {
+ this.jarFilter = filter == null || filter.size() == 0 ? null : filter;
+ }
+
+
+ /**
+ * Returns the name filter that is applied to aar files in this entry, if any.
+ */
+ public List getAarFilter()
+ {
+ return aarFilter;
+ }
+
+ /**
+ * Sets the name filter that is applied to aar files in this entry, if any.
+ */
+ public void setAarFilter(List filter)
+ {
+ this.aarFilter = filter == null || filter.size() == 0 ? null : filter;
+ }
+
+
+ /**
+ * Returns the name filter that is applied to war files in this entry, if any.
+ */
+ public List getWarFilter()
+ {
+ return warFilter;
+ }
+
+ /**
+ * Sets the name filter that is applied to war files in this entry, if any.
+ */
+ public void setWarFilter(List filter)
+ {
+ this.warFilter = filter == null || filter.size() == 0 ? null : filter;
+ }
+
+
+ /**
+ * Returns the name filter that is applied to ear files in this entry, if any.
+ */
+ public List getEarFilter()
+ {
+ return earFilter;
+ }
+
+ /**
+ * Sets the name filter that is applied to ear files in this entry, if any.
+ */
+ public void setEarFilter(List filter)
+ {
+ this.earFilter = filter == null || filter.size() == 0 ? null : filter;
+ }
+
+
+ /**
+ * Returns the name filter that is applied to zip files in this entry, if any.
+ */
+ public List getZipFilter()
+ {
+ return zipFilter;
+ }
+
+ /**
+ * Sets the name filter that is applied to zip files in this entry, if any.
+ */
+ public void setZipFilter(List filter)
+ {
+ this.zipFilter = filter == null || filter.size() == 0 ? null : filter;
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ String string = getName();
+
+ if (filter != null ||
+ jarFilter != null ||
+ aarFilter != null ||
+ warFilter != null ||
+ earFilter != null ||
+ zipFilter != null)
+ {
+ string +=
+ ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD +
+ (aarFilter != null ? ListUtil.commaSeparatedString(aarFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (apkFilter != null ? ListUtil.commaSeparatedString(apkFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (zipFilter != null ? ListUtil.commaSeparatedString(zipFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (earFilter != null ? ListUtil.commaSeparatedString(earFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (warFilter != null ? ListUtil.commaSeparatedString(warFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (jarFilter != null ? ListUtil.commaSeparatedString(jarFilter, true) : "") +
+ ConfigurationConstants.SEPARATOR_KEYWORD +
+ (filter != null ? ListUtil.commaSeparatedString(filter, true) : "") +
+ ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD;
+ }
+
+ return string;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecification.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecification.java
new file mode 100644
index 0000000000..efdeb1c817
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecification.java
@@ -0,0 +1,259 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.util.*;
+
+/**
+ * This class stores a specification of classes and possibly class members.
+ * The specification is template-based: the class names and class member names
+ * and descriptors can contain wildcards. Classes can be specified explicitly,
+ * or as extensions or implementations in the class hierarchy.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassSpecification implements Cloneable
+{
+ public final String comments;
+ public int requiredSetAccessFlags;
+ public int requiredUnsetAccessFlags;
+ public final String annotationType;
+ public String className;
+ public final String extendsAnnotationType;
+ public final String extendsClassName;
+
+ public List fieldSpecifications;
+ public List methodSpecifications;
+
+
+ /**
+ * Creates a new ClassSpecification for all possible classes, without
+ * comments or class members.
+ */
+ public ClassSpecification()
+ {
+ this(null,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ null);
+ }
+
+
+ /**
+ * Creates a new ClassSpecification that is a copy of the given specification.
+ */
+ public ClassSpecification(ClassSpecification classSpecification)
+ {
+ this(classSpecification.comments,
+ classSpecification.requiredSetAccessFlags,
+ classSpecification.requiredUnsetAccessFlags,
+ classSpecification.annotationType,
+ classSpecification.className,
+ classSpecification.extendsAnnotationType,
+ classSpecification.extendsClassName,
+ classSpecification.fieldSpecifications,
+ classSpecification.methodSpecifications);
+ }
+
+
+ /**
+ * Creates a new ClassSpecification for the specified class(es), without
+ * class members.
+ *
+ * @param comments provides optional comments on this
+ * specification.
+ * @param requiredSetAccessFlags the class access flags that must be set
+ * in order for the class to apply.
+ * @param requiredUnsetAccessFlags the class access flags that must be
+ * unset in order for the class to apply.
+ * @param annotationType the name of the class that must be an
+ * annotation of the class in order for it
+ * to apply. The name may be null to
+ * specify that no annotation is required.
+ * @param className the class name. The name may be null to
+ * specify any class, or it may contain
+ * "**", "*", or "?" wildcards.
+ * @param extendsAnnotationType the name of the class of that must be
+ * an annotation of the class that the
+ * class must extend or implement in order
+ * to apply. The name may be null to
+ * specify that no annotation is required.
+ * @param extendsClassName the name of the class that the class
+ * must extend or implement in order to
+ * apply. The name may be null to specify
+ * any class.
+ */
+ public ClassSpecification(String comments,
+ int requiredSetAccessFlags,
+ int requiredUnsetAccessFlags,
+ String annotationType,
+ String className,
+ String extendsAnnotationType,
+ String extendsClassName)
+ {
+ this(comments,
+ requiredSetAccessFlags,
+ requiredUnsetAccessFlags,
+ annotationType,
+ className,
+ extendsAnnotationType,
+ extendsClassName,
+ null,
+ null);
+ }
+
+
+ /**
+ * Creates a new ClassSpecification for the specified classes and class
+ * members.
+ *
+ * @param comments provides optional comments on this
+ * specification.
+ * @param requiredSetAccessFlags the class access flags that must be set
+ * in order for the class to apply.
+ * @param requiredUnsetAccessFlags the class access flags that must be
+ * unset in order for the class to apply.
+ * @param annotationType the name of the class that must be an
+ * annotation of the class in order for it
+ * to apply. The name may be null to
+ * specify that no annotation is required.
+ * @param className the class name. The name may be null to
+ * specify any class, or it may contain
+ * "**", "*", or "?" wildcards.
+ * @param extendsAnnotationType the name of the class of that must be
+ * an annotation of the class that the
+ * class must extend or implement in order
+ * to apply. The name may be null to
+ * specify that no annotation is required.
+ * @param extendsClassName the name of the class that the class
+ * must extend or implement in order to
+ * apply. The name may be null to specify
+ * any class.
+ * @param fieldSpecifications the field specifications.
+ * @param methodSpecifications the method specifications.
+ */
+ public ClassSpecification(String comments,
+ int requiredSetAccessFlags,
+ int requiredUnsetAccessFlags,
+ String annotationType,
+ String className,
+ String extendsAnnotationType,
+ String extendsClassName,
+ List fieldSpecifications,
+ List methodSpecifications)
+ {
+ this.comments = comments;
+ this.requiredSetAccessFlags = requiredSetAccessFlags;
+ this.requiredUnsetAccessFlags = requiredUnsetAccessFlags;
+ this.annotationType = annotationType;
+ this.className = className;
+ this.extendsAnnotationType = extendsAnnotationType;
+ this.extendsClassName = extendsClassName;
+ this.fieldSpecifications = fieldSpecifications;
+ this.methodSpecifications = methodSpecifications;
+ }
+
+
+ /**
+ * Specifies to keep the specified field(s) of this option's class(es).
+ *
+ * @param fieldSpecification the field specification.
+ */
+ public void addField(MemberSpecification fieldSpecification)
+ {
+ if (fieldSpecifications == null)
+ {
+ fieldSpecifications = new ArrayList();
+ }
+
+ fieldSpecifications.add(fieldSpecification);
+ }
+
+
+ /**
+ * Specifies to keep the specified method(s) of this option's class(es).
+ *
+ * @param methodSpecification the method specification.
+ */
+ public void addMethod(MemberSpecification methodSpecification)
+ {
+ if (methodSpecifications == null)
+ {
+ methodSpecifications = new ArrayList();
+ }
+
+ methodSpecifications.add(methodSpecification);
+ }
+
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (object == null ||
+ this.getClass() != object.getClass())
+ {
+ return false;
+ }
+
+ ClassSpecification other = (ClassSpecification)object;
+ return
+// (this.comments == null ? other.comments == null : this.comments.equals(other.comments) ) &&
+ (this.requiredSetAccessFlags == other.requiredSetAccessFlags ) &&
+ (this.requiredUnsetAccessFlags == other.requiredUnsetAccessFlags ) &&
+ (this.annotationType == null ? other.annotationType == null : this.annotationType.equals(other.annotationType) ) &&
+ (this.className == null ? other.className == null : this.className.equals(other.className) ) &&
+ (this.extendsAnnotationType == null ? other.extendsAnnotationType == null : this.extendsAnnotationType.equals(other.extendsAnnotationType)) &&
+ (this.extendsClassName == null ? other.extendsClassName == null : this.extendsClassName.equals(other.extendsClassName) ) &&
+ (this.fieldSpecifications == null ? other.fieldSpecifications == null : this.fieldSpecifications.equals(other.fieldSpecifications) ) &&
+ (this.methodSpecifications == null ? other.methodSpecifications == null : this.methodSpecifications.equals(other.methodSpecifications) );
+ }
+
+ public int hashCode()
+ {
+ return
+// (comments == null ? 0 : comments.hashCode() ) ^
+ (requiredSetAccessFlags ) ^
+ (requiredUnsetAccessFlags ) ^
+ (annotationType == null ? 0 : annotationType.hashCode() ) ^
+ (className == null ? 0 : className.hashCode() ) ^
+ (extendsAnnotationType == null ? 0 : extendsAnnotationType.hashCode()) ^
+ (extendsClassName == null ? 0 : extendsClassName.hashCode() ) ^
+ (fieldSpecifications == null ? 0 : fieldSpecifications.hashCode() ) ^
+ (methodSpecifications == null ? 0 : methodSpecifications.hashCode() );
+ }
+
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ return null;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecificationVisitorFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecificationVisitorFactory.java
new file mode 100644
index 0000000000..e13000388b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ClassSpecificationVisitorFactory.java
@@ -0,0 +1,529 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.ClassConstants;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.visitor.*;
+
+import java.util.List;
+
+/**
+ * This factory creates visitors to efficiently travel to specified classes and
+ * class members.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassSpecificationVisitorFactory
+{
+ /**
+ * Constructs a ClassPoolVisitor to efficiently travel to the specified
+ * classes and class members.
+ *
+ * @param keepClassSpecifications the list of KeepClassSpecification
+ * instances that specify the classes and
+ * class members to visit.
+ * @param classVisitor the ClassVisitor to be applied to matching
+ * classes.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class members.
+ * @param shrinking a flag that specifies whether the visitors
+ * are intended for the shrinking step.
+ * @param optimizing a flag that specifies whether the visitors
+ * are intended for the optimization step.
+ * @param obfuscating a flag that specifies whether the visitors
+ * are intended for the obfuscation step.
+ */
+ public static ClassPoolVisitor createClassPoolVisitor(List keepClassSpecifications,
+ ClassVisitor classVisitor,
+ MemberVisitor memberVisitor,
+ boolean shrinking,
+ boolean optimizing,
+ boolean obfuscating)
+ {
+ MultiClassPoolVisitor multiClassPoolVisitor = new MultiClassPoolVisitor();
+
+ if (keepClassSpecifications != null)
+ {
+ for (int index = 0; index < keepClassSpecifications.size(); index++)
+ {
+ KeepClassSpecification keepClassSpecification =
+ (KeepClassSpecification)keepClassSpecifications.get(index);
+
+ if ((shrinking && !keepClassSpecification.allowShrinking) ||
+ (optimizing && !keepClassSpecification.allowOptimization) ||
+ (obfuscating && !keepClassSpecification.allowObfuscation))
+ {
+ multiClassPoolVisitor.addClassPoolVisitor(
+ createClassPoolVisitor(keepClassSpecification,
+ classVisitor,
+ memberVisitor));
+ }
+ }
+ }
+
+ return multiClassPoolVisitor;
+ }
+
+
+ /**
+ * Constructs a ClassPoolVisitor to efficiently travel to the specified
+ * classes and class members.
+ *
+ * @param classSpecifications the list of ClassSpecification instances
+ * that specify the classes and class members
+ * to visit.
+ * @param classVisitor the ClassVisitor to be applied to matching
+ * classes.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class members.
+ */
+ public static ClassPoolVisitor createClassPoolVisitor(List classSpecifications,
+ ClassVisitor classVisitor,
+ MemberVisitor memberVisitor)
+ {
+ MultiClassPoolVisitor multiClassPoolVisitor = new MultiClassPoolVisitor();
+
+ if (classSpecifications != null)
+ {
+ for (int index = 0; index < classSpecifications.size(); index++)
+ {
+ ClassSpecification classSpecification =
+ (ClassSpecification)classSpecifications.get(index);
+
+ multiClassPoolVisitor.addClassPoolVisitor(
+ createClassPoolVisitor(classSpecification,
+ classVisitor,
+ memberVisitor));
+ }
+ }
+
+ return multiClassPoolVisitor;
+ }
+
+
+ /**
+ * Constructs a ClassPoolVisitor to efficiently travel to the specified
+ * classes and class members.
+ *
+ * @param keepClassSpecification the specifications of the class(es) and
+ * class members to visit.
+ * @param classVisitor the ClassVisitor to be applied to
+ * matching classes.
+ * @param memberVisitor the MemberVisitor to be applied to
+ * matching class members.
+ */
+ public static ClassPoolVisitor createClassPoolVisitor(KeepClassSpecification keepClassSpecification,
+ ClassVisitor classVisitor,
+ MemberVisitor memberVisitor)
+ {
+ // If specified, let the class visitor also visit the descriptor
+ // classes and the signature classes.
+ if (keepClassSpecification.markDescriptorClasses &&
+ classVisitor != null)
+ {
+ memberVisitor = memberVisitor == null ?
+ new MemberDescriptorReferencedClassVisitor(classVisitor) :
+ new MultiMemberVisitor(new MemberVisitor[]
+ {
+ memberVisitor,
+
+ new MemberDescriptorReferencedClassVisitor(classVisitor),
+
+ new AllAttributeVisitor(
+ new AttributeNameFilter(ClassConstants.ATTR_Signature,
+ new ReferencedClassVisitor(classVisitor)))
+ });
+ }
+
+ // Don't visit the classes if not specified.
+ if (!keepClassSpecification.markClasses &&
+ !keepClassSpecification.markConditionally)
+ {
+ classVisitor = null;
+ }
+
+ // If specified, let the marker visit the class and its class
+ // members conditionally.
+ if (keepClassSpecification.markConditionally)
+ {
+ // Combine both visitors.
+ ClassVisitor composedClassVisitor =
+ createCombinedClassVisitor(keepClassSpecification,
+ classVisitor,
+ memberVisitor);
+
+ // Replace the class visitor.
+ classVisitor =
+ createClassMemberTester(keepClassSpecification,
+ composedClassVisitor);
+
+ // Discard the member visitor, because it has already been included.
+ memberVisitor = null;
+ }
+
+ return createClassPoolVisitor((ClassSpecification)keepClassSpecification,
+ classVisitor,
+ memberVisitor);
+ }
+
+
+ /**
+ * Constructs a ClassPoolVisitor to efficiently travel to the specified
+ * classes and class members.
+ *
+ * @param classSpecification the specifications of the class(es) and class
+ * members to visit.
+ * @param classVisitor the ClassVisitor to be applied to matching
+ * classes.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class members.
+ */
+ public static ClassPoolVisitor createClassPoolVisitor(ClassSpecification classSpecification,
+ ClassVisitor classVisitor,
+ MemberVisitor memberVisitor)
+ {
+ // Combine both visitors.
+ ClassVisitor composedClassVisitor =
+ createCombinedClassVisitor(classSpecification,
+ classVisitor,
+ memberVisitor);
+
+ // By default, start visiting from the named class name, if specified.
+ String className = classSpecification.className;
+
+ // Although we may have to start from the extended class.
+ String extendsAnnotationType = classSpecification.extendsAnnotationType;
+ String extendsClassName = classSpecification.extendsClassName;
+
+ // If wildcarded, only visit classes with matching names.
+ if (className != null &&
+ (extendsAnnotationType != null ||
+ extendsClassName != null ||
+ containsWildCards(className)))
+ {
+ composedClassVisitor =
+ new ClassNameFilter(className, composedClassVisitor);
+
+ // We'll have to visit all classes now.
+ className = null;
+ }
+
+ // If specified, only visit classes with the right annotation.
+ String annotationType = classSpecification.annotationType;
+
+ if (annotationType != null)
+ {
+ composedClassVisitor =
+ new AllAttributeVisitor(
+ new AllAnnotationVisitor(
+ new AnnotationTypeFilter(annotationType,
+ new AnnotatedClassVisitor(composedClassVisitor))));
+ }
+
+ // If specified, only visit classes with the right access flags.
+ if (classSpecification.requiredSetAccessFlags != 0 ||
+ classSpecification.requiredUnsetAccessFlags != 0)
+ {
+ composedClassVisitor =
+ new ClassAccessFilter(classSpecification.requiredSetAccessFlags,
+ classSpecification.requiredUnsetAccessFlags,
+ composedClassVisitor);
+ }
+
+ // If it's specified, start visiting from the extended class.
+ if (extendsAnnotationType != null ||
+ extendsClassName != null)
+ {
+ // Start visiting from the extended class.
+ composedClassVisitor =
+ new ClassHierarchyTraveler(false, false, false, true,
+ composedClassVisitor);
+
+ // If specified, only visit extended classes with the right annotation.
+ if (extendsAnnotationType != null)
+ {
+ composedClassVisitor =
+ new AllAttributeVisitor(
+ new AllAnnotationVisitor(
+ new AnnotationTypeFilter(extendsAnnotationType,
+ new AnnotatedClassVisitor(composedClassVisitor))));
+ }
+
+ // If specified, only visit extended classes with matching names.
+ if (extendsClassName != null)
+ {
+ // If wildcarded, only visit extended classes with matching names.
+ if (containsWildCards(extendsClassName))
+ {
+ composedClassVisitor =
+ new ClassNameFilter(extendsClassName,
+ composedClassVisitor);
+ }
+ else
+ {
+ // Start visiting from the named extended class.
+ className = extendsClassName;
+ }
+ }
+ }
+
+ // If specified, visit a single named class, otherwise visit all classes.
+ return className != null ?
+ (ClassPoolVisitor)new NamedClassVisitor(composedClassVisitor, className) :
+ (ClassPoolVisitor)new AllClassVisitor(composedClassVisitor);
+ }
+
+
+ /**
+ * Constructs a ClassVisitor to efficiently travel to the specified
+ * classes and class members.
+ *
+ * @param classSpecification the specifications of the class(es) and class
+ * members to visit.
+ * @param classVisitor the ClassVisitor to be applied to matching
+ * classes.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class members.
+ */
+ private static ClassVisitor createCombinedClassVisitor(ClassSpecification classSpecification,
+ ClassVisitor classVisitor,
+ MemberVisitor memberVisitor)
+ {
+ // Don't visit any members if there aren't any member specifications.
+ if (classSpecification.fieldSpecifications == null &&
+ classSpecification.methodSpecifications == null)
+ {
+ memberVisitor = null;
+ }
+
+ // The class visitor for classes and their members.
+ MultiClassVisitor multiClassVisitor = new MultiClassVisitor();
+
+ // If specified, let the class visitor visit the class itself.
+ if (classVisitor != null)
+ {
+ // This class visitor may be the only one.
+ if (memberVisitor == null)
+ {
+ return classVisitor;
+ }
+
+ multiClassVisitor.addClassVisitor(classVisitor);
+ }
+
+ // If specified, let the member info visitor visit the class members.
+ if (memberVisitor != null)
+ {
+ ClassVisitor memberClassVisitor =
+ createClassVisitor(classSpecification, memberVisitor);
+
+ // This class visitor may be the only one.
+ if (classVisitor == null)
+ {
+ return memberClassVisitor;
+ }
+
+ multiClassVisitor.addClassVisitor(memberClassVisitor);
+ }
+
+ return multiClassVisitor;
+ }
+
+
+ /**
+ * Constructs a ClassVisitor to efficiently travel to the specified class
+ * members.
+ *
+ * @param classSpecification the specifications of the class members to visit.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class members.
+ */
+ private static ClassVisitor createClassVisitor(ClassSpecification classSpecification,
+ MemberVisitor memberVisitor)
+ {
+ MultiClassVisitor multiClassVisitor = new MultiClassVisitor();
+
+ addMemberVisitors(classSpecification.fieldSpecifications, true, multiClassVisitor, memberVisitor);
+ addMemberVisitors(classSpecification.methodSpecifications, false, multiClassVisitor, memberVisitor);
+
+ // Mark the class member in this class and in super classes.
+ return new ClassHierarchyTraveler(true, true, false, false,
+ multiClassVisitor);
+ }
+
+
+ /**
+ * Adds elements to the given MultiClassVisitor, to apply the given
+ * MemberVisitor to all class members that match the given List
+ * of options (of the given type).
+ */
+ private static void addMemberVisitors(List memberSpecifications,
+ boolean isField,
+ MultiClassVisitor multiClassVisitor,
+ MemberVisitor memberVisitor)
+ {
+ if (memberSpecifications != null)
+ {
+ for (int index = 0; index < memberSpecifications.size(); index++)
+ {
+ MemberSpecification memberSpecification =
+ (MemberSpecification)memberSpecifications.get(index);
+
+ multiClassVisitor.addClassVisitor(
+ createClassVisitor(memberSpecification,
+ isField,
+ memberVisitor));
+ }
+ }
+ }
+
+
+ /**
+ * Constructs a ClassVisitor that conditionally applies the given
+ * ClassVisitor to all classes that contain the given class members.
+ */
+ private static ClassVisitor createClassMemberTester(ClassSpecification classSpecification,
+ ClassVisitor classVisitor)
+ {
+ // Create a linked list of conditional visitors, for fields and for
+ // methods.
+ return createClassMemberTester(classSpecification.fieldSpecifications,
+ true,
+ createClassMemberTester(classSpecification.methodSpecifications,
+ false,
+ classVisitor));
+ }
+
+
+ /**
+ * Constructs a ClassVisitor that conditionally applies the given
+ * ClassVisitor to all classes that contain the given List of class
+ * members (of the given type).
+ */
+ private static ClassVisitor createClassMemberTester(List memberSpecifications,
+ boolean isField,
+ ClassVisitor classVisitor)
+ {
+ // Create a linked list of conditional visitors.
+ if (memberSpecifications != null)
+ {
+ for (int index = 0; index < memberSpecifications.size(); index++)
+ {
+ MemberSpecification memberSpecification =
+ (MemberSpecification)memberSpecifications.get(index);
+
+ classVisitor =
+ createClassVisitor(memberSpecification,
+ isField,
+ new MemberToClassVisitor(classVisitor));
+ }
+ }
+
+ return classVisitor;
+ }
+
+
+ /**
+ * Creates a new ClassVisitor to efficiently travel to the specified class
+ * members.
+ *
+ * @param memberSpecification the specification of the class member(s) to
+ * visit.
+ * @param memberVisitor the MemberVisitor to be applied to matching
+ * class member(s).
+ */
+ private static ClassVisitor createClassVisitor(MemberSpecification memberSpecification,
+ boolean isField,
+ MemberVisitor memberVisitor)
+ {
+ String name = memberSpecification.name;
+ String descriptor = memberSpecification.descriptor;
+
+ // If name or descriptor are not fully specified, only visit matching
+ // class members.
+ boolean fullySpecified =
+ name != null &&
+ descriptor != null &&
+ !containsWildCards(name) &&
+ !containsWildCards(descriptor);
+
+ if (!fullySpecified)
+ {
+ if (descriptor != null)
+ {
+ memberVisitor =
+ new MemberDescriptorFilter(descriptor, memberVisitor);
+ }
+
+ if (name != null)
+ {
+ memberVisitor =
+ new MemberNameFilter(name, memberVisitor);
+ }
+ }
+
+ // If specified, only visit class members with the right annotation.
+ if (memberSpecification.annotationType != null)
+ {
+ memberVisitor =
+ new AllAttributeVisitor(
+ new AllAnnotationVisitor(
+ new AnnotationTypeFilter(memberSpecification.annotationType,
+ new AnnotationToMemberVisitor(memberVisitor))));
+ }
+
+ // If any access flags are specified, only visit matching class members.
+ if (memberSpecification.requiredSetAccessFlags != 0 ||
+ memberSpecification.requiredUnsetAccessFlags != 0)
+ {
+ memberVisitor =
+ new MemberAccessFilter(memberSpecification.requiredSetAccessFlags,
+ memberSpecification.requiredUnsetAccessFlags,
+ memberVisitor);
+ }
+
+ // Depending on what's specified, visit a single named class member,
+ // or all class members, filtering the matching ones.
+ return isField ?
+ fullySpecified ?
+ (ClassVisitor)new NamedFieldVisitor(name, descriptor, memberVisitor) :
+ (ClassVisitor)new AllFieldVisitor(memberVisitor) :
+ fullySpecified ?
+ (ClassVisitor)new NamedMethodVisitor(name, descriptor, memberVisitor) :
+ (ClassVisitor)new AllMethodVisitor(memberVisitor);
+ }
+
+
+ // Small utility methods.
+
+ private static boolean containsWildCards(String string)
+ {
+ return string != null &&
+ (string.indexOf('!') >= 0 ||
+ string.indexOf('*') >= 0 ||
+ string.indexOf('?') >= 0 ||
+ string.indexOf('%') >= 0 ||
+ string.indexOf(',') >= 0 ||
+ string.indexOf("///") >= 0);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/Configuration.java b/third_party/java/proguard/proguard5.3.3/src/proguard/Configuration.java
new file mode 100644
index 0000000000..0df9884a9a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/Configuration.java
@@ -0,0 +1,331 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * The ProGuard configuration.
+ *
+ * @see ProGuard
+ *
+ * @author Eric Lafortune
+ */
+public class Configuration
+{
+ public static final File STD_OUT = new File("");
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Input and output options.
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * A list of input and output entries (jars, wars, ears, zips, and directories).
+ */
+ public ClassPath programJars;
+
+ /**
+ * A list of library entries (jars, wars, ears, zips, and directories).
+ */
+ public ClassPath libraryJars;
+
+ /**
+ * Specifies whether to skip non-public library classes while reading
+ * library jars.
+ */
+ public boolean skipNonPublicLibraryClasses = false;
+
+ /**
+ * Specifies whether to skip non-public library class members while reading
+ * library classes.
+ */
+ public boolean skipNonPublicLibraryClassMembers = true;
+
+ /**
+ * A list of <code>String</code>s specifying directories to be kept in
+ * the output directories or the output jars. A <code>null</code> list
+ * means no directories. An empty list means all directories. The directory
+ * names may contain "**", "*", or "?" wildcards, and they may be preceded
+ * by the "!" negator.
+ */
+ public List keepDirectories;
+
+ /**
+ * Specifies the version number of the output classes, or 0 if the version
+ * number can be left unchanged.
+ */
+ public int targetClassVersion;
+
+ /**
+ * Specifies the last modification time of this configuration. This time
+ * is necessary to check whether the input has to be processed. Setting it
+ * to Long.MAX_VALUE forces processing, even if the modification times
+ * of the output appear more recent than the modification times of the
+ * input.
+ */
+ public long lastModified = 0L;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Keep options.
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * A list of {@link KeepClassSpecification} instances, whose class names and
+ * class member names are to be kept from shrinking, optimization, and/or
+ * obfuscation.
+ */
+ public List keep;
+
+ /**
+ * An optional output file for listing the kept seeds.
+ * An empty file name means the standard output.
+ */
+ public File printSeeds;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Shrinking options.
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Specifies whether the code should be shrunk.
+ */
+ public boolean shrink = true;
+
+ /**
+ * An optional output file for listing the unused classes and class
+ * members. An empty file name means the standard output.
+ */
+ public File printUsage;
+
+ /**
+ * A list of {@link ClassSpecification} instances, for which an explanation
+ * is to be printed, why they are kept in the shrinking step.
+ */
+ public List whyAreYouKeeping;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Optimization options.
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Specifies whether the code should be optimized.
+ */
+ public boolean optimize = true;
+
+ /**
+ * A list of <code>String</code>s specifying the optimizations to be
+ * performed. A <code>null</code> list means all optimizations. The
+ * optimization names may contain "*" or "?" wildcards, and they may
+ * be preceded by the "!" negator.
+ */
+ public List optimizations;
+
+ /**
+ * Specifies the number of optimization passes.
+ */
+ public int optimizationPasses = 1;
+
+ /**
+ * A list of {@link ClassSpecification} instances, whose methods are
+ * assumed to have no side effects.
+ */
+ public List assumeNoSideEffects;
+
+ /**
+ * Specifies whether the access of class members can be modified.
+ */
+ public boolean allowAccessModification = false;
+
+ /**
+ * Specifies whether interfaces may be merged aggressively.
+ */
+ public boolean mergeInterfacesAggressively = false;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Obfuscation options.
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Specifies whether the code should be obfuscated.
+ */
+ public boolean obfuscate = true;
+
+ /**
+ * An optional output file for listing the obfuscation mapping.
+ * An empty file name means the standard output.
+ */
+ public File printMapping;
+
+ /**
+ * An optional input file for reading an obfuscation mapping.
+ */
+ public File applyMapping;
+
+ /**
+ * An optional name of a file containing obfuscated class member names.
+ */
+ public File obfuscationDictionary;
+
+ /**
+ * An optional name of a file containing obfuscated class names.
+ */
+ public File classObfuscationDictionary;
+
+ /**
+ * An optional name of a file containing obfuscated package names.
+ */
+ public File packageObfuscationDictionary;
+
+ /**
+ * Specifies whether to apply aggressive name overloading on class members.
+ */
+ public boolean overloadAggressively = false;
+
+ /**
+ * Specifies whether to generate globally unique class member names.
+ */
+ public boolean useUniqueClassMemberNames = false;
+
+ /**
+ * Specifies whether obfuscated packages and classes can get mixed-case names.
+ */
+ public boolean useMixedCaseClassNames = true;
+
+ /**
+ * A list of <code>String</code>s specifying package names to be kept.
+ * A <code>null</code> list means no names. An empty list means all
+ * names. The package names may contain "**", "*", or "?" wildcards, and
+ * they may be preceded by the "!" negator.
+ */
+ public List keepPackageNames;
+
+ /**
+ * An optional base package if the obfuscated package hierarchy is to be
+ * flattened, <code>null</code> otherwise.
+ */
+ public String flattenPackageHierarchy;
+
+ /**
+ * An optional base package if the obfuscated classes are to be repackaged
+ * into a single package, <code>null</code> otherwise.
+ */
+ public String repackageClasses;
+
+ /**
+ * A list of <code>String</code>s specifying optional attributes to be kept.
+ * A <code>null</code> list means no attributes. An empty list means all
+ * attributes. The attribute names may contain "*" or "?" wildcards, and
+ * they may be preceded by the "!" negator.
+ */
+ public List keepAttributes;
+
+ /**
+ * Specifies whether method parameter names and types should be kept for
+ * methods that are not obfuscated. This is achieved by keeping partial
+ * "LocalVariableTable" and "LocalVariableTypeTable" attributes.
+ */
+ public boolean keepParameterNames = false;
+
+ /**
+ * An optional replacement for all SourceFile attributes.
+ */
+ public String newSourceFileAttribute;
+
+ /**
+ * A list of <code>String</code>s specifying a filter for classes whose
+ * string constants are to be adapted, based on corresponding obfuscated
+ * class names.
+ */
+ public List adaptClassStrings;
+
+ /**
+ * A list of <code>String</code>s specifying a filter for files whose
+ * names are to be adapted, based on corresponding obfuscated class names.
+ */
+ public List adaptResourceFileNames;
+
+ /**
+ * A list of <code>String</code>s specifying a filter for files whose
+ * contents are to be adapted, based on obfuscated class names.
+ */
+ public List adaptResourceFileContents;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Preverification options.
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Specifies whether the code should be preverified.
+ */
+ public boolean preverify = true;
+
+ /**
+ * Specifies whether the code should be preverified for Java Micro Edition
+ * (creating StackMap attributes) instead of for Java Standard Edition
+ * (creating StackMapTable attributes).
+ */
+ public boolean microEdition = false;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // General options.
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Specifies whether to print verbose messages.
+ */
+ public boolean verbose = false;
+
+ /**
+ * A list of <code>String</code>s specifying a filter for the classes for
+ * which not to print notes, if there are noteworthy potential problems.
+ * A <code>null</code> list means all classes. The class names may contain
+ * "**", "*", or "?" wildcards, and they may be preceded by the "!" negator.
+ */
+ public List note = null;
+
+ /**
+ * A list of <code>String</code>s specifying a filter for the classes for
+ * which not to print warnings, if there are any problems.
+ * A <code>null</code> list means all classes. The class names may contain
+ * "**", "*", or "?" wildcards, and they may be preceded by the "!" negator.
+ */
+ public List warn = null;
+
+ /**
+ * Specifies whether to ignore any warnings.
+ */
+ public boolean ignoreWarnings = false;
+
+ /**
+ * An optional output file for printing out the configuration that ProGuard
+ * is using (with included files and replaced variables).
+ * An empty file name means the standard output.
+ */
+ public File printConfiguration;
+
+ /**
+ * An optional output file for printing out the processed code in a more
+ * or less readable form. An empty file name means the standard output.
+ */
+ public File dump;
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationChecker.java
new file mode 100644
index 0000000000..63c0f65861
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationChecker.java
@@ -0,0 +1,224 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.util.WarningPrinter;
+
+import java.io.IOException;
+
+/**
+ * This class performs sanity checks on a given configurations.
+ *
+ * @author Eric Lafortune
+ */
+public class ConfigurationChecker
+{
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new ConfigurationChecker with the given configuration.
+ */
+ public ConfigurationChecker(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Checks the given configuration for potential problems.
+ */
+ public void check() throws IOException
+ {
+ ClassPath programJars = configuration.programJars;
+ ClassPath libraryJars = configuration.libraryJars;
+
+ // Check that the input isn't empty.
+ if (programJars == null)
+ {
+ throw new IOException("The input is empty. You have to specify one or more '-injars' options.");
+ }
+
+ // Check that the first jar is an input jar.
+ ClassPathEntry firstEntry = programJars.get(0);
+ if (firstEntry.isOutput())
+ {
+ throw new IOException("The output jar [" + firstEntry.getName() +
+ "] must be specified after an input jar, or it will be empty.");
+ }
+
+ // Check that the first of two subsequent the output jars has a filter.
+ for (int index = 0; index < programJars.size() - 1; index++)
+ {
+ ClassPathEntry entry = programJars.get(index);
+ if (entry.isOutput() &&
+ !entry.isFiltered() &&
+ programJars.get(index + 1).isOutput())
+ {
+ throw new IOException("The output jar [" + entry.getName() +
+ "] must have a filter, or all subsequent output jars will be empty.");
+ }
+ }
+
+ // Check for conflicts between input/output entries of the class paths.
+ checkConflicts(programJars, programJars);
+ checkConflicts(programJars, libraryJars);
+ checkConflicts(libraryJars, libraryJars);
+
+ // Print out some general notes if necessary.
+ if ((configuration.note == null ||
+ !configuration.note.isEmpty()))
+ {
+ // Check for potential problems with mixed-case class names on
+ // case-insensitive file systems.
+ if (configuration.obfuscate &&
+ configuration.useMixedCaseClassNames &&
+ configuration.classObfuscationDictionary == null)
+ {
+ String os = System.getProperty("os.name").toLowerCase();
+ if (os.startsWith("windows") ||
+ os.startsWith("mac os"))
+ {
+ // Go over all program class path entries.
+ for (int index = 0; index < programJars.size(); index++)
+ {
+ // Is it an output directory?
+ ClassPathEntry entry = programJars.get(index);
+ if (entry.isOutput() &&
+ !entry.isApk() &&
+ !entry.isJar() &&
+ !entry.isAar() &&
+ !entry.isWar() &&
+ !entry.isEar() &&
+ !entry.isZip())
+ {
+ System.out.println("Note: you're writing the processed class files to a directory [" + entry.getName() + "].");
+ System.out.println(" This will likely cause problems with obfuscated mixed-case class names.");
+ System.out.println(" You should consider writing the output to a jar file, or otherwise");
+ System.out.println(" specify '-dontusemixedcaseclassnames'.");
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Check if -adaptresourcefilecontents has a proper filter.
+ if (configuration.adaptResourceFileContents != null &&
+ (configuration.adaptResourceFileContents.isEmpty() ||
+ configuration.adaptResourceFileContents.get(0).equals(ConfigurationConstants.ANY_FILE_KEYWORD)))
+ {
+ System.out.println("Note: you're specifying '-adaptresourcefilecontents' for all resource files.");
+ System.out.println(" This will most likely cause problems with binary files.");
+ }
+
+ // Check if all -keepclassmembers options indeed have class members.
+ WarningPrinter keepClassMemberNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ new KeepClassMemberChecker(keepClassMemberNotePrinter).checkClassSpecifications(configuration.keep);
+
+ // Check if -assumenosideffects options don't specify all methods.
+ WarningPrinter assumeNoSideEffectsNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ new AssumeNoSideEffectsChecker(assumeNoSideEffectsNotePrinter).checkClassSpecifications(configuration.assumeNoSideEffects);
+
+ // Print out a summary of the notes, if necessary.
+ int keepClassMemberNoteCount = keepClassMemberNotePrinter.getWarningCount();
+ if (keepClassMemberNoteCount > 0)
+ {
+ System.out.println("Note: there were " + keepClassMemberNoteCount +
+ " '-keepclassmembers' options that didn't specify class");
+ System.out.println(" members. You should specify at least some class members or consider");
+ System.out.println(" if you just need '-keep'.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#classmembers)");
+ }
+
+ int assumeNoSideEffectsNoteCount = assumeNoSideEffectsNotePrinter.getWarningCount();
+ if (assumeNoSideEffectsNoteCount > 0)
+ {
+ System.out.println("Note: there were " + assumeNoSideEffectsNoteCount +
+ " '-assumenosideeffects' options that try to match all");
+ System.out.println(" methods with wildcards. This will likely cause problems with methods like");
+ System.out.println(" 'wait()' and 'notify()'. You should specify the methods more precisely.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#nosideeffects)");
+ }
+ }
+ }
+
+
+ /**
+ * Performs some sanity checks on the class paths.
+ */
+ private void checkConflicts(ClassPath classPath1,
+ ClassPath classPath2)
+ throws IOException
+ {
+ if (classPath1 == null ||
+ classPath2 == null)
+ {
+ return;
+ }
+
+ for (int index1 = 0; index1 < classPath1.size(); index1++)
+ {
+ ClassPathEntry entry1 = classPath1.get(index1);
+
+ for (int index2 = 0; index2 < classPath2.size(); index2++)
+ {
+ if (classPath1 != classPath2 || index1 != index2)
+ {
+ ClassPathEntry entry2 = classPath2.get(index2);
+
+ if (entry2.getName().equals(entry1.getName()))
+ {
+ if (entry1.isOutput())
+ {
+ if (entry2.isOutput())
+ {
+ // Output / output.
+ throw new IOException("The same output jar ["+entry1.getName()+"] is specified twice.");
+ }
+ else
+ {
+ // Output / input.
+ throw new IOException("Input jars and output jars must be different ["+entry1.getName()+"].");
+ }
+ }
+ else
+ {
+ if (entry2.isOutput())
+ {
+ // Input / output.
+ throw new IOException("Input jars and output jars must be different ["+entry1.getName()+"].");
+ }
+ else if (!entry1.isFiltered() ||
+ !entry2.isFiltered())
+ {
+ // Input / input.
+ throw new IOException("The same input jar ["+entry1.getName()+"] is specified twice.");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationConstants.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationConstants.java
new file mode 100644
index 0000000000..ab41e6a4a8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationConstants.java
@@ -0,0 +1,126 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+/**
+ * This class provides constants for parsing and writing ProGuard configurations.
+ *
+ * @author Eric Lafortune
+ */
+class ConfigurationConstants
+{
+ public static final String OPTION_PREFIX = "-";
+ public static final String AT_DIRECTIVE = "@";
+ public static final String INCLUDE_DIRECTIVE = "-include";
+ public static final String BASE_DIRECTORY_DIRECTIVE = "-basedirectory";
+
+ public static final String INJARS_OPTION = "-injars";
+ public static final String OUTJARS_OPTION = "-outjars";
+ public static final String LIBRARYJARS_OPTION = "-libraryjars";
+ public static final String RESOURCEJARS_OPTION = "-resourcejars";
+
+ public static final String KEEP_OPTION = "-keep";
+ public static final String KEEP_CLASS_MEMBERS_OPTION = "-keepclassmembers";
+ public static final String KEEP_CLASSES_WITH_MEMBERS_OPTION = "-keepclasseswithmembers";
+ public static final String KEEP_NAMES_OPTION = "-keepnames";
+ public static final String KEEP_CLASS_MEMBER_NAMES_OPTION = "-keepclassmembernames";
+ public static final String KEEP_CLASSES_WITH_MEMBER_NAMES_OPTION = "-keepclasseswithmembernames";
+ public static final String INCLUDE_DESCRIPTOR_CLASSES_SUBOPTION = "includedescriptorclasses";
+ public static final String ALLOW_SHRINKING_SUBOPTION = "allowshrinking";
+ public static final String ALLOW_OPTIMIZATION_SUBOPTION = "allowoptimization";
+ public static final String ALLOW_OBFUSCATION_SUBOPTION = "allowobfuscation";
+ public static final String PRINT_SEEDS_OPTION = "-printseeds";
+
+ public static final String DONT_SHRINK_OPTION = "-dontshrink";
+ public static final String PRINT_USAGE_OPTION = "-printusage";
+ public static final String WHY_ARE_YOU_KEEPING_OPTION = "-whyareyoukeeping";
+
+ public static final String DONT_OPTIMIZE_OPTION = "-dontoptimize";
+ public static final String OPTIMIZATIONS = "-optimizations";
+ public static final String OPTIMIZATION_PASSES = "-optimizationpasses";
+ public static final String ASSUME_NO_SIDE_EFFECTS_OPTION = "-assumenosideeffects";
+ public static final String ALLOW_ACCESS_MODIFICATION_OPTION = "-allowaccessmodification";
+ public static final String MERGE_INTERFACES_AGGRESSIVELY_OPTION = "-mergeinterfacesaggressively";
+
+ public static final String DONT_OBFUSCATE_OPTION = "-dontobfuscate";
+ public static final String PRINT_MAPPING_OPTION = "-printmapping";
+ public static final String APPLY_MAPPING_OPTION = "-applymapping";
+ public static final String OBFUSCATION_DICTIONARY_OPTION = "-obfuscationdictionary";
+ public static final String CLASS_OBFUSCATION_DICTIONARY_OPTION = "-classobfuscationdictionary";
+ public static final String PACKAGE_OBFUSCATION_DICTIONARY_OPTION = "-packageobfuscationdictionary";
+ public static final String OVERLOAD_AGGRESSIVELY_OPTION = "-overloadaggressively";
+ public static final String USE_UNIQUE_CLASS_MEMBER_NAMES_OPTION = "-useuniqueclassmembernames";
+ public static final String DONT_USE_MIXED_CASE_CLASS_NAMES_OPTION = "-dontusemixedcaseclassnames";
+ public static final String KEEP_PACKAGE_NAMES_OPTION = "-keeppackagenames";
+ public static final String FLATTEN_PACKAGE_HIERARCHY_OPTION = "-flattenpackagehierarchy";
+ public static final String REPACKAGE_CLASSES_OPTION = "-repackageclasses";
+ public static final String DEFAULT_PACKAGE_OPTION = "-defaultpackage";
+ public static final String KEEP_ATTRIBUTES_OPTION = "-keepattributes";
+ public static final String KEEP_PARAMETER_NAMES_OPTION = "-keepparameternames";
+ public static final String RENAME_SOURCE_FILE_ATTRIBUTE_OPTION = "-renamesourcefileattribute";
+ public static final String ADAPT_CLASS_STRINGS_OPTION = "-adaptclassstrings";
+ public static final String ADAPT_RESOURCE_FILE_NAMES_OPTION = "-adaptresourcefilenames";
+ public static final String ADAPT_RESOURCE_FILE_CONTENTS_OPTION = "-adaptresourcefilecontents";
+
+ public static final String DONT_PREVERIFY_OPTION = "-dontpreverify";
+ public static final String MICRO_EDITION_OPTION = "-microedition";
+
+ public static final String VERBOSE_OPTION = "-verbose";
+ public static final String DONT_NOTE_OPTION = "-dontnote";
+ public static final String DONT_WARN_OPTION = "-dontwarn";
+ public static final String IGNORE_WARNINGS_OPTION = "-ignorewarnings";
+ public static final String PRINT_CONFIGURATION_OPTION = "-printconfiguration";
+ public static final String DUMP_OPTION = "-dump";
+ public static final String SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION = "-skipnonpubliclibraryclasses";
+ public static final String DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION = "-dontskipnonpubliclibraryclasses";
+ public static final String DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION = "-dontskipnonpubliclibraryclassmembers";
+ public static final String TARGET_OPTION = "-target";
+ public static final String KEEP_DIRECTORIES_OPTION = "-keepdirectories";
+ public static final String FORCE_PROCESSING_OPTION = "-forceprocessing";
+
+ public static final String ANY_FILE_KEYWORD = "**";
+
+ public static final String ANY_ATTRIBUTE_KEYWORD = "*";
+ public static final String ATTRIBUTE_SEPARATOR_KEYWORD = ",";
+
+ public static final String JAR_SEPARATOR_KEYWORD = System.getProperty("path.separator");
+
+ public static final char OPEN_SYSTEM_PROPERTY = '<';
+ public static final char CLOSE_SYSTEM_PROPERTY = '>';
+
+ public static final String ANNOTATION_KEYWORD = "@";
+ public static final String NEGATOR_KEYWORD = "!";
+ public static final String CLASS_KEYWORD = "class";
+ public static final String ANY_CLASS_KEYWORD = "*";
+ public static final String ANY_TYPE_KEYWORD = "***";
+ public static final String IMPLEMENTS_KEYWORD = "implements";
+ public static final String EXTENDS_KEYWORD = "extends";
+ public static final String OPEN_KEYWORD = "{";
+ public static final String ANY_CLASS_MEMBER_KEYWORD = "*";
+ public static final String ANY_FIELD_KEYWORD = "<fields>";
+ public static final String ANY_METHOD_KEYWORD = "<methods>";
+ public static final String OPEN_ARGUMENTS_KEYWORD = "(";
+ public static final String ARGUMENT_SEPARATOR_KEYWORD = ",";
+ public static final String ANY_ARGUMENTS_KEYWORD = "...";
+ public static final String CLOSE_ARGUMENTS_KEYWORD = ")";
+ public static final String SEPARATOR_KEYWORD = ";";
+ public static final String CLOSE_KEYWORD = "}";
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationParser.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationParser.java
new file mode 100644
index 0000000000..e6a09ba95a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationParser.java
@@ -0,0 +1,1364 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+import proguard.util.ListUtil;
+
+import java.io.*;
+import java.net.URL;
+import java.util.*;
+
+
+/**
+ * This class parses ProGuard configurations. Configurations can be read from an
+ * array of arguments or from a configuration file or URL. External references
+ * in file names ('<...>') can be resolved against a given set of properties.
+ *
+ * @author Eric Lafortune
+ */
+public class ConfigurationParser
+{
+ private final WordReader reader;
+ private final Properties properties;
+
+ private String nextWord;
+ private String lastComments;
+
+
+ /**
+ * Creates a new ConfigurationParser for the given String arguments and
+ * the given Properties.
+ */
+ public ConfigurationParser(String[] args,
+ Properties properties) throws IOException
+ {
+ this(args, null, properties);
+ }
+
+
+ /**
+ * Creates a new ConfigurationParser for the given String arguments,
+ * with the given base directory and the given Properties.
+ */
+ public ConfigurationParser(String[] args,
+ File baseDir,
+ Properties properties) throws IOException
+ {
+ this(new ArgumentWordReader(args, baseDir), properties);
+ }
+
+
+ /**
+ * Creates a new ConfigurationParser for the given lines,
+ * with the given base directory and the given Properties.
+ */
+ public ConfigurationParser(String lines,
+ String description,
+ File baseDir,
+ Properties properties) throws IOException
+ {
+ this(new LineWordReader(new LineNumberReader(new StringReader(lines)),
+ description,
+ baseDir),
+ properties);
+ }
+
+
+ /**
+ * Creates a new ConfigurationParser for the given file, with the system
+ * Properties.
+ * @deprecated Temporary code for backward compatibility in Obclipse.
+ */
+ public ConfigurationParser(File file) throws IOException
+ {
+ this(file, System.getProperties());
+ }
+
+
+ /**
+ * Creates a new ConfigurationParser for the given file and the given
+ * Properties.
+ */
+ public ConfigurationParser(File file,
+ Properties properties) throws IOException
+ {
+ this(new FileWordReader(file), properties);
+ }
+
+
+ /**
+ * Creates a new ConfigurationParser for the given URL and the given
+ * Properties.
+ */
+ public ConfigurationParser(URL url,
+ Properties properties) throws IOException
+ {
+ this(new FileWordReader(url), properties);
+ }
+
+
+ /**
+ * Creates a new ConfigurationParser for the given word reader and the
+ * given Properties.
+ */
+ public ConfigurationParser(WordReader reader,
+ Properties properties) throws IOException
+ {
+ this.reader = reader;
+ this.properties = properties;
+
+ readNextWord();
+ }
+
+
+ /**
+ * Parses and returns the configuration.
+ * @param configuration the configuration that is updated as a side-effect.
+ * @throws ParseException if the any of the configuration settings contains
+ * a syntax error.
+ * @throws IOException if an IO error occurs while reading a configuration.
+ */
+ public void parse(Configuration configuration)
+ throws ParseException, IOException
+ {
+ while (nextWord != null)
+ {
+ lastComments = reader.lastComments();
+
+ // First include directives.
+ if (ConfigurationConstants.AT_DIRECTIVE .startsWith(nextWord) ||
+ ConfigurationConstants.INCLUDE_DIRECTIVE .startsWith(nextWord)) configuration.lastModified = parseIncludeArgument(configuration.lastModified);
+ else if (ConfigurationConstants.BASE_DIRECTORY_DIRECTIVE .startsWith(nextWord)) parseBaseDirectoryArgument();
+
+ // Then configuration options with or without arguments.
+ else if (ConfigurationConstants.INJARS_OPTION .startsWith(nextWord)) configuration.programJars = parseClassPathArgument(configuration.programJars, false);
+ else if (ConfigurationConstants.OUTJARS_OPTION .startsWith(nextWord)) configuration.programJars = parseClassPathArgument(configuration.programJars, true);
+ else if (ConfigurationConstants.LIBRARYJARS_OPTION .startsWith(nextWord)) configuration.libraryJars = parseClassPathArgument(configuration.libraryJars, false);
+ else if (ConfigurationConstants.RESOURCEJARS_OPTION .startsWith(nextWord)) throw new ParseException("The '-resourcejars' option is no longer supported. Please use the '-injars' option for all input");
+ else if (ConfigurationConstants.SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION .startsWith(nextWord)) configuration.skipNonPublicLibraryClasses = parseNoArgument(true);
+ else if (ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION .startsWith(nextWord)) configuration.skipNonPublicLibraryClasses = parseNoArgument(false);
+ else if (ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION.startsWith(nextWord)) configuration.skipNonPublicLibraryClassMembers = parseNoArgument(false);
+ else if (ConfigurationConstants.TARGET_OPTION .startsWith(nextWord)) configuration.targetClassVersion = parseClassVersion();
+ else if (ConfigurationConstants.FORCE_PROCESSING_OPTION .startsWith(nextWord)) configuration.lastModified = parseNoArgument(Long.MAX_VALUE);
+
+ else if (ConfigurationConstants.KEEP_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, true, false, false);
+ else if (ConfigurationConstants.KEEP_CLASS_MEMBERS_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, false, false, false);
+ else if (ConfigurationConstants.KEEP_CLASSES_WITH_MEMBERS_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, false, true, false);
+ else if (ConfigurationConstants.KEEP_NAMES_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, true, false, true);
+ else if (ConfigurationConstants.KEEP_CLASS_MEMBER_NAMES_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, false, false, true);
+ else if (ConfigurationConstants.KEEP_CLASSES_WITH_MEMBER_NAMES_OPTION .startsWith(nextWord)) configuration.keep = parseKeepClassSpecificationArguments(configuration.keep, false, true, true);
+ else if (ConfigurationConstants.PRINT_SEEDS_OPTION .startsWith(nextWord)) configuration.printSeeds = parseOptionalFile();
+
+ // After '-keep'.
+ else if (ConfigurationConstants.KEEP_DIRECTORIES_OPTION .startsWith(nextWord)) configuration.keepDirectories = parseCommaSeparatedList("directory name", true, true, false, true, false, true, false, false, configuration.keepDirectories);
+
+ else if (ConfigurationConstants.DONT_SHRINK_OPTION .startsWith(nextWord)) configuration.shrink = parseNoArgument(false);
+ else if (ConfigurationConstants.PRINT_USAGE_OPTION .startsWith(nextWord)) configuration.printUsage = parseOptionalFile();
+ else if (ConfigurationConstants.WHY_ARE_YOU_KEEPING_OPTION .startsWith(nextWord)) configuration.whyAreYouKeeping = parseClassSpecificationArguments(configuration.whyAreYouKeeping);
+
+ else if (ConfigurationConstants.DONT_OPTIMIZE_OPTION .startsWith(nextWord)) configuration.optimize = parseNoArgument(false);
+ else if (ConfigurationConstants.OPTIMIZATION_PASSES .startsWith(nextWord)) configuration.optimizationPasses = parseIntegerArgument();
+ else if (ConfigurationConstants.OPTIMIZATIONS .startsWith(nextWord)) configuration.optimizations = parseCommaSeparatedList("optimization name", true, false, false, false, false, false, false, false, configuration.optimizations);
+ else if (ConfigurationConstants.ASSUME_NO_SIDE_EFFECTS_OPTION .startsWith(nextWord)) configuration.assumeNoSideEffects = parseClassSpecificationArguments(configuration.assumeNoSideEffects);
+ else if (ConfigurationConstants.ALLOW_ACCESS_MODIFICATION_OPTION .startsWith(nextWord)) configuration.allowAccessModification = parseNoArgument(true);
+ else if (ConfigurationConstants.MERGE_INTERFACES_AGGRESSIVELY_OPTION .startsWith(nextWord)) configuration.mergeInterfacesAggressively = parseNoArgument(true);
+
+ else if (ConfigurationConstants.DONT_OBFUSCATE_OPTION .startsWith(nextWord)) configuration.obfuscate = parseNoArgument(false);
+ else if (ConfigurationConstants.PRINT_MAPPING_OPTION .startsWith(nextWord)) configuration.printMapping = parseOptionalFile();
+ else if (ConfigurationConstants.APPLY_MAPPING_OPTION .startsWith(nextWord)) configuration.applyMapping = parseFile();
+ else if (ConfigurationConstants.OBFUSCATION_DICTIONARY_OPTION .startsWith(nextWord)) configuration.obfuscationDictionary = parseFile();
+ else if (ConfigurationConstants.CLASS_OBFUSCATION_DICTIONARY_OPTION .startsWith(nextWord)) configuration.classObfuscationDictionary = parseFile();
+ else if (ConfigurationConstants.PACKAGE_OBFUSCATION_DICTIONARY_OPTION .startsWith(nextWord)) configuration.packageObfuscationDictionary = parseFile();
+ else if (ConfigurationConstants.OVERLOAD_AGGRESSIVELY_OPTION .startsWith(nextWord)) configuration.overloadAggressively = parseNoArgument(true);
+ else if (ConfigurationConstants.USE_UNIQUE_CLASS_MEMBER_NAMES_OPTION .startsWith(nextWord)) configuration.useUniqueClassMemberNames = parseNoArgument(true);
+ else if (ConfigurationConstants.DONT_USE_MIXED_CASE_CLASS_NAMES_OPTION .startsWith(nextWord)) configuration.useMixedCaseClassNames = parseNoArgument(false);
+ else if (ConfigurationConstants.KEEP_PACKAGE_NAMES_OPTION .startsWith(nextWord)) configuration.keepPackageNames = parseCommaSeparatedList("package name", true, true, false, false, true, false, true, false, configuration.keepPackageNames);
+ else if (ConfigurationConstants.FLATTEN_PACKAGE_HIERARCHY_OPTION .startsWith(nextWord)) configuration.flattenPackageHierarchy = ClassUtil.internalClassName(parseOptionalArgument());
+ else if (ConfigurationConstants.REPACKAGE_CLASSES_OPTION .startsWith(nextWord)) configuration.repackageClasses = ClassUtil.internalClassName(parseOptionalArgument());
+ else if (ConfigurationConstants.DEFAULT_PACKAGE_OPTION .startsWith(nextWord)) configuration.repackageClasses = ClassUtil.internalClassName(parseOptionalArgument());
+ else if (ConfigurationConstants.KEEP_ATTRIBUTES_OPTION .startsWith(nextWord)) configuration.keepAttributes = parseCommaSeparatedList("attribute name", true, true, false, false, true, false, false, false, configuration.keepAttributes);
+ else if (ConfigurationConstants.KEEP_PARAMETER_NAMES_OPTION .startsWith(nextWord)) configuration.keepParameterNames = parseNoArgument(true);
+ else if (ConfigurationConstants.RENAME_SOURCE_FILE_ATTRIBUTE_OPTION .startsWith(nextWord)) configuration.newSourceFileAttribute = parseOptionalArgument();
+ else if (ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION .startsWith(nextWord)) configuration.adaptClassStrings = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.adaptClassStrings);
+ else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION .startsWith(nextWord)) configuration.adaptResourceFileNames = parseCommaSeparatedList("resource file name", true, true, false, true, false, false, false, false, configuration.adaptResourceFileNames);
+ else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_CONTENTS_OPTION .startsWith(nextWord)) configuration.adaptResourceFileContents = parseCommaSeparatedList("resource file name", true, true, false, true, false, false, false, false, configuration.adaptResourceFileContents);
+
+ else if (ConfigurationConstants.DONT_PREVERIFY_OPTION .startsWith(nextWord)) configuration.preverify = parseNoArgument(false);
+ else if (ConfigurationConstants.MICRO_EDITION_OPTION .startsWith(nextWord)) configuration.microEdition = parseNoArgument(true);
+
+ else if (ConfigurationConstants.VERBOSE_OPTION .startsWith(nextWord)) configuration.verbose = parseNoArgument(true);
+ else if (ConfigurationConstants.DONT_NOTE_OPTION .startsWith(nextWord)) configuration.note = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.note);
+ else if (ConfigurationConstants.DONT_WARN_OPTION .startsWith(nextWord)) configuration.warn = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.warn);
+ else if (ConfigurationConstants.IGNORE_WARNINGS_OPTION .startsWith(nextWord)) configuration.ignoreWarnings = parseNoArgument(true);
+ else if (ConfigurationConstants.PRINT_CONFIGURATION_OPTION .startsWith(nextWord)) configuration.printConfiguration = parseOptionalFile();
+ else if (ConfigurationConstants.DUMP_OPTION .startsWith(nextWord)) configuration.dump = parseOptionalFile();
+ else
+ {
+ throw new ParseException("Unknown option " + reader.locationDescription());
+ }
+ }
+ }
+
+
+
+ /**
+ * Closes the configuration.
+ * @throws IOException if an IO error occurs while closing the configuration.
+ */
+ public void close() throws IOException
+ {
+ if (reader != null)
+ {
+ reader.close();
+ }
+ }
+
+
+ private long parseIncludeArgument(long lastModified) throws ParseException, IOException
+ {
+ // Read the configuration file name.
+ readNextWord("configuration file name", true, false);
+
+ File file = file(nextWord);
+ reader.includeWordReader(new FileWordReader(file));
+
+ readNextWord();
+
+ return Math.max(lastModified, file.lastModified());
+ }
+
+
+ private void parseBaseDirectoryArgument() throws ParseException, IOException
+ {
+ // Read the base directory name.
+ readNextWord("base directory name", true, false);
+
+ reader.setBaseDir(file(nextWord));
+
+ readNextWord();
+ }
+
+
+ private ClassPath parseClassPathArgument(ClassPath classPath,
+ boolean isOutput)
+ throws ParseException, IOException
+ {
+ // Create a new List if necessary.
+ if (classPath == null)
+ {
+ classPath = new ClassPath();
+ }
+
+ while (true)
+ {
+ // Read the next jar name.
+ readNextWord("jar or directory name", true, false);
+
+ // Create a new class path entry.
+ ClassPathEntry entry = new ClassPathEntry(file(nextWord), isOutput);
+
+ // Read the opening parenthesis or the separator, if any.
+ readNextWord();
+
+ // Read the optional filters.
+ if (!configurationEnd() &&
+ ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD.equals(nextWord))
+ {
+ // Read all filters in an array.
+ List[] filters = new List[7];
+
+ int counter = 0;
+ do
+ {
+ // Read the filter.
+ filters[counter++] =
+ parseCommaSeparatedList("filter", true, true, true, true, false, true, false, false, null);
+ }
+ while (counter < filters.length &&
+ ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord));
+
+ // Make sure there is a closing parenthesis.
+ if (!ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD.equals(nextWord))
+ {
+ throw new ParseException("Expecting separating '" + ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
+ "' or '" + ConfigurationConstants.SEPARATOR_KEYWORD +
+ "', or closing '" + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD +
+ "' before " + reader.locationDescription());
+ }
+
+ // Set all filters from the array on the entry.
+ entry.setFilter(filters[--counter]);
+ if (counter > 0)
+ {
+ entry.setJarFilter(filters[--counter]);
+ if (counter > 0)
+ {
+ entry.setWarFilter(filters[--counter]);
+ if (counter > 0)
+ {
+ entry.setEarFilter(filters[--counter]);
+ if (counter > 0)
+ {
+ entry.setZipFilter(filters[--counter]);
+ if (counter > 0)
+ {
+ // For backward compatibility, the apk
+ // filter comes second in the list.
+ entry.setApkFilter(filters[--counter]);
+ if (counter > 0)
+ {
+ // For backward compatibility, the aar
+ // filter comes first in the list.
+ entry.setAarFilter(filters[--counter]);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Read the separator, if any.
+ readNextWord();
+ }
+
+ // Add the entry to the list.
+ classPath.add(entry);
+
+ if (configurationEnd())
+ {
+ return classPath;
+ }
+
+ if (!nextWord.equals(ConfigurationConstants.JAR_SEPARATOR_KEYWORD))
+ {
+ throw new ParseException("Expecting class path separator '" + ConfigurationConstants.JAR_SEPARATOR_KEYWORD +
+ "' before " + reader.locationDescription());
+ }
+ }
+ }
+
+
+ private int parseClassVersion()
+ throws ParseException, IOException
+ {
+ // Read the obligatory target.
+ readNextWord("java version");
+
+ int classVersion = ClassUtil.internalClassVersion(nextWord);
+ if (classVersion == 0)
+ {
+ throw new ParseException("Unsupported java version " + reader.locationDescription());
+ }
+
+ readNextWord();
+
+ return classVersion;
+ }
+
+
+ private int parseIntegerArgument()
+ throws ParseException, IOException
+ {
+ try
+ {
+ // Read the obligatory integer.
+ readNextWord("integer");
+
+ int integer = Integer.parseInt(nextWord);
+
+ readNextWord();
+
+ return integer;
+ }
+ catch (NumberFormatException e)
+ {
+ throw new ParseException("Expecting integer argument instead of '" + nextWord +
+ "' before " + reader.locationDescription());
+ }
+ }
+
+
+ private File parseFile()
+ throws ParseException, IOException
+ {
+ // Read the obligatory file name.
+ readNextWord("file name", true, false);
+
+ // Make sure the file is properly resolved.
+ File file = file(nextWord);
+
+ readNextWord();
+
+ return file;
+ }
+
+
+ private File parseOptionalFile()
+ throws ParseException, IOException
+ {
+ // Read the optional file name.
+ readNextWord(true);
+
+ // Didn't the user specify a file name?
+ if (configurationEnd())
+ {
+ return Configuration.STD_OUT;
+ }
+
+ // Make sure the file is properly resolved.
+ File file = file(nextWord);
+
+ readNextWord();
+
+ return file;
+ }
+
+
+ private String parseOptionalArgument() throws IOException
+ {
+ // Read the optional argument.
+ readNextWord();
+
+ // Didn't the user specify an argument?
+ if (configurationEnd())
+ {
+ return "";
+ }
+
+ String argument = nextWord;
+
+ readNextWord();
+
+ return argument;
+ }
+
+
+ private boolean parseNoArgument(boolean value) throws IOException
+ {
+ readNextWord();
+
+ return value;
+ }
+
+
+ private long parseNoArgument(long value) throws IOException
+ {
+ readNextWord();
+
+ return value;
+ }
+
+
+ private List parseKeepClassSpecificationArguments(List keepClassSpecifications,
+ boolean markClasses,
+ boolean markConditionally,
+ boolean allowShrinking)
+ throws ParseException, IOException
+ {
+ // Create a new List if necessary.
+ if (keepClassSpecifications == null)
+ {
+ keepClassSpecifications = new ArrayList();
+ }
+
+ boolean markDescriptorClasses = false;
+ //boolean allowShrinking = false;
+ boolean allowOptimization = false;
+ boolean allowObfuscation = false;
+
+ // Read the keep modifiers.
+ while (true)
+ {
+ readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
+ "', '" + JavaConstants.ACC_INTERFACE +
+ "', or '" + JavaConstants.ACC_ENUM + "'",
+ false, true);
+
+ if (!ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD.equals(nextWord))
+ {
+ // Not a comma. Stop parsing the keep modifiers.
+ break;
+ }
+
+ readNextWord("keyword '" + ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION +
+ "', '" + ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION +
+ "', or '" + ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION + "'");
+
+ if (ConfigurationConstants.INCLUDE_DESCRIPTOR_CLASSES_SUBOPTION.startsWith(nextWord))
+ {
+ markDescriptorClasses = true;
+ }
+ else if (ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION .startsWith(nextWord))
+ {
+ allowShrinking = true;
+ }
+ else if (ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION .startsWith(nextWord))
+ {
+ allowOptimization = true;
+ }
+ else if (ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION .startsWith(nextWord))
+ {
+ allowObfuscation = true;
+ }
+ else
+ {
+ throw new ParseException("Expecting keyword '" + ConfigurationConstants.INCLUDE_DESCRIPTOR_CLASSES_SUBOPTION +
+ "', '" + ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION +
+ "', '" + ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION +
+ "', or '" + ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION +
+ "' before " + reader.locationDescription());
+ }
+ }
+
+ // Read the class configuration.
+ ClassSpecification classSpecification =
+ parseClassSpecificationArguments();
+
+ // Create and add the keep configuration.
+ keepClassSpecifications.add(new KeepClassSpecification(markClasses,
+ markConditionally,
+ markDescriptorClasses,
+ allowShrinking,
+ allowOptimization,
+ allowObfuscation,
+ classSpecification));
+ return keepClassSpecifications;
+ }
+
+
+ private List parseClassSpecificationArguments(List classSpecifications)
+ throws ParseException, IOException
+ {
+ // Create a new List if necessary.
+ if (classSpecifications == null)
+ {
+ classSpecifications = new ArrayList();
+ }
+
+ // Read and add the class configuration.
+ readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
+ "', '" + JavaConstants.ACC_INTERFACE +
+ "', or '" + JavaConstants.ACC_ENUM + "'",
+ false, true);
+
+ classSpecifications.add(parseClassSpecificationArguments());
+
+ return classSpecifications;
+ }
+
+
+ /**
+ * Parses and returns a class specification.
+ * @throws ParseException if the class specification contains a syntax error.
+ * @throws IOException if an IO error occurs while reading the class
+ * specification.
+ */
+ public ClassSpecification parseClassSpecificationArguments()
+ throws ParseException, IOException
+ {
+ // Clear the annotation type.
+ String annotationType = null;
+
+ // Clear the class access modifiers.
+ int requiredSetClassAccessFlags = 0;
+ int requiredUnsetClassAccessFlags = 0;
+
+ // Parse the class annotations and access modifiers until the class keyword.
+ while (!ConfigurationConstants.CLASS_KEYWORD.equals(nextWord))
+ {
+ // Strip the negating sign, if any.
+ boolean negated =
+ nextWord.startsWith(ConfigurationConstants.NEGATOR_KEYWORD);
+
+ String strippedWord = negated ?
+ nextWord.substring(1) :
+ nextWord;
+
+ // Parse the class access modifiers.
+ int accessFlag =
+ strippedWord.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC :
+ strippedWord.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL :
+ strippedWord.equals(JavaConstants.ACC_INTERFACE) ? ClassConstants.ACC_INTERFACE :
+ strippedWord.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT :
+ strippedWord.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC :
+ strippedWord.equals(JavaConstants.ACC_ANNOTATION) ? ClassConstants.ACC_ANNOTATTION :
+ strippedWord.equals(JavaConstants.ACC_ENUM) ? ClassConstants.ACC_ENUM :
+ unknownAccessFlag();
+
+ // Is it an annotation modifier?
+ if (accessFlag == ClassConstants.ACC_ANNOTATTION)
+ {
+ // Already read the next word.
+ readNextWord("annotation type or keyword '" + JavaConstants.ACC_INTERFACE + "'",
+ false, false);
+
+ // Is the next word actually an annotation type?
+ if (!nextWord.equals(JavaConstants.ACC_INTERFACE) &&
+ !nextWord.equals(JavaConstants.ACC_ENUM) &&
+ !nextWord.equals(ConfigurationConstants.CLASS_KEYWORD))
+ {
+ // Parse the annotation type.
+ annotationType =
+ ListUtil.commaSeparatedString(
+ parseCommaSeparatedList("annotation type",
+ false, false, false, false, true, false, false, true, null), false);
+
+ // Continue parsing the access modifier that we just read
+ // in the next cycle.
+ continue;
+ }
+
+ // Otherwise just handle the annotation modifier.
+ }
+
+ if (!negated)
+ {
+ requiredSetClassAccessFlags |= accessFlag;
+ }
+ else
+ {
+ requiredUnsetClassAccessFlags |= accessFlag;
+ }
+
+ if ((requiredSetClassAccessFlags &
+ requiredUnsetClassAccessFlags) != 0)
+ {
+ throw new ParseException("Conflicting class access modifiers for '" + strippedWord +
+ "' before " + reader.locationDescription());
+ }
+
+ if (strippedWord.equals(JavaConstants.ACC_INTERFACE) ||
+ strippedWord.equals(JavaConstants.ACC_ENUM) ||
+ strippedWord.equals(ConfigurationConstants.CLASS_KEYWORD))
+ {
+ // The interface or enum keyword. Stop parsing the class flags.
+ break;
+ }
+
+ // Should we read the next word?
+ if (accessFlag != ClassConstants.ACC_ANNOTATTION)
+ {
+ readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
+ "', '" + JavaConstants.ACC_INTERFACE +
+ "', or '" + JavaConstants.ACC_ENUM + "'",
+ false, true);
+ }
+ }
+
+ // Parse the class name part.
+ String externalClassName =
+ ListUtil.commaSeparatedString(
+ parseCommaSeparatedList("class name or interface name",
+ true, false, false, false, true, false, false, false, null), false);
+
+ // For backward compatibility, allow a single "*" wildcard to match any
+ // class.
+ String className = ConfigurationConstants.ANY_CLASS_KEYWORD.equals(externalClassName) ?
+ null :
+ ClassUtil.internalClassName(externalClassName);
+
+ // Clear the annotation type and the class name of the extends part.
+ String extendsAnnotationType = null;
+ String extendsClassName = null;
+
+ if (!configurationEnd())
+ {
+ // Parse 'implements ...' or 'extends ...' part, if any.
+ if (ConfigurationConstants.IMPLEMENTS_KEYWORD.equals(nextWord) ||
+ ConfigurationConstants.EXTENDS_KEYWORD.equals(nextWord))
+ {
+ readNextWord("class name or interface name", false, true);
+
+ // Parse the annotation type, if any.
+ if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
+ {
+ extendsAnnotationType =
+ ListUtil.commaSeparatedString(
+ parseCommaSeparatedList("annotation type",
+ true, false, false, false, true, false, false, true, null), false);
+ }
+
+ String externalExtendsClassName =
+ ListUtil.commaSeparatedString(
+ parseCommaSeparatedList("class name or interface name",
+ false, false, false, false, true, false, false, false, null), false);
+
+ extendsClassName = ConfigurationConstants.ANY_CLASS_KEYWORD.equals(externalExtendsClassName) ?
+ null :
+ ClassUtil.internalClassName(externalExtendsClassName);
+ }
+ }
+
+ // Create the basic class specification.
+ ClassSpecification classSpecification =
+ new ClassSpecification(lastComments,
+ requiredSetClassAccessFlags,
+ requiredUnsetClassAccessFlags,
+ annotationType,
+ className,
+ extendsAnnotationType,
+ extendsClassName);
+
+
+ // Now add any class members to this class specification.
+ if (!configurationEnd())
+ {
+ // Check the class member opening part.
+ if (!ConfigurationConstants.OPEN_KEYWORD.equals(nextWord))
+ {
+ throw new ParseException("Expecting opening '" + ConfigurationConstants.OPEN_KEYWORD +
+ "' at " + reader.locationDescription());
+ }
+
+ // Parse all class members.
+ while (true)
+ {
+ readNextWord("class member description" +
+ " or closing '" + ConfigurationConstants.CLOSE_KEYWORD + "'",
+ false, true);
+
+ if (nextWord.equals(ConfigurationConstants.CLOSE_KEYWORD))
+ {
+ // The closing brace. Stop parsing the class members.
+ readNextWord();
+
+ break;
+ }
+
+ parseMemberSpecificationArguments(externalClassName,
+ classSpecification);
+ }
+ }
+
+ return classSpecification;
+ }
+
+
+ private void parseMemberSpecificationArguments(String externalClassName,
+ ClassSpecification classSpecification)
+ throws ParseException, IOException
+ {
+ // Clear the annotation name.
+ String annotationType = null;
+
+ // Parse the class member access modifiers, if any.
+ int requiredSetMemberAccessFlags = 0;
+ int requiredUnsetMemberAccessFlags = 0;
+
+ while (!configurationEnd(true))
+ {
+ // Parse the annotation type, if any.
+ if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
+ {
+ annotationType =
+ ListUtil.commaSeparatedString(
+ parseCommaSeparatedList("annotation type",
+ true, false, false, false, true, false, false, true, null), false);
+ continue;
+ }
+
+ String strippedWord = nextWord.startsWith("!") ?
+ nextWord.substring(1) :
+ nextWord;
+
+ // Parse the class member access modifiers.
+ int accessFlag =
+ strippedWord.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC :
+ strippedWord.equals(JavaConstants.ACC_PRIVATE) ? ClassConstants.ACC_PRIVATE :
+ strippedWord.equals(JavaConstants.ACC_PROTECTED) ? ClassConstants.ACC_PROTECTED :
+ strippedWord.equals(JavaConstants.ACC_STATIC) ? ClassConstants.ACC_STATIC :
+ strippedWord.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL :
+ strippedWord.equals(JavaConstants.ACC_SYNCHRONIZED) ? ClassConstants.ACC_SYNCHRONIZED :
+ strippedWord.equals(JavaConstants.ACC_VOLATILE) ? ClassConstants.ACC_VOLATILE :
+ strippedWord.equals(JavaConstants.ACC_TRANSIENT) ? ClassConstants.ACC_TRANSIENT :
+ strippedWord.equals(JavaConstants.ACC_BRIDGE) ? ClassConstants.ACC_BRIDGE :
+ strippedWord.equals(JavaConstants.ACC_VARARGS) ? ClassConstants.ACC_VARARGS :
+ strippedWord.equals(JavaConstants.ACC_NATIVE) ? ClassConstants.ACC_NATIVE :
+ strippedWord.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT :
+ strippedWord.equals(JavaConstants.ACC_STRICT) ? ClassConstants.ACC_STRICT :
+ strippedWord.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC :
+ 0;
+ if (accessFlag == 0)
+ {
+ // Not a class member access modifier. Stop parsing them.
+ break;
+ }
+
+ if (strippedWord.equals(nextWord))
+ {
+ requiredSetMemberAccessFlags |= accessFlag;
+ }
+ else
+ {
+ requiredUnsetMemberAccessFlags |= accessFlag;
+ }
+
+ // Make sure the user doesn't try to set and unset the same
+ // access flags simultaneously.
+ if ((requiredSetMemberAccessFlags &
+ requiredUnsetMemberAccessFlags) != 0)
+ {
+ throw new ParseException("Conflicting class member access modifiers for " +
+ reader.locationDescription());
+ }
+
+ readNextWord("class member description");
+ }
+
+ // Parse the class member type and name part.
+
+ // Did we get a special wildcard?
+ if (ConfigurationConstants.ANY_CLASS_MEMBER_KEYWORD.equals(nextWord) ||
+ ConfigurationConstants.ANY_FIELD_KEYWORD .equals(nextWord) ||
+ ConfigurationConstants.ANY_METHOD_KEYWORD .equals(nextWord))
+ {
+ // Act according to the type of wildcard..
+ if (ConfigurationConstants.ANY_CLASS_MEMBER_KEYWORD.equals(nextWord))
+ {
+ checkFieldAccessFlags(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags);
+ checkMethodAccessFlags(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags);
+
+ classSpecification.addField(
+ new MemberSpecification(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags,
+ annotationType,
+ null,
+ null));
+ classSpecification.addMethod(
+ new MemberSpecification(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags,
+ annotationType,
+ null,
+ null));
+ }
+ else if (ConfigurationConstants.ANY_FIELD_KEYWORD.equals(nextWord))
+ {
+ checkFieldAccessFlags(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags);
+
+ classSpecification.addField(
+ new MemberSpecification(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags,
+ annotationType,
+ null,
+ null));
+ }
+ else if (ConfigurationConstants.ANY_METHOD_KEYWORD.equals(nextWord))
+ {
+ checkMethodAccessFlags(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags);
+
+ classSpecification.addMethod(
+ new MemberSpecification(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags,
+ annotationType,
+ null,
+ null));
+ }
+
+ // We still have to read the closing separator.
+ readNextWord("separator '" + ConfigurationConstants.SEPARATOR_KEYWORD + "'");
+
+ if (!ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord))
+ {
+ throw new ParseException("Expecting separator '" + ConfigurationConstants.SEPARATOR_KEYWORD +
+ "' before " + reader.locationDescription());
+ }
+ }
+ else
+ {
+ // Make sure we have a proper type.
+ checkJavaIdentifier("java type");
+ String type = nextWord;
+
+ readNextWord("class member name");
+ String name = nextWord;
+
+ // Did we get just one word before the opening parenthesis?
+ if (ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD.equals(name))
+ {
+ // This must be a constructor then.
+ // Make sure the type is a proper constructor name.
+ if (!(type.equals(ClassConstants.METHOD_NAME_INIT) ||
+ type.equals(externalClassName) ||
+ type.equals(ClassUtil.externalShortClassName(externalClassName))))
+ {
+ throw new ParseException("Expecting type and name " +
+ "instead of just '" + type +
+ "' before " + reader.locationDescription());
+ }
+
+ // Assign the fixed constructor type and name.
+ type = JavaConstants.TYPE_VOID;
+ name = ClassConstants.METHOD_NAME_INIT;
+ }
+ else
+ {
+ // It's not a constructor.
+ // Make sure we have a proper name.
+ checkJavaIdentifier("class member name");
+
+ // Read the opening parenthesis or the separating
+ // semi-colon.
+ readNextWord("opening '" + ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD +
+ "' or separator '" + ConfigurationConstants.SEPARATOR_KEYWORD + "'");
+ }
+
+ // Are we looking at a field, a method, or something else?
+ if (ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord))
+ {
+ // It's a field.
+ checkFieldAccessFlags(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags);
+
+ // We already have a field descriptor.
+ String descriptor = ClassUtil.internalType(type);
+
+ // Add the field.
+ classSpecification.addField(
+ new MemberSpecification(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags,
+ annotationType,
+ name,
+ descriptor));
+ }
+ else if (ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD.equals(nextWord))
+ {
+ // It's a method.
+ checkMethodAccessFlags(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags);
+
+ // Parse the method arguments.
+ String descriptor =
+ ClassUtil.internalMethodDescriptor(type,
+ parseCommaSeparatedList("argument", true, true, true, false, true, false, false, false, null));
+
+ if (!ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD.equals(nextWord))
+ {
+ throw new ParseException("Expecting separating '" + ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
+ "' or closing '" + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD +
+ "' before " + reader.locationDescription());
+ }
+
+ // Read the separator after the closing parenthesis.
+ readNextWord("separator '" + ConfigurationConstants.SEPARATOR_KEYWORD + "'");
+
+ if (!ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord))
+ {
+ throw new ParseException("Expecting separator '" + ConfigurationConstants.SEPARATOR_KEYWORD +
+ "' before " + reader.locationDescription());
+ }
+
+ // Add the method.
+ classSpecification.addMethod(
+ new MemberSpecification(requiredSetMemberAccessFlags,
+ requiredUnsetMemberAccessFlags,
+ annotationType,
+ name,
+ descriptor));
+ }
+ else
+ {
+ // It doesn't look like a field or a method.
+ throw new ParseException("Expecting opening '" + ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD +
+ "' or separator '" + ConfigurationConstants.SEPARATOR_KEYWORD +
+ "' before " + reader.locationDescription());
+ }
+ }
+ }
+
+
+ /**
+ * Reads a comma-separated list of java identifiers or of file names.
+ * Examples of invocation arguments:
+ * ("directory name", true, true, false, true, false, true, false, false, ...)
+ * ("optimization", true, false, false, false, false, false, false, false, ...)
+ * ("package name", true, true, false, false, true, false, true, false, ...)
+ * ("attribute name", true, true, false, false, true, false, false, false, ...)
+ * ("class name", true, true, false, false, true, false, true, false, ...)
+ * ("resource file", true, true, false, true, false, false, false, false, ...)
+ * ("resource file", true, true, false, true, false, false, false, false, ...)
+ * ("class name", true, true, false, false, true, false, true, false, ...)
+ * ("class name", true, true, false, false, true, false, true, false, ...)
+ * ("filter", true, true, true, true, false, true, false, false, ...)
+ * ("annotation ", false, false, false, false, true, false, false, true, ...)
+ * ("class name ", true, false, false, false, true, false, false, false, ...)
+ * ("annotation ", true, false, false, false, true, false, false, true, ...)
+ * ("class name ", false, false, false, false, true, false, false, false, ...)
+ * ("annotation ", true, false, false, false, true, false, false, true, ...)
+ * ("argument", true, true, true, false, true, false, false, false, ...)
+ */
+ private List parseCommaSeparatedList(String expectedDescription,
+ boolean readFirstWord,
+ boolean allowEmptyList,
+ boolean expectClosingParenthesis,
+ boolean isFileName,
+ boolean checkJavaIdentifiers,
+ boolean replaceSystemProperties,
+ boolean replaceExternalClassNames,
+ boolean replaceExternalTypes,
+ List list)
+ throws ParseException, IOException
+ {
+ if (list == null)
+ {
+ list = new ArrayList();
+ }
+
+ if (readFirstWord)
+ {
+ if (!allowEmptyList)
+ {
+ // Read the first list entry.
+ readNextWord(expectedDescription, isFileName, false);
+ }
+ else if (expectClosingParenthesis)
+ {
+ // Read the first list entry.
+ readNextWord(expectedDescription, isFileName, false);
+
+ // Return if the entry is actually empty (an empty file name or
+ // a closing parenthesis).
+ if (nextWord.length() == 0)
+ {
+ // Read the closing parenthesis
+ readNextWord("closing '" + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD +
+ "'");
+
+ return list;
+ }
+ else if (nextWord.equals(ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD))
+ {
+ return list;
+ }
+ }
+ else
+ {
+ // Read the first list entry, if there is any.
+ readNextWord(isFileName);
+
+ // Check if the list is empty.
+ if (configurationEnd())
+ {
+ return list;
+ }
+ }
+ }
+
+ while (true)
+ {
+ if (checkJavaIdentifiers)
+ {
+ checkJavaIdentifier("java type");
+ }
+
+ if (replaceSystemProperties)
+ {
+ nextWord = replaceSystemProperties(nextWord);
+ }
+
+ if (replaceExternalClassNames)
+ {
+ nextWord = ClassUtil.internalClassName(nextWord);
+ }
+
+ if (replaceExternalTypes)
+ {
+ nextWord = ClassUtil.internalType(nextWord);
+ }
+
+ list.add(nextWord);
+
+ if (expectClosingParenthesis)
+ {
+ // Read a comma (or a closing parenthesis, or a different word).
+ readNextWord("separating '" + ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
+ "' or closing '" + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD +
+ "'");
+ }
+ else
+ {
+ // Read a comma (or a different word).
+ readNextWord();
+ }
+
+ if (!ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD.equals(nextWord))
+ {
+ return list;
+ }
+
+ // Read the next list entry.
+ readNextWord(expectedDescription, isFileName, false);
+ }
+ }
+
+
+ /**
+ * Throws a ParseException for an unexpected keyword.
+ */
+ private int unknownAccessFlag() throws ParseException
+ {
+ throw new ParseException("Unexpected keyword " + reader.locationDescription());
+ }
+
+
+ /**
+ * Creates a properly resolved File, based on the given word.
+ */
+ private File file(String word) throws ParseException
+ {
+ String fileName = replaceSystemProperties(word);
+ File file = new File(fileName);
+
+ // Try to get an absolute file.
+ if (!file.isAbsolute())
+ {
+ file = new File(reader.getBaseDir(), fileName);
+ }
+
+ return file;
+ }
+
+
+ /**
+ * Replaces any properties in the given word by their values.
+ * For instance, the substring "<java.home>" is replaced by its value.
+ */
+ private String replaceSystemProperties(String word) throws ParseException
+ {
+ int fromIndex = 0;
+ while (true)
+ {
+ fromIndex = word.indexOf(ConfigurationConstants.OPEN_SYSTEM_PROPERTY, fromIndex);
+ if (fromIndex < 0)
+ {
+ break;
+ }
+
+ int toIndex = word.indexOf(ConfigurationConstants.CLOSE_SYSTEM_PROPERTY, fromIndex+1);
+ if (toIndex < 0)
+ {
+ break;
+ }
+
+ String propertyName = word.substring(fromIndex+1, toIndex);
+ String propertyValue = properties.getProperty(propertyName);
+ if (propertyValue == null)
+ {
+ throw new ParseException("Value of system property '" + propertyName +
+ "' is undefined in " + reader.locationDescription());
+ }
+
+ word = word.substring(0, fromIndex) + propertyValue + word.substring(toIndex+1);
+
+ fromIndex += propertyValue.length();
+ }
+
+ return word;
+ }
+
+
+ /**
+ * Reads the next word of the configuration in the 'nextWord' field,
+ * throwing an exception if there is no next word.
+ */
+ private void readNextWord(String expectedDescription)
+ throws ParseException, IOException
+ {
+ readNextWord(expectedDescription, false, false);
+ }
+
+
+ /**
+ * Reads the next word of the configuration in the 'nextWord' field,
+ * throwing an exception if there is no next word.
+ */
+ private void readNextWord(String expectedDescription,
+ boolean isFileName,
+ boolean expectingAtCharacter)
+ throws ParseException, IOException
+ {
+ readNextWord(isFileName);
+ if (configurationEnd(expectingAtCharacter))
+ {
+ throw new ParseException("Expecting " + expectedDescription +
+ " before " + reader.locationDescription());
+ }
+ }
+
+
+ /**
+ * Reads the next word of the configuration in the 'nextWord' field.
+ */
+ private void readNextWord() throws IOException
+ {
+ readNextWord(false);
+ }
+
+
+ /**
+ * Reads the next word of the configuration in the 'nextWord' field.
+ */
+ private void readNextWord(boolean isFileName) throws IOException
+ {
+ nextWord = reader.nextWord(isFileName);
+ }
+
+
+ /**
+ * Returns whether the end of the configuration has been reached.
+ */
+ private boolean configurationEnd()
+ {
+ return configurationEnd(false);
+ }
+
+
+ /**
+ * Returns whether the end of the configuration has been reached.
+ */
+ private boolean configurationEnd(boolean expectingAtCharacter)
+ {
+ return nextWord == null ||
+ nextWord.startsWith(ConfigurationConstants.OPTION_PREFIX) ||
+ (!expectingAtCharacter &&
+ nextWord.equals(ConfigurationConstants.AT_DIRECTIVE));
+ }
+
+
+ /**
+ * Checks whether the given word is a valid Java identifier and throws
+ * a ParseException if it isn't. Wildcard characters are accepted.
+ */
+ private void checkJavaIdentifier(String expectedDescription)
+ throws ParseException
+ {
+ if (!isJavaIdentifier(nextWord))
+ {
+ throw new ParseException("Expecting " + expectedDescription +
+ " before " + reader.locationDescription());
+ }
+ }
+
+
+ /**
+ * Returns whether the given word is a valid Java identifier.
+ * Wildcard characters are accepted.
+ */
+ private boolean isJavaIdentifier(String aWord)
+ {
+ if (aWord.length() == 0)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < aWord.length(); index++)
+ {
+ char c = aWord.charAt(index);
+ if (!(Character.isJavaIdentifierPart(c) ||
+ c == '.' ||
+ c == '[' ||
+ c == ']' ||
+ c == '<' ||
+ c == '>' ||
+ c == '-' ||
+ c == '!' ||
+ c == '*' ||
+ c == '?' ||
+ c == '%'))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Checks whether the given access flags are valid field access flags,
+ * throwing a ParseException if they aren't.
+ */
+ private void checkFieldAccessFlags(int requiredSetMemberAccessFlags,
+ int requiredUnsetMemberAccessFlags)
+ throws ParseException
+ {
+ if (((requiredSetMemberAccessFlags |
+ requiredUnsetMemberAccessFlags) &
+ ~ClassConstants.VALID_ACC_FIELD) != 0)
+ {
+ throw new ParseException("Invalid method access modifier for field before " +
+ reader.locationDescription());
+ }
+ }
+
+
+ /**
+ * Checks whether the given access flags are valid method access flags,
+ * throwing a ParseException if they aren't.
+ */
+ private void checkMethodAccessFlags(int requiredSetMemberAccessFlags,
+ int requiredUnsetMemberAccessFlags)
+ throws ParseException
+ {
+ if (((requiredSetMemberAccessFlags |
+ requiredUnsetMemberAccessFlags) &
+ ~ClassConstants.VALID_ACC_METHOD) != 0)
+ {
+ throw new ParseException("Invalid field access modifier for method before " +
+ reader.locationDescription());
+ }
+ }
+
+
+ /**
+ * A main method for testing configuration parsing.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ ConfigurationParser parser =
+ new ConfigurationParser(args, System.getProperties());
+
+ try
+ {
+ parser.parse(new Configuration());
+ }
+ catch (ParseException ex)
+ {
+ ex.printStackTrace();
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ catch (IOException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationWriter.java
new file mode 100644
index 0000000000..648f639aa4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ConfigurationWriter.java
@@ -0,0 +1,661 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.ClassConstants;
+import proguard.classfile.util.ClassUtil;
+import proguard.util.ListUtil;
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * This class writes ProGuard configurations to a file.
+ *
+ * @author Eric Lafortune
+ */
+public class ConfigurationWriter
+{
+ private static final String[] KEEP_OPTIONS = new String[]
+ {
+ ConfigurationConstants.KEEP_OPTION,
+ ConfigurationConstants.KEEP_CLASS_MEMBERS_OPTION,
+ ConfigurationConstants.KEEP_CLASSES_WITH_MEMBERS_OPTION
+ };
+
+
+ private final PrintWriter writer;
+ private File baseDir;
+
+
+ /**
+ * Creates a new ConfigurationWriter for the given file name.
+ */
+ public ConfigurationWriter(File configurationFile) throws IOException
+ {
+ this(new PrintWriter(new FileWriter(configurationFile)));
+
+ baseDir = configurationFile.getParentFile();
+ }
+
+
+ /**
+ * Creates a new ConfigurationWriter for the given OutputStream.
+ */
+ public ConfigurationWriter(OutputStream outputStream) throws IOException
+ {
+ this(new PrintWriter(outputStream));
+ }
+
+
+ /**
+ * Creates a new ConfigurationWriter for the given PrintWriter.
+ */
+ public ConfigurationWriter(PrintWriter writer) throws IOException
+ {
+ this.writer = writer;
+ }
+
+
+ /**
+ * Closes this ConfigurationWriter.
+ */
+ public void close() throws IOException
+ {
+ writer.close();
+ }
+
+
+ /**
+ * Writes the given configuration.
+ * @param configuration the configuration that is to be written out.
+ * @throws IOException if an IO error occurs while writing the configuration.
+ */
+ public void write(Configuration configuration) throws IOException
+ {
+ // Write the program class path (input and output entries).
+ writeJarOptions(ConfigurationConstants.INJARS_OPTION,
+ ConfigurationConstants.OUTJARS_OPTION,
+ configuration.programJars);
+ writer.println();
+
+ // Write the library class path (output entries only).
+ writeJarOptions(ConfigurationConstants.LIBRARYJARS_OPTION,
+ ConfigurationConstants.LIBRARYJARS_OPTION,
+ configuration.libraryJars);
+ writer.println();
+
+ // Write the other options.
+ writeOption(ConfigurationConstants.SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION, configuration.skipNonPublicLibraryClasses);
+ writeOption(ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION, !configuration.skipNonPublicLibraryClassMembers);
+ writeOption(ConfigurationConstants.KEEP_DIRECTORIES_OPTION, configuration.keepDirectories);
+ writeOption(ConfigurationConstants.TARGET_OPTION, ClassUtil.externalClassVersion(configuration.targetClassVersion));
+ writeOption(ConfigurationConstants.FORCE_PROCESSING_OPTION, configuration.lastModified == Long.MAX_VALUE);
+
+ writeOption(ConfigurationConstants.DONT_SHRINK_OPTION, !configuration.shrink);
+ writeOption(ConfigurationConstants.PRINT_USAGE_OPTION, configuration.printUsage);
+
+ writeOption(ConfigurationConstants.DONT_OPTIMIZE_OPTION, !configuration.optimize);
+ writeOption(ConfigurationConstants.OPTIMIZATIONS, configuration.optimizations);
+ writeOption(ConfigurationConstants.OPTIMIZATION_PASSES, configuration.optimizationPasses);
+ writeOption(ConfigurationConstants.ALLOW_ACCESS_MODIFICATION_OPTION, configuration.allowAccessModification);
+ writeOption(ConfigurationConstants.MERGE_INTERFACES_AGGRESSIVELY_OPTION, configuration.mergeInterfacesAggressively);
+
+ writeOption(ConfigurationConstants.DONT_OBFUSCATE_OPTION, !configuration.obfuscate);
+ writeOption(ConfigurationConstants.PRINT_MAPPING_OPTION, configuration.printMapping);
+ writeOption(ConfigurationConstants.APPLY_MAPPING_OPTION, configuration.applyMapping);
+ writeOption(ConfigurationConstants.OBFUSCATION_DICTIONARY_OPTION, configuration.obfuscationDictionary);
+ writeOption(ConfigurationConstants.CLASS_OBFUSCATION_DICTIONARY_OPTION, configuration.classObfuscationDictionary);
+ writeOption(ConfigurationConstants.PACKAGE_OBFUSCATION_DICTIONARY_OPTION, configuration.packageObfuscationDictionary);
+ writeOption(ConfigurationConstants.OVERLOAD_AGGRESSIVELY_OPTION, configuration.overloadAggressively);
+ writeOption(ConfigurationConstants.USE_UNIQUE_CLASS_MEMBER_NAMES_OPTION, configuration.useUniqueClassMemberNames);
+ writeOption(ConfigurationConstants.DONT_USE_MIXED_CASE_CLASS_NAMES_OPTION, !configuration.useMixedCaseClassNames);
+ writeOption(ConfigurationConstants.KEEP_PACKAGE_NAMES_OPTION, configuration.keepPackageNames, true);
+ writeOption(ConfigurationConstants.FLATTEN_PACKAGE_HIERARCHY_OPTION, configuration.flattenPackageHierarchy, true);
+ writeOption(ConfigurationConstants.REPACKAGE_CLASSES_OPTION, configuration.repackageClasses, true);
+ writeOption(ConfigurationConstants.KEEP_ATTRIBUTES_OPTION, configuration.keepAttributes);
+ writeOption(ConfigurationConstants.KEEP_PARAMETER_NAMES_OPTION, configuration.keepParameterNames);
+ writeOption(ConfigurationConstants.RENAME_SOURCE_FILE_ATTRIBUTE_OPTION, configuration.newSourceFileAttribute);
+ writeOption(ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION, configuration.adaptClassStrings, true);
+ writeOption(ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION, configuration.adaptResourceFileNames);
+ writeOption(ConfigurationConstants.ADAPT_RESOURCE_FILE_CONTENTS_OPTION, configuration.adaptResourceFileContents);
+
+ writeOption(ConfigurationConstants.DONT_PREVERIFY_OPTION, !configuration.preverify);
+ writeOption(ConfigurationConstants.MICRO_EDITION_OPTION, configuration.microEdition);
+
+ writeOption(ConfigurationConstants.VERBOSE_OPTION, configuration.verbose);
+ writeOption(ConfigurationConstants.DONT_NOTE_OPTION, configuration.note, true);
+ writeOption(ConfigurationConstants.DONT_WARN_OPTION, configuration.warn, true);
+ writeOption(ConfigurationConstants.IGNORE_WARNINGS_OPTION, configuration.ignoreWarnings);
+ writeOption(ConfigurationConstants.PRINT_CONFIGURATION_OPTION, configuration.printConfiguration);
+ writeOption(ConfigurationConstants.DUMP_OPTION, configuration.dump);
+
+ writeOption(ConfigurationConstants.PRINT_SEEDS_OPTION, configuration.printSeeds);
+ writer.println();
+
+ // Write the "why are you keeping" options.
+ writeOptions(ConfigurationConstants.WHY_ARE_YOU_KEEPING_OPTION, configuration.whyAreYouKeeping);
+
+ // Write the keep options.
+ writeOptions(KEEP_OPTIONS, configuration.keep);
+
+ // Write the "no side effect methods" options.
+ writeOptions(ConfigurationConstants.ASSUME_NO_SIDE_EFFECTS_OPTION, configuration.assumeNoSideEffects);
+
+ if (writer.checkError())
+ {
+ throw new IOException("Can't write configuration");
+ }
+ }
+
+
+ private void writeJarOptions(String inputEntryOptionName,
+ String outputEntryOptionName,
+ ClassPath classPath)
+ {
+ if (classPath != null)
+ {
+ for (int index = 0; index < classPath.size(); index++)
+ {
+ ClassPathEntry entry = classPath.get(index);
+ String optionName = entry.isOutput() ?
+ outputEntryOptionName :
+ inputEntryOptionName;
+
+ writer.print(optionName);
+ writer.print(' ');
+ writer.print(relativeFileName(entry.getFile()));
+
+ // Append the filters, if any.
+ boolean filtered = false;
+
+ // For backward compatibility, the aar and apk filters come
+ // first.
+ filtered = writeFilter(filtered, entry.getAarFilter());
+ filtered = writeFilter(filtered, entry.getApkFilter());
+ filtered = writeFilter(filtered, entry.getZipFilter());
+ filtered = writeFilter(filtered, entry.getEarFilter());
+ filtered = writeFilter(filtered, entry.getWarFilter());
+ filtered = writeFilter(filtered, entry.getJarFilter());
+ filtered = writeFilter(filtered, entry.getFilter());
+
+ if (filtered)
+ {
+ writer.print(ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD);
+ }
+
+ writer.println();
+ }
+ }
+ }
+
+
+ private boolean writeFilter(boolean filtered, List filter)
+ {
+ if (filtered)
+ {
+ writer.print(ConfigurationConstants.SEPARATOR_KEYWORD);
+ }
+
+ if (filter != null)
+ {
+ if (!filtered)
+ {
+ writer.print(ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD);
+ }
+
+ writer.print(ListUtil.commaSeparatedString(filter, true));
+
+ filtered = true;
+ }
+
+ return filtered;
+ }
+
+
+ private void writeOption(String optionName, boolean flag)
+ {
+ if (flag)
+ {
+ writer.println(optionName);
+ }
+ }
+
+
+ private void writeOption(String optionName, int argument)
+ {
+ if (argument != 1)
+ {
+ writer.print(optionName);
+ writer.print(' ');
+ writer.println(argument);
+ }
+ }
+
+
+ private void writeOption(String optionName, List arguments)
+ {
+ writeOption(optionName, arguments, false);
+ }
+
+
+ private void writeOption(String optionName,
+ List arguments,
+ boolean replaceInternalClassNames)
+ {
+ if (arguments != null)
+ {
+ if (arguments.isEmpty())
+ {
+ writer.println(optionName);
+ }
+ else
+ {
+ if (replaceInternalClassNames)
+ {
+ arguments = externalClassNames(arguments);
+ }
+
+ writer.print(optionName);
+ writer.print(' ');
+ writer.println(ListUtil.commaSeparatedString(arguments, true));
+ }
+ }
+ }
+
+
+ private void writeOption(String optionName, String arguments)
+ {
+ writeOption(optionName, arguments, false);
+ }
+
+
+ private void writeOption(String optionName,
+ String arguments,
+ boolean replaceInternalClassNames)
+ {
+ if (arguments != null)
+ {
+ if (replaceInternalClassNames)
+ {
+ arguments = ClassUtil.externalClassName(arguments);
+ }
+
+ writer.print(optionName);
+ writer.print(' ');
+ writer.println(quotedString(arguments));
+ }
+ }
+
+
+ private void writeOption(String optionName, File file)
+ {
+ if (file != null)
+ {
+ if (file.getPath().length() > 0)
+ {
+ writer.print(optionName);
+ writer.print(' ');
+ writer.println(relativeFileName(file));
+ }
+ else
+ {
+ writer.println(optionName);
+ }
+ }
+ }
+
+
+ private void writeOptions(String[] optionNames,
+ List keepClassSpecifications)
+ {
+ if (keepClassSpecifications != null)
+ {
+ for (int index = 0; index < keepClassSpecifications.size(); index++)
+ {
+ writeOption(optionNames, (KeepClassSpecification)keepClassSpecifications.get(index));
+ }
+ }
+ }
+
+
+ private void writeOption(String[] optionNames,
+ KeepClassSpecification keepClassSpecification)
+ {
+ // Compose the option name.
+ String optionName = optionNames[keepClassSpecification.markConditionally ? 2 :
+ keepClassSpecification.markClasses ? 0 :
+ 1];
+
+ if (keepClassSpecification.markDescriptorClasses)
+ {
+ optionName += ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
+ ConfigurationConstants.INCLUDE_DESCRIPTOR_CLASSES_SUBOPTION;
+ }
+
+ if (keepClassSpecification.allowShrinking)
+ {
+ optionName += ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
+ ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION;
+ }
+
+ if (keepClassSpecification.allowOptimization)
+ {
+ optionName += ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
+ ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION;
+ }
+
+ if (keepClassSpecification.allowObfuscation)
+ {
+ optionName += ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
+ ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION;
+ }
+
+ // Write out the option with the proper class specification.
+ writeOption(optionName, keepClassSpecification);
+ }
+
+
+ private void writeOptions(String optionName,
+ List classSpecifications)
+ {
+ if (classSpecifications != null)
+ {
+ for (int index = 0; index < classSpecifications.size(); index++)
+ {
+ writeOption(optionName, (ClassSpecification)classSpecifications.get(index));
+ }
+ }
+ }
+
+
+ private void writeOption(String optionName,
+ ClassSpecification classSpecification)
+ {
+ writer.println();
+
+ // Write out the comments for this option.
+ writeComments(classSpecification.comments);
+
+ writer.print(optionName);
+ writer.print(' ');
+
+ // Write out the required annotation, if any.
+ if (classSpecification.annotationType != null)
+ {
+ writer.print(ConfigurationConstants.ANNOTATION_KEYWORD);
+ writer.print(ClassUtil.externalType(classSpecification.annotationType));
+ writer.print(' ');
+ }
+
+ // Write out the class access flags.
+ writer.print(ClassUtil.externalClassAccessFlags(classSpecification.requiredUnsetAccessFlags,
+ ConfigurationConstants.NEGATOR_KEYWORD));
+
+ writer.print(ClassUtil.externalClassAccessFlags(classSpecification.requiredSetAccessFlags));
+
+ // Write out the class keyword, if we didn't write the interface
+ // keyword earlier.
+ if (((classSpecification.requiredSetAccessFlags |
+ classSpecification.requiredUnsetAccessFlags) &
+ (ClassConstants.ACC_INTERFACE |
+ ClassConstants.ACC_ENUM)) == 0)
+ {
+ writer.print(ConfigurationConstants.CLASS_KEYWORD);
+ }
+
+ writer.print(' ');
+
+ // Write out the class name.
+ writer.print(classSpecification.className != null ?
+ ClassUtil.externalClassName(classSpecification.className) :
+ ConfigurationConstants.ANY_CLASS_KEYWORD);
+
+ // Write out the extends template, if any.
+ if (classSpecification.extendsAnnotationType != null ||
+ classSpecification.extendsClassName != null)
+ {
+ writer.print(' ');
+ writer.print(ConfigurationConstants.EXTENDS_KEYWORD);
+ writer.print(' ');
+
+ // Write out the required extends annotation, if any.
+ if (classSpecification.extendsAnnotationType != null)
+ {
+ writer.print(ConfigurationConstants.ANNOTATION_KEYWORD);
+ writer.print(ClassUtil.externalType(classSpecification.extendsAnnotationType));
+ writer.print(' ');
+ }
+
+ // Write out the extended class name.
+ writer.print(classSpecification.extendsClassName != null ?
+ ClassUtil.externalClassName(classSpecification.extendsClassName) :
+ ConfigurationConstants.ANY_CLASS_KEYWORD);
+ }
+
+ // Write out the keep field and keep method options, if any.
+ if (classSpecification.fieldSpecifications != null ||
+ classSpecification.methodSpecifications != null)
+ {
+ writer.print(' ');
+ writer.println(ConfigurationConstants.OPEN_KEYWORD);
+
+ writeFieldSpecification( classSpecification.fieldSpecifications);
+ writeMethodSpecification(classSpecification.methodSpecifications);
+
+ writer.println(ConfigurationConstants.CLOSE_KEYWORD);
+ }
+ else
+ {
+ writer.println();
+ }
+ }
+
+
+
+ private void writeComments(String comments)
+ {
+ if (comments != null)
+ {
+ int index = 0;
+ while (index < comments.length())
+ {
+ int breakIndex = comments.indexOf('\n', index);
+ if (breakIndex < 0)
+ {
+ breakIndex = comments.length();
+ }
+
+ writer.print('#');
+
+ if (comments.charAt(index) != ' ')
+ {
+ writer.print(' ');
+ }
+
+ writer.println(comments.substring(index, breakIndex));
+
+ index = breakIndex + 1;
+ }
+ }
+ }
+
+
+ private void writeFieldSpecification(List memberSpecifications)
+ {
+ if (memberSpecifications != null)
+ {
+ for (int index = 0; index < memberSpecifications.size(); index++)
+ {
+ MemberSpecification memberSpecification =
+ (MemberSpecification)memberSpecifications.get(index);
+
+ writer.print(" ");
+
+ // Write out the required annotation, if any.
+ if (memberSpecification.annotationType != null)
+ {
+ writer.print(ConfigurationConstants.ANNOTATION_KEYWORD);
+ writer.println(ClassUtil.externalType(memberSpecification.annotationType));
+ writer.print(" ");
+ }
+
+ // Write out the field access flags.
+ writer.print(ClassUtil.externalFieldAccessFlags(memberSpecification.requiredUnsetAccessFlags,
+ ConfigurationConstants.NEGATOR_KEYWORD));
+
+ writer.print(ClassUtil.externalFieldAccessFlags(memberSpecification.requiredSetAccessFlags));
+
+ // Write out the field name and descriptor.
+ String name = memberSpecification.name;
+ String descriptor = memberSpecification.descriptor;
+
+ writer.print(descriptor == null ? name == null ?
+ ConfigurationConstants.ANY_FIELD_KEYWORD :
+ ConfigurationConstants.ANY_TYPE_KEYWORD + ' ' + name :
+ ClassUtil.externalFullFieldDescription(0,
+ name == null ? ConfigurationConstants.ANY_CLASS_MEMBER_KEYWORD : name,
+ descriptor));
+
+ writer.println(ConfigurationConstants.SEPARATOR_KEYWORD);
+ }
+ }
+ }
+
+
+ private void writeMethodSpecification(List memberSpecifications)
+ {
+ if (memberSpecifications != null)
+ {
+ for (int index = 0; index < memberSpecifications.size(); index++)
+ {
+ MemberSpecification memberSpecification =
+ (MemberSpecification)memberSpecifications.get(index);
+
+ writer.print(" ");
+
+ // Write out the required annotation, if any.
+ if (memberSpecification.annotationType != null)
+ {
+ writer.print(ConfigurationConstants.ANNOTATION_KEYWORD);
+ writer.println(ClassUtil.externalType(memberSpecification.annotationType));
+ writer.print(" ");
+ }
+
+ // Write out the method access flags.
+ writer.print(ClassUtil.externalMethodAccessFlags(memberSpecification.requiredUnsetAccessFlags,
+ ConfigurationConstants.NEGATOR_KEYWORD));
+
+ writer.print(ClassUtil.externalMethodAccessFlags(memberSpecification.requiredSetAccessFlags));
+
+ // Write out the method name and descriptor.
+ String name = memberSpecification.name;
+ String descriptor = memberSpecification.descriptor;
+
+ writer.print(descriptor == null ? name == null ?
+ ConfigurationConstants.ANY_METHOD_KEYWORD :
+ ConfigurationConstants.ANY_TYPE_KEYWORD + ' ' + name + ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD + ConfigurationConstants.ANY_ARGUMENTS_KEYWORD + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD :
+ ClassUtil.externalFullMethodDescription(ClassConstants.METHOD_NAME_INIT,
+ 0,
+ name == null ? ConfigurationConstants.ANY_CLASS_MEMBER_KEYWORD : name,
+ descriptor));
+
+ writer.println(ConfigurationConstants.SEPARATOR_KEYWORD);
+ }
+ }
+ }
+
+
+ /**
+ * Returns a list with external versions of the given list of internal
+ * class names.
+ */
+ private List externalClassNames(List internalClassNames)
+ {
+ List externalClassNames = new ArrayList(internalClassNames.size());
+
+ for (int index = 0; index < internalClassNames.size(); index++)
+ {
+ externalClassNames.add(ClassUtil.externalClassName((String)internalClassNames.get(index)));
+ }
+
+ return externalClassNames;
+ }
+
+
+ /**
+ * Returns a relative file name of the given file, if possible.
+ * The file name is also quoted, if necessary.
+ */
+ private String relativeFileName(File file)
+ {
+ String fileName = file.getAbsolutePath();
+
+ // See if we can convert the file name into a relative file name.
+ if (baseDir != null)
+ {
+ String baseDirName = baseDir.getAbsolutePath() + File.separator;
+ if (fileName.startsWith(baseDirName))
+ {
+ fileName = fileName.substring(baseDirName.length());
+ }
+ }
+
+ return quotedString(fileName);
+ }
+
+
+ /**
+ * Returns a quoted version of the given string, if necessary.
+ */
+ private String quotedString(String string)
+ {
+ return string.length() == 0 ||
+ string.indexOf(' ') >= 0 ||
+ string.indexOf('@') >= 0 ||
+ string.indexOf('{') >= 0 ||
+ string.indexOf('}') >= 0 ||
+ string.indexOf('(') >= 0 ||
+ string.indexOf(')') >= 0 ||
+ string.indexOf(':') >= 0 ||
+ string.indexOf(';') >= 0 ||
+ string.indexOf(',') >= 0 ? ("'" + string + "'") :
+ ( string );
+ }
+
+
+ /**
+ * A main method for testing configuration writing.
+ */
+ public static void main(String[] args) {
+ try
+ {
+ ConfigurationWriter writer = new ConfigurationWriter(new File(args[0]));
+
+ writer.write(new Configuration());
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/DataEntryReaderFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/DataEntryReaderFactory.java
new file mode 100644
index 0000000000..3bdd220149
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/DataEntryReaderFactory.java
@@ -0,0 +1,159 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.io.*;
+import proguard.util.*;
+
+import java.util.List;
+
+
+/**
+ * This class can create DataEntryReader instances based on class path entries.
+ * The readers will unwrap the input data entries from any jars, wars, ears,
+ * and zips, before passing them to a given reader.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryReaderFactory
+{
+ /**
+ * Creates a DataEntryReader that can read the given class path entry.
+ *
+ * @param messagePrefix a prefix for messages that are printed out.
+ * @param classPathEntry the input class path entry.
+ * @param reader a data entry reader to which the reading of actual
+ * classes and resource files can be delegated.
+ * @return a DataEntryReader for reading the given class path entry.
+ */
+ public static DataEntryReader createDataEntryReader(String messagePrefix,
+ ClassPathEntry classPathEntry,
+ DataEntryReader reader)
+ {
+ boolean isApk = classPathEntry.isApk();
+ boolean isJar = classPathEntry.isJar();
+ boolean isAar = classPathEntry.isAar();
+ boolean isWar = classPathEntry.isWar();
+ boolean isEar = classPathEntry.isEar();
+ boolean isZip = classPathEntry.isZip();
+
+ List filter = classPathEntry.getFilter();
+ List apkFilter = classPathEntry.getApkFilter();
+ List jarFilter = classPathEntry.getJarFilter();
+ List aarFilter = classPathEntry.getAarFilter();
+ List warFilter = classPathEntry.getWarFilter();
+ List earFilter = classPathEntry.getEarFilter();
+ List zipFilter = classPathEntry.getZipFilter();
+
+ System.out.println(messagePrefix +
+ (isApk ? "apk" :
+ isJar ? "jar" :
+ isAar ? "aar" :
+ isWar ? "war" :
+ isEar ? "ear" :
+ isZip ? "zip" :
+ "directory") +
+ " [" + classPathEntry.getName() + "]" +
+ (filter != null ||
+ apkFilter != null ||
+ jarFilter != null ||
+ aarFilter != null ||
+ warFilter != null ||
+ earFilter != null ||
+ zipFilter != null ? " (filtered)" : ""));
+
+ // Add a filter, if specified.
+ if (filter != null)
+ {
+ reader = new FilteredDataEntryReader(
+ new DataEntryNameFilter(
+ new ListParser(new FileNameParser()).parse(filter)),
+ reader);
+ }
+
+ // Unzip any apks, if necessary.
+ reader = wrapInJarReader(reader, isApk, apkFilter, ".apk");
+ if (!isApk)
+ {
+ // Unzip any jars, if necessary.
+ reader = wrapInJarReader(reader, isJar, jarFilter, ".jar");
+ if (!isJar)
+ {
+ // Unzip any aars, if necessary.
+ reader = wrapInJarReader(reader, isAar, aarFilter, ".aar");
+ if (!isAar)
+ {
+ // Unzip any wars, if necessary.
+ reader = wrapInJarReader(reader, isWar, warFilter, ".war");
+ if (!isWar)
+ {
+ // Unzip any ears, if necessary.
+ reader = wrapInJarReader(reader, isEar, earFilter, ".ear");
+ if (!isEar)
+ {
+ // Unzip any zips, if necessary.
+ reader = wrapInJarReader(reader, isZip, zipFilter, ".zip");
+ }
+ }
+ }
+ }
+ }
+
+ return reader;
+ }
+
+
+ /**
+ * Wraps the given DataEntryReader in a JarReader, filtering it if necessary.
+ */
+ private static DataEntryReader wrapInJarReader(DataEntryReader reader,
+ boolean isJar,
+ List jarFilter,
+ String jarExtension)
+ {
+ // Unzip any jars, if necessary.
+ DataEntryReader jarReader = new JarReader(reader);
+
+ if (isJar)
+ {
+ // Always unzip.
+ return jarReader;
+ }
+ else
+ {
+ // Add a filter, if specified.
+ if (jarFilter != null)
+ {
+ jarReader = new FilteredDataEntryReader(
+ new DataEntryNameFilter(
+ new ListParser(new FileNameParser()).parse(jarFilter)),
+ jarReader);
+ }
+
+ // Only unzip the right type of jars.
+ return new FilteredDataEntryReader(
+ new DataEntryNameFilter(
+ new ExtensionMatcher(jarExtension)),
+ jarReader,
+ reader);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/DataEntryWriterFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/DataEntryWriterFactory.java
new file mode 100644
index 0000000000..4225a794e7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/DataEntryWriterFactory.java
@@ -0,0 +1,162 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.io.*;
+import proguard.util.*;
+
+import java.util.List;
+
+/**
+ * This class can create DataEntryWriter instances based on class paths. The
+ * writers will wrap the output in the proper apks, jars, wars, ears, and zips.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryWriterFactory
+{
+ /**
+ * Creates a DataEntryWriter that can write to the given class path entries.
+ *
+ * @param classPath the output class path.
+ * @param fromIndex the start index in the class path.
+ * @param toIndex the end index in the class path.
+ * @return a DataEntryWriter for writing to the given class path entries.
+ */
+ public static DataEntryWriter createDataEntryWriter(ClassPath classPath,
+ int fromIndex,
+ int toIndex)
+ {
+ DataEntryWriter writer = null;
+
+ // Create a chain of writers, one for each class path entry.
+ for (int index = toIndex - 1; index >= fromIndex; index--)
+ {
+ ClassPathEntry entry = classPath.get(index);
+ writer = createClassPathEntryWriter(entry, writer);
+ }
+
+ return writer;
+ }
+
+
+ /**
+ * Creates a DataEntryWriter that can write to the given class path entry,
+ * or delegate to another DataEntryWriter if its filters don't match.
+ */
+ private static DataEntryWriter createClassPathEntryWriter(ClassPathEntry classPathEntry,
+ DataEntryWriter alternativeWriter)
+ {
+ boolean isApk = classPathEntry.isApk();
+ boolean isJar = classPathEntry.isJar();
+ boolean isAar = classPathEntry.isAar();
+ boolean isWar = classPathEntry.isWar();
+ boolean isEar = classPathEntry.isEar();
+ boolean isZip = classPathEntry.isZip();
+
+ List filter = classPathEntry.getFilter();
+ List apkFilter = classPathEntry.getApkFilter();
+ List jarFilter = classPathEntry.getJarFilter();
+ List aarFilter = classPathEntry.getAarFilter();
+ List warFilter = classPathEntry.getWarFilter();
+ List earFilter = classPathEntry.getEarFilter();
+ List zipFilter = classPathEntry.getZipFilter();
+
+ System.out.println("Preparing output " +
+ (isApk ? "apk" :
+ isJar ? "jar" :
+ isAar ? "aar" :
+ isWar ? "war" :
+ isEar ? "ear" :
+ isZip ? "zip" :
+ "directory") +
+ " [" + classPathEntry.getName() + "]" +
+ (filter != null ||
+ apkFilter != null ||
+ jarFilter != null ||
+ aarFilter != null ||
+ warFilter != null ||
+ earFilter != null ||
+ zipFilter != null ? " (filtered)" : ""));
+
+ DataEntryWriter writer = new DirectoryWriter(classPathEntry.getFile(),
+ isApk ||
+ isJar ||
+ isAar ||
+ isWar ||
+ isEar ||
+ isZip);
+
+ // Set up the filtered jar writers.
+ writer = wrapInJarWriter(writer, isZip, zipFilter, ".zip", isApk || isJar || isAar || isWar || isEar);
+ writer = wrapInJarWriter(writer, isEar, earFilter, ".ear", isApk || isJar || isAar || isWar);
+ writer = wrapInJarWriter(writer, isWar, warFilter, ".war", isApk || isJar || isAar);
+ writer = wrapInJarWriter(writer, isAar, aarFilter, ".aar", isApk || isJar);
+ writer = wrapInJarWriter(writer, isJar, jarFilter, ".jar", isApk);
+ writer = wrapInJarWriter(writer, isApk, apkFilter, ".apk", false);
+
+ // Add a filter, if specified.
+ writer = filter != null?
+ new FilteredDataEntryWriter(
+ new DataEntryNameFilter(
+ new ListParser(new FileNameParser()).parse(filter)),
+ writer) :
+ writer;
+
+ // Let the writer cascade, if specified.
+ return alternativeWriter != null ?
+ new CascadingDataEntryWriter(writer, alternativeWriter) :
+ writer;
+ }
+
+
+ /**
+ * Wraps the given DataEntryWriter in a JarWriter, filtering if necessary.
+ */
+ private static DataEntryWriter wrapInJarWriter(DataEntryWriter writer,
+ boolean isJar,
+ List jarFilter,
+ String jarExtension,
+ boolean dontWrap)
+ {
+ // Zip up jars, if necessary.
+ DataEntryWriter jarWriter = dontWrap ?
+ (DataEntryWriter)new ParentDataEntryWriter(writer) :
+ (DataEntryWriter)new JarWriter(writer);
+
+ // Add a filter, if specified.
+ DataEntryWriter filteredJarWriter = jarFilter != null?
+ new FilteredDataEntryWriter(
+ new DataEntryParentFilter(
+ new DataEntryNameFilter(
+ new ListParser(new FileNameParser()).parse(jarFilter))),
+ jarWriter) :
+ jarWriter;
+
+ // Only zip up jars, unless the output is a jar file itself.
+ return new FilteredDataEntryWriter(
+ new DataEntryParentFilter(
+ new DataEntryNameFilter(
+ new ExtensionMatcher(jarExtension))),
+ filteredJarWriter,
+ isJar ? jarWriter : writer);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/DescriptorKeepChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/DescriptorKeepChecker.java
new file mode 100644
index 0000000000..e71197b16b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/DescriptorKeepChecker.java
@@ -0,0 +1,168 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.optimize.*;
+
+import java.util.List;
+
+/**
+ * This class checks whether classes referenced by class members that are
+ * marked to be kept are marked to be kept too.
+ *
+ * @author Eric Lafortune
+ */
+public class DescriptorKeepChecker
+extends SimplifiedVisitor
+implements MemberVisitor,
+ ClassVisitor
+{
+ private final ClassPool programClassPool;
+ private final ClassPool libraryClassPool;
+ private final WarningPrinter notePrinter;
+
+ // Some fields acting as parameters for the class visitor.
+ private Clazz referencingClass;
+ private Member referencingMember;
+ private boolean isField;
+
+
+ /**
+ * Creates a new DescriptorKeepChecker.
+ */
+ public DescriptorKeepChecker(ClassPool programClassPool,
+ ClassPool libraryClassPool,
+ WarningPrinter notePrinter)
+ {
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ this.notePrinter = notePrinter;
+ }
+
+
+ /**
+ * Checks the classes mentioned in the given keep specifications, printing
+ * notes if necessary.
+ */
+ public void checkClassSpecifications(List keepSpecifications)
+ {
+ // Clean up any old visitor info.
+ programClassPool.classesAccept(new ClassCleaner());
+ libraryClassPool.classesAccept(new ClassCleaner());
+
+ // Create a visitor for marking the seeds.
+ KeepMarker keepMarker = new KeepMarker();
+ ClassPoolVisitor classPoolvisitor =
+ ClassSpecificationVisitorFactory.createClassPoolVisitor(keepSpecifications,
+ keepMarker,
+ keepMarker,
+ false,
+ true,
+ true);
+ // Mark the seeds.
+ programClassPool.accept(classPoolvisitor);
+ libraryClassPool.accept(classPoolvisitor);
+
+ // Print out notes about argument types that are not being kept in
+ // class members that are being kept.
+ programClassPool.classesAccept(
+ new AllMemberVisitor(
+ new KeptMemberFilter(this)));
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ //referencingClass = programClass;
+ //referencingMember = programField;
+ //isField = true;
+ //
+ // Don't check the type, because it is not required for introspection.
+ //programField.referencedClassesAccept(this);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ referencingClass = programClass;
+ referencingMember = programMethod;
+ isField = false;
+
+ // Don't check the return type, because it is not required for
+ // introspection (e.g. the return type of the special Enum methods).
+ //programMethod.referencedClassesAccept(this);
+
+ Clazz[] referencedClasses = programMethod.referencedClasses;
+ if (referencedClasses != null)
+ {
+ int count = referencedClasses.length;
+
+ // Adapt the count if the return type is a class type (not so
+ // pretty; assuming test just checks for final ';').
+ if (ClassUtil.isInternalClassType(programMethod.getDescriptor(programClass)))
+ {
+ count--;
+ }
+
+ for (int index = 0; index < count; index++)
+ {
+ if (referencedClasses[index] != null)
+ {
+ referencedClasses[index].accept(this);
+ }
+ }
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (!KeepMarker.isKept(programClass))
+ {
+ notePrinter.print(referencingClass.getName(),
+ programClass.getName(),
+ "Note: the configuration keeps the entry point '" +
+ ClassUtil.externalClassName(referencingClass.getName()) +
+ " { " +
+ (isField ?
+ ClassUtil.externalFullFieldDescription(0,
+ referencingMember.getName(referencingClass),
+ referencingMember.getDescriptor(referencingClass)) :
+ ClassUtil.externalFullMethodDescription(referencingClass.getName(),
+ 0,
+ referencingMember.getName(referencingClass),
+ referencingMember.getDescriptor(referencingClass))) +
+ "; }', but not the descriptor class '" +
+ ClassUtil.externalClassName(programClass.getName()) +
+ "'");
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/DuplicateClassPrinter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/DuplicateClassPrinter.java
new file mode 100644
index 0000000000..947e3ae50b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/DuplicateClassPrinter.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor writes out notes about the class files that it visits
+ * being duplicates.
+ *
+ * @author Eric Lafortune
+ */
+public class DuplicateClassPrinter implements ClassVisitor
+{
+ private final WarningPrinter notePrinter;
+
+
+ /**
+ * Creates a new DuplicateClassVisitor.
+ */
+ public DuplicateClassPrinter(WarningPrinter notePrinter)
+ {
+ this.notePrinter = notePrinter;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ notePrinter.print(programClass.getName(),
+ "Note: duplicate definition of program class [" +
+ ClassUtil.externalClassName(programClass.getName()) + "]");
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ notePrinter.print(libraryClass.getName(),
+ "Note: duplicate definition of library class [" +
+ ClassUtil.externalClassName(libraryClass.getName()) + "]");
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/FileWordReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/FileWordReader.java
new file mode 100644
index 0000000000..9b8f0e8909
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/FileWordReader.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.io.*;
+import java.net.URL;
+
+
+/**
+ * A <code>WordReader</code> that returns words from a file or a URL.
+ *
+ * @author Eric Lafortune
+ */
+public class FileWordReader extends LineWordReader
+{
+ /**
+ * Creates a new FileWordReader for the given file.
+ */
+ public FileWordReader(File file) throws IOException
+ {
+ super(new LineNumberReader(new BufferedReader(new FileReader(file))),
+ "file '" + file.getPath() + "'",
+ file.getParentFile()
+ );
+ }
+
+
+ /**
+ * Creates a new FileWordReader for the given URL.
+ */
+ public FileWordReader(URL url) throws IOException
+ {
+ super(new LineNumberReader(new BufferedReader(new InputStreamReader(url.openStream()))),
+ "file '" + url.toString() + "'",
+ null);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/FullyQualifiedClassNameChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/FullyQualifiedClassNameChecker.java
new file mode 100644
index 0000000000..f284349cac
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/FullyQualifiedClassNameChecker.java
@@ -0,0 +1,200 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+import java.util.List;
+
+/**
+ * This class checks if the user has forgotten to fully qualify any classes
+ * in the configuration.
+ *
+ * @author Eric Lafortune
+ */
+public class FullyQualifiedClassNameChecker
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private static final String INVALID_CLASS_EXTENSION = ClassUtil.internalClassName(ClassConstants.CLASS_FILE_EXTENSION);
+
+
+ private final ClassPool programClassPool;
+ private final ClassPool libraryClassPool;
+ private final WarningPrinter notePrinter;
+
+
+ /**
+ * Creates a new FullyQualifiedClassNameChecker.
+ */
+ public FullyQualifiedClassNameChecker(ClassPool programClassPool,
+ ClassPool libraryClassPool,
+ WarningPrinter notePrinter)
+ {
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ this.notePrinter = notePrinter;
+ }
+
+
+ /**
+ * Checks the classes mentioned in the given class specifications, printing
+ * notes if necessary.
+ */
+ public void checkClassSpecifications(List classSpecifications)
+ {
+ if (classSpecifications != null)
+ {
+ for (int index = 0; index < classSpecifications.size(); index++)
+ {
+ ClassSpecification classSpecification =
+ (ClassSpecification)classSpecifications.get(index);
+
+ checkType(classSpecification.annotationType);
+ checkClassName(classSpecification.className);
+ checkType(classSpecification.extendsAnnotationType);
+ checkClassName(classSpecification.extendsClassName);
+
+ checkMemberSpecifications(classSpecification.fieldSpecifications, true);
+ checkMemberSpecifications(classSpecification.methodSpecifications, false);
+ }
+ }
+ }
+
+
+ /**
+ * Checks the classes mentioned in the given class member specifications,
+ * printing notes if necessary.
+ */
+ private void checkMemberSpecifications(List memberSpecifications, boolean isField)
+ {
+ if (memberSpecifications != null)
+ {
+ for (int index = 0; index < memberSpecifications.size(); index++)
+ {
+ MemberSpecification memberSpecification =
+ (MemberSpecification)memberSpecifications.get(index);
+
+ checkType(memberSpecification.annotationType);
+
+ if (isField)
+ {
+ checkType(memberSpecification.descriptor);
+ }
+ else
+ {
+ checkDescriptor(memberSpecification.descriptor);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Checks the classes mentioned in the given class member descriptor,
+ * printing notes if necessary.
+ */
+ private void checkDescriptor(String descriptor)
+ {
+ if (descriptor != null)
+ {
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(descriptor);
+
+ checkType(internalTypeEnumeration.returnType());
+
+ while (internalTypeEnumeration.hasMoreTypes())
+ {
+ checkType(internalTypeEnumeration.nextType());
+ }
+ }
+ }
+
+
+ /**
+ * Checks the class mentioned in the given type (if any),
+ * printing notes if necessary.
+ */
+ private void checkType(String type)
+ {
+ if (type != null)
+ {
+ checkClassName(ClassUtil.internalClassNameFromType(type));
+ }
+ }
+
+
+ /**
+ * Checks the specified class (if any),
+ * printing notes if necessary.
+ */
+ private void checkClassName(String className)
+ {
+ if (className != null &&
+ !containsWildCards(className) &&
+ programClassPool.getClass(className) == null &&
+ libraryClassPool.getClass(className) == null &&
+ notePrinter.accepts(className))
+ {
+ notePrinter.print(className,
+ "Note: the configuration refers to the unknown class '" +
+ ClassUtil.externalClassName(className) + "'");
+
+ // Strip "/class" or replace the package name by a wildcard.
+ int lastSeparatorIndex =
+ className.lastIndexOf(ClassConstants.PACKAGE_SEPARATOR);
+
+ String fullyQualifiedClassName =
+ className.endsWith(INVALID_CLASS_EXTENSION) ?
+ className.substring(0, lastSeparatorIndex) :
+ "**" + ClassConstants.PACKAGE_SEPARATOR + className.substring(lastSeparatorIndex + 1);
+
+ // Suggest matching classes.
+ ClassNameFilter classNameFilter =
+ new ClassNameFilter(fullyQualifiedClassName, this);
+
+ programClassPool.classesAccept(classNameFilter);
+ libraryClassPool.classesAccept(classNameFilter);
+ }
+ }
+
+
+ private static boolean containsWildCards(String string)
+ {
+ return string != null &&
+ (string.indexOf('!') >= 0 ||
+ string.indexOf('*') >= 0 ||
+ string.indexOf('?') >= 0 ||
+ string.indexOf(',') >= 0 ||
+ string.indexOf("///") >= 0);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ System.out.println(" Maybe you meant the fully qualified name '" +
+ ClassUtil.externalClassName(clazz.getName()) + "'?");
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/GPL.java b/third_party/java/proguard/proguard5.3.3/src/proguard/GPL.java
new file mode 100644
index 0000000000..6558470d7d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/GPL.java
@@ -0,0 +1,196 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class checks and prints out information about the GPL.
+ *
+ * @author Eric Lafortune
+ */
+public class GPL
+{
+ /**
+ * Prints out a note about the GPL if ProGuard is linked against unknown
+ * code.
+ */
+ public static void check()
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ new Exception().printStackTrace(new PrintStream(out));
+ LineNumberReader reader = new LineNumberReader(
+ new InputStreamReader(
+ new ByteArrayInputStream(out.toByteArray())));
+
+ Set unknownPackageNames = unknownPackageNames(reader);
+
+ if (unknownPackageNames.size() > 0)
+ {
+ String uniquePackageNames = uniquePackageNames(unknownPackageNames);
+
+ System.out.println("ProGuard is released under the GNU General Public License. You therefore");
+ System.out.println("must ensure that programs that link to it ("+uniquePackageNames+"...)");
+ System.out.println("carry the GNU General Public License as well. Alternatively, you can");
+ System.out.println("apply for an exception with the author of ProGuard.");
+ }
+ }
+
+
+ /**
+ * Returns a set of package names from the given stack trace.
+ */
+ private static Set unknownPackageNames(LineNumberReader reader)
+ {
+ Set packageNames = new HashSet();
+
+ try
+ {
+ while (true)
+ {
+ String line = reader.readLine();
+ if (line == null)
+ {
+ break;
+ }
+
+ line = line.trim();
+ if (line.startsWith("at "))
+ {
+ line = line.substring(2).trim();
+ line = trimSuffix(line, '(');
+ line = trimSuffix(line, '.');
+ line = trimSuffix(line, '.');
+
+ if (line.length() > 0 && !isKnown(line))
+ {
+ packageNames.add(line);
+ }
+ }
+ }
+ }
+ catch (IOException ex)
+ {
+ // We'll just stop looking for more names.
+ }
+
+ return packageNames;
+ }
+
+
+ /**
+ * Returns a comma-separated list of package names from the set, excluding
+ * any subpackages of packages in the set.
+ */
+ private static String uniquePackageNames(Set packageNames)
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ Iterator iterator = packageNames.iterator();
+ while (iterator.hasNext())
+ {
+ String packageName = (String)iterator.next();
+ if (!containsPrefix(packageNames, packageName))
+ {
+ buffer.append(packageName).append(", ");
+ }
+ }
+
+ return buffer.toString();
+ }
+
+
+ /**
+ * Returns a given string without the suffix, as defined by the given
+ * separator.
+ */
+ private static String trimSuffix(String string, char separator)
+ {
+ int index = string.lastIndexOf(separator);
+ return index < 0 ? "" : string.substring(0, index);
+ }
+
+
+ /**
+ * Returns whether the given set contains a prefix of the given name.
+ */
+ private static boolean containsPrefix(Set set, String name)
+ {
+ int index = 0;
+
+ while (!set.contains(name.substring(0, index)))
+ {
+ index = name.indexOf('.', index + 1);
+ if (index < 0)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the given package name has been granted an exception
+ * against the GPL linking clause, by the copyright holder of ProGuard.
+ * This method is not legally binding, but of course the actual license is.
+ * Please contact the copyright holder if you would like an exception for
+ * your code as well.
+ */
+ private static boolean isKnown(String packageName)
+ {
+ return packageName.startsWith("java") ||
+ packageName.startsWith("sun.reflect") ||
+ packageName.startsWith("proguard") ||
+ packageName.startsWith("org.apache.tools.ant") ||
+ packageName.startsWith("org.apache.tools.maven") ||
+ packageName.startsWith("org.gradle") ||
+ packageName.startsWith("org.codehaus.groovy") ||
+ packageName.startsWith("org.eclipse") ||
+ packageName.startsWith("org.netbeans") ||
+ packageName.startsWith("com.android") ||
+ packageName.startsWith("com.sun.kvem") ||
+ packageName.startsWith("net.certiv.proguarddt") ||
+ packageName.startsWith("groovy") ||
+ packageName.startsWith("scala") ||
+ packageName.startsWith("sbt") ||
+ packageName.startsWith("xsbt") ||
+ packageName.startsWith("eclipseme");
+ }
+
+
+ public static void main(String[] args)
+ {
+ LineNumberReader reader = new LineNumberReader(
+ new InputStreamReader(System.in));
+
+ Set unknownPackageNames = unknownPackageNames(reader);
+
+ if (unknownPackageNames.size() > 0)
+ {
+ String uniquePackageNames = uniquePackageNames(unknownPackageNames);
+
+ System.out.println(uniquePackageNames);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/GetAnnotationChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/GetAnnotationChecker.java
new file mode 100644
index 0000000000..6aad6cc66b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/GetAnnotationChecker.java
@@ -0,0 +1,80 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+
+/**
+ * This constant visitor checks whether visited method references try to
+ * access annotations.
+ *
+ * @author Eric Lafortune
+ */
+public class GetAnnotationChecker
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final WarningPrinter notePrinter;
+
+
+ /**
+ * Creates a new GetAnnotationChecker.
+ */
+ public GetAnnotationChecker(WarningPrinter notePrinter)
+ {
+ this.notePrinter = notePrinter;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ String className = methodrefConstant.getClassName(clazz);
+
+ if (className.equals(ClassConstants.NAME_JAVA_LANG_CLASS) ||
+ className.equals(ClassConstants.NAME_JAVA_LANG_REFLECT_FIELD) ||
+ className.equals(ClassConstants.NAME_JAVA_LANG_REFLECT_METHOD))
+ {
+ String methodName = methodrefConstant.getName(clazz);
+
+ if (methodName.equals(ClassConstants.METHOD_NAME_GET_ANNOTATION) ||
+ methodName.equals(ClassConstants.METHOD_NAME_GET_ANNOTATIONS) ||
+ methodName.equals(ClassConstants.METHOD_NAME_GET_DECLARED_ANNOTATIONS) ||
+ methodName.equals(ClassConstants.METHOD_NAME_GET_PARAMETER_ANNOTATIONS))
+ {
+ notePrinter.print(clazz.getName(),
+ "Note: " +
+ ClassUtil.externalClassName(clazz.getName()) +
+ " calls '" +
+ ClassUtil.externalShortClassName(ClassUtil.externalClassName(className)) +
+ "." +
+ methodName + "'");
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/GetEnclosingClassChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/GetEnclosingClassChecker.java
new file mode 100644
index 0000000000..b9c1105ca2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/GetEnclosingClassChecker.java
@@ -0,0 +1,76 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+
+/**
+ * This constant visitor checks whether visited method references try to
+ * access enclosing classes.
+ *
+ * @author Eric Lafortune
+ */
+public class GetEnclosingClassChecker
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final WarningPrinter notePrinter;
+
+
+ /**
+ * Creates a new GetEnclosingMethodChecker.
+ */
+ public GetEnclosingClassChecker(WarningPrinter notePrinter)
+ {
+ this.notePrinter = notePrinter;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ String className = methodrefConstant.getClassName(clazz);
+
+ if (className.equals(ClassConstants.NAME_JAVA_LANG_CLASS))
+ {
+ String methodName = methodrefConstant.getName(clazz);
+
+ if (methodName.equals(ClassConstants.METHOD_NAME_CLASS_GET_ENCLOSING_CLASS) ||
+ methodName.equals(ClassConstants.METHOD_NAME_CLASS_GET_DECLARING_CLASS))
+ {
+ notePrinter.print(clazz.getName(),
+ "Note: " +
+ ClassUtil.externalClassName(clazz.getName()) +
+ " calls '" +
+ ClassUtil.externalShortClassName(ClassUtil.externalClassName(className)) +
+ "." +
+ methodName + "'");
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/GetEnclosingMethodChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/GetEnclosingMethodChecker.java
new file mode 100644
index 0000000000..9926ea6ea6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/GetEnclosingMethodChecker.java
@@ -0,0 +1,76 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+
+/**
+ * This constant visitor checks whether visited method references try to
+ * access enclosing methods.
+ *
+ * @author Eric Lafortune
+ */
+public class GetEnclosingMethodChecker
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final WarningPrinter notePrinter;
+
+
+ /**
+ * Creates a new GetEnclosingMethodChecker.
+ */
+ public GetEnclosingMethodChecker(WarningPrinter notePrinter)
+ {
+ this.notePrinter = notePrinter;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ String className = methodrefConstant.getClassName(clazz);
+
+ if (className.equals(ClassConstants.NAME_JAVA_LANG_CLASS))
+ {
+ String methodName = methodrefConstant.getName(clazz);
+
+ if (methodName.equals(ClassConstants.METHOD_NAME_CLASS_GET_ENCLOSING_CONSTRUCTOR) ||
+ methodName.equals(ClassConstants.METHOD_NAME_CLASS_GET_ENCLOSING_METHOD))
+ {
+ notePrinter.print(clazz.getName(),
+ "Note: " +
+ ClassUtil.externalClassName(clazz.getName()) +
+ " calls '" +
+ ClassUtil.externalShortClassName(ClassUtil.externalClassName(className)) +
+ "." +
+ methodName + "'");
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/GetSignatureChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/GetSignatureChecker.java
new file mode 100644
index 0000000000..cec97d04b5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/GetSignatureChecker.java
@@ -0,0 +1,78 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+
+/**
+ * This constant visitor checks whether visited method references try to
+ * access signatures.
+ *
+ * @author Eric Lafortune
+ */
+public class GetSignatureChecker
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final WarningPrinter notePrinter;
+
+
+ /**
+ * Creates a new GetSignatureChecker.
+ */
+ public GetSignatureChecker(WarningPrinter notePrinter)
+ {
+ this.notePrinter = notePrinter;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ String className = methodrefConstant.getClassName(clazz);
+
+ if (className.equals(ClassConstants.NAME_JAVA_LANG_CLASS) ||
+ className.equals(ClassConstants.NAME_JAVA_LANG_REFLECT_FIELD) ||
+ className.equals(ClassConstants.NAME_JAVA_LANG_REFLECT_METHOD))
+ {
+ String methodName = methodrefConstant.getName(clazz);
+
+ if (methodName.startsWith(ClassConstants.METHOD_NAME_GET_TYPE_PREFIX) ||
+ methodName.startsWith(ClassConstants.METHOD_NAME_GET_GENERIC_PREFIX))
+ {
+ notePrinter.print(clazz.getName(),
+ "Note: " +
+ ClassUtil.externalClassName(clazz.getName()) +
+ " calls '" +
+ ClassUtil.externalShortClassName(ClassUtil.externalClassName(className)) +
+ "." +
+ methodName + "'");
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/Initializer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/Initializer.java
new file mode 100644
index 0000000000..c93ba38be9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/Initializer.java
@@ -0,0 +1,576 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.visitor.AllElementValueVisitor;
+import proguard.classfile.attribute.visitor.AllAttributeVisitor;
+import proguard.classfile.constant.visitor.AllConstantVisitor;
+import proguard.classfile.instruction.visitor.AllInstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.util.*;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * This class initializes class pools.
+ *
+ * @author Eric Lafortune
+ */
+public class Initializer
+{
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new Initializer to initialize classes according to the given
+ * configuration.
+ */
+ public Initializer(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Initializes the classes in the given program class pool and library class
+ * pool, performs some basic checks, and shrinks the library class pool.
+ */
+ public void execute(ClassPool programClassPool,
+ ClassPool libraryClassPool) throws IOException
+ {
+ int originalLibraryClassPoolSize = libraryClassPool.size();
+
+ // Perform basic checks on the configuration.
+ WarningPrinter fullyQualifiedClassNameNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ FullyQualifiedClassNameChecker fullyQualifiedClassNameChecker =
+ new FullyQualifiedClassNameChecker(programClassPool,
+ libraryClassPool,
+ fullyQualifiedClassNameNotePrinter);
+
+ fullyQualifiedClassNameChecker.checkClassSpecifications(configuration.keep);
+ fullyQualifiedClassNameChecker.checkClassSpecifications(configuration.assumeNoSideEffects);
+
+ StringMatcher keepAttributesMatcher = configuration.keepAttributes != null ?
+ new ListParser(new NameParser()).parse(configuration.keepAttributes) :
+ new EmptyStringMatcher();
+
+ WarningPrinter getAnnotationNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ if (!keepAttributesMatcher.matches(ClassConstants.ATTR_RuntimeVisibleAnnotations))
+ {
+ programClassPool.classesAccept(
+ new AllConstantVisitor(
+ new GetAnnotationChecker(getAnnotationNotePrinter)));
+ }
+
+ WarningPrinter getSignatureNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ if (!keepAttributesMatcher.matches(ClassConstants.ATTR_Signature))
+ {
+ programClassPool.classesAccept(
+ new AllConstantVisitor(
+ new GetSignatureChecker(getSignatureNotePrinter)));
+ }
+
+ WarningPrinter getEnclosingClassNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ if (!keepAttributesMatcher.matches(ClassConstants.ATTR_InnerClasses))
+ {
+ programClassPool.classesAccept(
+ new AllConstantVisitor(
+ new GetEnclosingClassChecker(getEnclosingClassNotePrinter)));
+ }
+
+ WarningPrinter getEnclosingMethodNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ if (!keepAttributesMatcher.matches(ClassConstants.ATTR_EnclosingMethod))
+ {
+ programClassPool.classesAccept(
+ new AllConstantVisitor(
+ new GetEnclosingMethodChecker(getEnclosingMethodNotePrinter)));
+ }
+
+ // Construct a reduced library class pool with only those library
+ // classes whose hierarchies are referenced by the program classes.
+ // We can't do this if we later have to come up with the obfuscated
+ // class member names that are globally unique.
+ ClassPool reducedLibraryClassPool = configuration.useUniqueClassMemberNames ?
+ null : new ClassPool();
+
+ WarningPrinter classReferenceWarningPrinter = new WarningPrinter(System.err, configuration.warn);
+ WarningPrinter dependencyWarningPrinter = new WarningPrinter(System.err, configuration.warn);
+
+ // Initialize the superclass hierarchies for program classes.
+ programClassPool.classesAccept(
+ new ClassSuperHierarchyInitializer(programClassPool,
+ libraryClassPool,
+ classReferenceWarningPrinter,
+ null));
+
+ // Initialize the superclass hierarchy of all library classes, without
+ // warnings.
+ libraryClassPool.classesAccept(
+ new ClassSuperHierarchyInitializer(programClassPool,
+ libraryClassPool,
+ null,
+ dependencyWarningPrinter));
+
+ // Initialize the class references of program class members and
+ // attributes. Note that all superclass hierarchies have to be
+ // initialized for this purpose.
+ WarningPrinter programMemberReferenceWarningPrinter = new WarningPrinter(System.err, configuration.warn);
+ WarningPrinter libraryMemberReferenceWarningPrinter = new WarningPrinter(System.err, configuration.warn);
+
+ programClassPool.classesAccept(
+ new ClassReferenceInitializer(programClassPool,
+ libraryClassPool,
+ classReferenceWarningPrinter,
+ programMemberReferenceWarningPrinter,
+ libraryMemberReferenceWarningPrinter,
+ null));
+
+ if (reducedLibraryClassPool != null)
+ {
+ // Collect the library classes that are directly referenced by
+ // program classes, without introspection.
+ programClassPool.classesAccept(
+ new ReferencedClassVisitor(
+ new LibraryClassFilter(
+ new ClassPoolFiller(reducedLibraryClassPool))));
+
+ // Reinitialize the superclass hierarchies of referenced library
+ // classes, this time with warnings.
+ reducedLibraryClassPool.classesAccept(
+ new ClassSuperHierarchyInitializer(programClassPool,
+ libraryClassPool,
+ classReferenceWarningPrinter,
+ null));
+ }
+
+ // Initialize the enum annotation references.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(true,
+ new AllElementValueVisitor(true,
+ new EnumFieldReferenceInitializer())));
+
+ // Initialize the Class.forName references.
+ WarningPrinter dynamicClassReferenceNotePrinter = new WarningPrinter(System.out, configuration.note);
+ WarningPrinter classForNameNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new AllInstructionVisitor(
+ new DynamicClassReferenceInitializer(programClassPool,
+ libraryClassPool,
+ dynamicClassReferenceNotePrinter,
+ null,
+ classForNameNotePrinter,
+ createClassNoteExceptionMatcher(configuration.keep))))));
+
+ // Initialize the Class.get[Declared]{Field,Method} references.
+ WarningPrinter getMemberNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new AllInstructionVisitor(
+ new DynamicMemberReferenceInitializer(programClassPool,
+ libraryClassPool,
+ getMemberNotePrinter,
+ createClassMemberNoteExceptionMatcher(configuration.keep, true),
+ createClassMemberNoteExceptionMatcher(configuration.keep, false))))));
+
+ // Initialize other string constant references, if requested.
+ if (configuration.adaptClassStrings != null)
+ {
+ programClassPool.classesAccept(
+ new ClassNameFilter(configuration.adaptClassStrings,
+ new AllConstantVisitor(
+ new StringReferenceInitializer(programClassPool,
+ libraryClassPool))));
+ }
+
+ // Initialize the class references of library class members.
+ if (reducedLibraryClassPool != null)
+ {
+ // Collect the library classes that are referenced by program
+ // classes, directly or indirectly, with or without reflection.
+ programClassPool.classesAccept(
+ new ReferencedClassVisitor(
+ new LibraryClassFilter(
+ new ClassHierarchyTraveler(true, true, true, false,
+ new LibraryClassFilter(
+ new ClassPoolFiller(reducedLibraryClassPool))))));
+
+ // Initialize the class references of referenced library
+ // classes, without warnings.
+ reducedLibraryClassPool.classesAccept(
+ new ClassReferenceInitializer(programClassPool,
+ libraryClassPool,
+ null,
+ null,
+ null,
+ dependencyWarningPrinter));
+
+ // Reset the library class pool.
+ libraryClassPool.clear();
+
+ // Copy the library classes that are referenced directly by program
+ // classes and the library classes that are referenced by referenced
+ // library classes.
+ reducedLibraryClassPool.classesAccept(
+ new MultiClassVisitor(new ClassVisitor[]
+ {
+ new ClassHierarchyTraveler(true, true, true, false,
+ new LibraryClassFilter(
+ new ClassPoolFiller(libraryClassPool))),
+
+ new ReferencedClassVisitor(
+ new LibraryClassFilter(
+ new ClassHierarchyTraveler(true, true, true, false,
+ new LibraryClassFilter(
+ new ClassPoolFiller(libraryClassPool)))))
+ }));
+ }
+ else
+ {
+ // Initialize the class references of all library class members.
+ libraryClassPool.classesAccept(
+ new ClassReferenceInitializer(programClassPool,
+ libraryClassPool,
+ null,
+ null,
+ null,
+ dependencyWarningPrinter));
+ }
+
+ // Initialize the subclass hierarchies.
+ programClassPool.classesAccept(new ClassSubHierarchyInitializer());
+ libraryClassPool.classesAccept(new ClassSubHierarchyInitializer());
+
+ // Share strings between the classes, to reduce heap memory usage.
+ programClassPool.classesAccept(new StringSharer());
+ libraryClassPool.classesAccept(new StringSharer());
+
+ // Check for any unmatched class members.
+ WarningPrinter classMemberNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ ClassMemberChecker classMemberChecker =
+ new ClassMemberChecker(programClassPool,
+ classMemberNotePrinter);
+
+ classMemberChecker.checkClassSpecifications(configuration.keep);
+ classMemberChecker.checkClassSpecifications(configuration.assumeNoSideEffects);
+
+ // Check for unkept descriptor classes of kept class members.
+ WarningPrinter descriptorKeepNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ new DescriptorKeepChecker(programClassPool,
+ libraryClassPool,
+ descriptorKeepNotePrinter).checkClassSpecifications(configuration.keep);
+
+ // Check for keep options that only match library classes.
+ WarningPrinter libraryKeepNotePrinter = new WarningPrinter(System.out, configuration.note);
+
+ new LibraryKeepChecker(programClassPool,
+ libraryClassPool,
+ libraryKeepNotePrinter).checkClassSpecifications(configuration.keep);
+
+ // Print out a summary of the notes, if necessary.
+ int fullyQualifiedNoteCount = fullyQualifiedClassNameNotePrinter.getWarningCount();
+ if (fullyQualifiedNoteCount > 0)
+ {
+ System.out.println("Note: there were " + fullyQualifiedNoteCount +
+ " references to unknown classes.");
+ System.out.println(" You should check your configuration for typos.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unknownclass)");
+ }
+
+ int classMemberNoteCount = classMemberNotePrinter.getWarningCount();
+ if (classMemberNoteCount > 0)
+ {
+ System.out.println("Note: there were " + classMemberNoteCount +
+ " references to unknown class members.");
+ System.out.println(" You should check your configuration for typos.");
+ }
+
+ int getAnnotationNoteCount = getAnnotationNotePrinter.getWarningCount();
+ if (getAnnotationNoteCount > 0)
+ {
+ System.out.println("Note: there were " + getAnnotationNoteCount +
+ " classes trying to access annotations using reflection.");
+ System.out.println(" You should consider keeping the annotation attributes");
+ System.out.println(" (using '-keepattributes *Annotation*').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#attributes)");
+ }
+
+ int getSignatureNoteCount = getSignatureNotePrinter.getWarningCount();
+ if (getSignatureNoteCount > 0)
+ {
+ System.out.println("Note: there were " + getSignatureNoteCount +
+ " classes trying to access generic signatures using reflection.");
+ System.out.println(" You should consider keeping the signature attributes");
+ System.out.println(" (using '-keepattributes Signature').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#attributes)");
+ }
+
+ int getEnclosingClassNoteCount = getEnclosingClassNotePrinter.getWarningCount();
+ if (getEnclosingClassNoteCount > 0)
+ {
+ System.out.println("Note: there were " + getEnclosingClassNoteCount +
+ " classes trying to access enclosing classes using reflection.");
+ System.out.println(" You should consider keeping the inner classes attributes");
+ System.out.println(" (using '-keepattributes InnerClasses').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#attributes)");
+ }
+
+ int getEnclosingMethodNoteCount = getEnclosingMethodNotePrinter.getWarningCount();
+ if (getEnclosingMethodNoteCount > 0)
+ {
+ System.out.println("Note: there were " + getEnclosingMethodNoteCount +
+ " classes trying to access enclosing methods using reflection.");
+ System.out.println(" You should consider keeping the enclosing method attributes");
+ System.out.println(" (using '-keepattributes InnerClasses,EnclosingMethod').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#attributes)");
+ }
+
+ int descriptorNoteCount = descriptorKeepNotePrinter.getWarningCount();
+ if (descriptorNoteCount > 0)
+ {
+ System.out.println("Note: there were " + descriptorNoteCount +
+ " unkept descriptor classes in kept class members.");
+ System.out.println(" You should consider explicitly keeping the mentioned classes");
+ System.out.println(" (using '-keep').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#descriptorclass)");
+ }
+
+ int libraryNoteCount = libraryKeepNotePrinter.getWarningCount();
+ if (libraryNoteCount > 0)
+ {
+ System.out.println("Note: there were " + libraryNoteCount +
+ " library classes explicitly being kept.");
+ System.out.println(" You don't need to keep library classes; they are already left unchanged.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#libraryclass)");
+ }
+
+ int dynamicClassReferenceNoteCount = dynamicClassReferenceNotePrinter.getWarningCount();
+ if (dynamicClassReferenceNoteCount > 0)
+ {
+ System.out.println("Note: there were " + dynamicClassReferenceNoteCount +
+ " unresolved dynamic references to classes or interfaces.");
+ System.out.println(" You should check if you need to specify additional program jars.");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclass)");
+ }
+
+ int classForNameNoteCount = classForNameNotePrinter.getWarningCount();
+ if (classForNameNoteCount > 0)
+ {
+ System.out.println("Note: there were " + classForNameNoteCount +
+ " class casts of dynamically created class instances.");
+ System.out.println(" You might consider explicitly keeping the mentioned classes and/or");
+ System.out.println(" their implementations (using '-keep').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclasscast)");
+ }
+
+ int getmemberNoteCount = getMemberNotePrinter.getWarningCount();
+ if (getmemberNoteCount > 0)
+ {
+ System.out.println("Note: there were " + getmemberNoteCount +
+ " accesses to class members by means of introspection.");
+ System.out.println(" You should consider explicitly keeping the mentioned class members");
+ System.out.println(" (using '-keep' or '-keepclassmembers').");
+ System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclassmember)");
+ }
+
+ // Print out a summary of the warnings, if necessary.
+ int classReferenceWarningCount = classReferenceWarningPrinter.getWarningCount();
+ if (classReferenceWarningCount > 0)
+ {
+ System.err.println("Warning: there were " + classReferenceWarningCount +
+ " unresolved references to classes or interfaces.");
+ System.err.println(" You may need to add missing library jars or update their versions.");
+ System.err.println(" If your code works fine without the missing classes, you can suppress");
+ System.err.println(" the warnings with '-dontwarn' options.");
+
+ if (configuration.skipNonPublicLibraryClasses)
+ {
+ System.err.println(" You may also have to remove the option '-skipnonpubliclibraryclasses'.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)");
+ }
+
+ int dependencyWarningCount = dependencyWarningPrinter.getWarningCount();
+ if (dependencyWarningCount > 0)
+ {
+ System.err.println("Warning: there were " + dependencyWarningCount +
+ " instances of library classes depending on program classes.");
+ System.err.println(" You must avoid such dependencies, since the program classes will");
+ System.err.println(" be processed, while the library classes will remain unchanged.");
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#dependency)");
+ }
+
+ int programMemberReferenceWarningCount = programMemberReferenceWarningPrinter.getWarningCount();
+ if (programMemberReferenceWarningCount > 0)
+ {
+ System.err.println("Warning: there were " + programMemberReferenceWarningCount +
+ " unresolved references to program class members.");
+ System.err.println(" Your input classes appear to be inconsistent.");
+ System.err.println(" You may need to recompile the code.");
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedprogramclassmember)");
+ }
+
+ int libraryMemberReferenceWarningCount = libraryMemberReferenceWarningPrinter.getWarningCount();
+ if (libraryMemberReferenceWarningCount > 0)
+ {
+ System.err.println("Warning: there were " + libraryMemberReferenceWarningCount +
+ " unresolved references to library class members.");
+ System.err.println(" You probably need to update the library versions.");
+
+ if (!configuration.skipNonPublicLibraryClassMembers)
+ {
+ System.err.println(" Alternatively, you may have to specify the option ");
+ System.err.println(" '-dontskipnonpubliclibraryclassmembers'.");
+ }
+
+ if (configuration.skipNonPublicLibraryClasses)
+ {
+ System.err.println(" You may also have to remove the option '-skipnonpubliclibraryclasses'.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedlibraryclassmember)");
+ }
+
+ if ((classReferenceWarningCount > 0 ||
+ dependencyWarningCount > 0 ||
+ programMemberReferenceWarningCount > 0 ||
+ libraryMemberReferenceWarningCount > 0) &&
+ !configuration.ignoreWarnings)
+ {
+ throw new IOException("Please correct the above warnings first.");
+ }
+
+ if ((configuration.note == null ||
+ !configuration.note.isEmpty()) &&
+ (configuration.warn != null &&
+ configuration.warn.isEmpty() ||
+ configuration.ignoreWarnings))
+ {
+ System.out.println("Note: you're ignoring all warnings!");
+ }
+
+ // Discard unused library classes.
+ if (configuration.verbose)
+ {
+ System.out.println("Ignoring unused library classes...");
+ System.out.println(" Original number of library classes: " + originalLibraryClassPoolSize);
+ System.out.println(" Final number of library classes: " + libraryClassPool.size());
+ }
+ }
+
+
+ /**
+ * Extracts a list of exceptions of classes for which not to print notes,
+ * from the keep configuration.
+ */
+ private StringMatcher createClassNoteExceptionMatcher(List noteExceptions)
+ {
+ if (noteExceptions != null)
+ {
+ List noteExceptionNames = new ArrayList(noteExceptions.size());
+ for (int index = 0; index < noteExceptions.size(); index++)
+ {
+ KeepClassSpecification keepClassSpecification = (KeepClassSpecification)noteExceptions.get(index);
+ if (keepClassSpecification.markClasses)
+ {
+ // If the class itself is being kept, it's ok.
+ String className = keepClassSpecification.className;
+ if (className != null)
+ {
+ noteExceptionNames.add(className);
+ }
+
+ // If all of its extensions are being kept, it's ok too.
+ String extendsClassName = keepClassSpecification.extendsClassName;
+ if (extendsClassName != null)
+ {
+ noteExceptionNames.add(extendsClassName);
+ }
+ }
+ }
+
+ if (noteExceptionNames.size() > 0)
+ {
+ return new ListParser(new ClassNameParser()).parse(noteExceptionNames);
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Extracts a list of exceptions of field or method names for which not to
+ * print notes, from the keep configuration.
+ */
+ private StringMatcher createClassMemberNoteExceptionMatcher(List noteExceptions,
+ boolean isField)
+ {
+ if (noteExceptions != null)
+ {
+ List noteExceptionNames = new ArrayList();
+ for (int index = 0; index < noteExceptions.size(); index++)
+ {
+ KeepClassSpecification keepClassSpecification = (KeepClassSpecification)noteExceptions.get(index);
+ List memberSpecifications = isField ?
+ keepClassSpecification.fieldSpecifications :
+ keepClassSpecification.methodSpecifications;
+
+ if (memberSpecifications != null)
+ {
+ for (int index2 = 0; index2 < memberSpecifications.size(); index2++)
+ {
+ MemberSpecification memberSpecification =
+ (MemberSpecification)memberSpecifications.get(index2);
+
+ String memberName = memberSpecification.name;
+ if (memberName != null)
+ {
+ noteExceptionNames.add(memberName);
+ }
+ }
+ }
+ }
+
+ if (noteExceptionNames.size() > 0)
+ {
+ return new ListParser(new ClassNameParser()).parse(noteExceptionNames);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/InputReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/InputReader.java
new file mode 100644
index 0000000000..341407489b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/InputReader.java
@@ -0,0 +1,191 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.ClassPool;
+import proguard.classfile.util.WarningPrinter;
+import proguard.classfile.visitor.*;
+import proguard.io.*;
+
+import java.io.IOException;
+
+/**
+ * This class reads the input class files.
+ *
+ * @author Eric Lafortune
+ */
+public class InputReader
+{
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new InputReader to read input class files as specified by the
+ * given configuration.
+ */
+ public InputReader(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Fills the given program class pool and library class pool by reading
+ * class files, based on the current configuration.
+ */
+ public void execute(ClassPool programClassPool,
+ ClassPool libraryClassPool) throws IOException
+ {
+ WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn);
+ WarningPrinter notePrinter = new WarningPrinter(System.out, configuration.note);
+
+ DuplicateClassPrinter duplicateClassPrinter = new DuplicateClassPrinter(notePrinter);
+
+ // Read the program class files.
+ // Prepare a data entry reader to filter all classes,
+ // which are then decoded to classes by a class reader,
+ // which are then put in the class pool by a class pool filler.
+ readInput("Reading program ",
+ configuration.programJars,
+ new ClassFilter(
+ new ClassReader(false,
+ configuration.skipNonPublicLibraryClasses,
+ configuration.skipNonPublicLibraryClassMembers,
+ warningPrinter,
+ new ClassPresenceFilter(programClassPool, duplicateClassPrinter,
+ new ClassPoolFiller(programClassPool)))));
+
+ // Check if we have at least some input classes.
+ if (programClassPool.size() == 0)
+ {
+ throw new IOException("The input doesn't contain any classes. Did you specify the proper '-injars' options?");
+ }
+
+ // Read the library class files, if any.
+ if (configuration.libraryJars != null)
+ {
+ // Prepare a data entry reader to filter all classes,
+ // which are then decoded to classes by a class reader,
+ // which are then put in the class pool by a class pool filler.
+ readInput("Reading library ",
+ configuration.libraryJars,
+ new ClassFilter(
+ new ClassReader(true,
+ configuration.skipNonPublicLibraryClasses,
+ configuration.skipNonPublicLibraryClassMembers,
+ warningPrinter,
+ new ClassPresenceFilter(programClassPool, duplicateClassPrinter,
+ new ClassPresenceFilter(libraryClassPool, duplicateClassPrinter,
+ new ClassPoolFiller(libraryClassPool))))));
+ }
+
+ // Print out a summary of the notes, if necessary.
+ int noteCount = notePrinter.getWarningCount();
+ if (noteCount > 0)
+ {
+ System.err.println("Note: there were " + noteCount +
+ " duplicate class definitions.");
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#duplicateclass)");
+ }
+
+ // Print out a summary of the warnings, if necessary.
+ int warningCount = warningPrinter.getWarningCount();
+ if (warningCount > 0)
+ {
+ System.err.println("Warning: there were " + warningCount +
+ " classes in incorrectly named files.");
+ System.err.println(" You should make sure all file names correspond to their class names.");
+ System.err.println(" The directory hierarchies must correspond to the package hierarchies.");
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#unexpectedclass)");
+
+ if (!configuration.ignoreWarnings)
+ {
+ System.err.println(" If you don't mind the mentioned classes not being written out,");
+ System.err.println(" you could try your luck using the '-ignorewarnings' option.");
+ throw new IOException("Please correct the above warnings first.");
+ }
+ }
+ }
+
+
+ /**
+ * Reads all input entries from the given class path.
+ */
+ private void readInput(String messagePrefix,
+ ClassPath classPath,
+ DataEntryReader reader) throws IOException
+ {
+ readInput(messagePrefix,
+ classPath,
+ 0,
+ classPath.size(),
+ reader);
+ }
+
+
+ /**
+ * Reads all input entries from the given section of the given class path.
+ */
+ public void readInput(String messagePrefix,
+ ClassPath classPath,
+ int fromIndex,
+ int toIndex,
+ DataEntryReader reader) throws IOException
+ {
+ for (int index = fromIndex; index < toIndex; index++)
+ {
+ ClassPathEntry entry = classPath.get(index);
+ if (!entry.isOutput())
+ {
+ readInput(messagePrefix, entry, reader);
+ }
+ }
+ }
+
+
+ /**
+ * Reads the given input class path entry.
+ */
+ private void readInput(String messagePrefix,
+ ClassPathEntry classPathEntry,
+ DataEntryReader dataEntryReader) throws IOException
+ {
+ try
+ {
+ // Create a reader that can unwrap jars, wars, ears, and zips.
+ DataEntryReader reader =
+ DataEntryReaderFactory.createDataEntryReader(messagePrefix,
+ classPathEntry,
+ dataEntryReader);
+
+ // Create the data entry pump.
+ DirectoryPump directoryPump =
+ new DirectoryPump(classPathEntry.getFile());
+
+ // Pump the data entries into the reader.
+ directoryPump.pumpDataEntries(reader);
+ }
+ catch (IOException ex)
+ {
+ throw (IOException)new IOException("Can't read [" + classPathEntry + "] (" + ex.getMessage() + ")").initCause(ex);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/KeepClassMemberChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/KeepClassMemberChecker.java
new file mode 100644
index 0000000000..38dcc5a895
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/KeepClassMemberChecker.java
@@ -0,0 +1,86 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.util.List;
+
+/**
+ * This class checks if the user has forgotten to specify class members in
+ * some keep options in the configuration.
+ *
+ * @author Eric Lafortune
+ */
+public class KeepClassMemberChecker
+{
+ private final WarningPrinter notePrinter;
+
+
+ /**
+ * Creates a new KeepClassMemberChecker.
+ */
+ public KeepClassMemberChecker(WarningPrinter notePrinter)
+ {
+ this.notePrinter = notePrinter;
+ }
+
+
+ /**
+ * Checks if the given class specifications try to keep class members
+ * without actually specifying any, printing notes if necessary.
+ */
+ public void checkClassSpecifications(List keepClassSpecifications)
+ {
+ if (keepClassSpecifications != null)
+ {
+ for (int index = 0; index < keepClassSpecifications.size(); index++)
+ {
+ KeepClassSpecification keepClassSpecification =
+ (KeepClassSpecification)keepClassSpecifications.get(index);
+
+ if (!keepClassSpecification.markClasses &&
+ (keepClassSpecification.fieldSpecifications == null ||
+ keepClassSpecification.fieldSpecifications.size() == 0) &&
+ (keepClassSpecification.methodSpecifications == null ||
+ keepClassSpecification.methodSpecifications.size() == 0))
+ {
+ String className = keepClassSpecification.className;
+ if (className == null)
+ {
+ className = keepClassSpecification.extendsClassName;
+ }
+
+ if (className == null ||
+ notePrinter.accepts(className))
+ {
+ notePrinter.print(className,
+ "Note: the configuration doesn't specify which class members to keep for class '" +
+ (className == null ?
+ ConfigurationConstants.ANY_CLASS_KEYWORD :
+ ClassUtil.externalClassName(className)) + "'");
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/KeepClassSpecification.java b/third_party/java/proguard/proguard5.3.3/src/proguard/KeepClassSpecification.java
new file mode 100644
index 0000000000..26a5bc0f70
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/KeepClassSpecification.java
@@ -0,0 +1,151 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+/**
+ * This class represents a keep option with class specification.
+ *
+ * @author Eric Lafortune
+ */
+public class KeepClassSpecification extends ClassSpecification
+{
+ public final boolean markClasses;
+ public final boolean markConditionally;
+ public final boolean markDescriptorClasses;
+ public final boolean allowShrinking;
+ public final boolean allowOptimization;
+ public final boolean allowObfuscation;
+
+
+ /**
+ * Creates a new KeepClassSpecification for all possible classes.
+ * @param markClasses specifies whether to mark the classes.
+ * If false, only class members are marked.
+ * If true, the classes are marked as well.
+ * @param markConditionally specifies whether to mark the classes and
+ * class members conditionally. If true,
+ * classes and class members are marked, on
+ * the condition that all specified class
+ * members are present.
+ * @param markDescriptorClasses specifies whether to mark the classes in
+ * the descriptors of the marked class members.
+ * @param allowShrinking specifies whether shrinking is allowed.
+ * @param allowOptimization specifies whether optimization is allowed.
+ * @param allowObfuscation specifies whether obfuscation is allowed.
+ */
+ public KeepClassSpecification(boolean markClasses,
+ boolean markConditionally,
+ boolean markDescriptorClasses,
+ boolean allowShrinking,
+ boolean allowOptimization,
+ boolean allowObfuscation)
+ {
+ this.markClasses = markClasses;
+ this.markConditionally = markConditionally;
+ this.markDescriptorClasses = markDescriptorClasses;
+ this.allowShrinking = allowShrinking;
+ this.allowOptimization = allowOptimization;
+ this.allowObfuscation = allowObfuscation;
+ }
+
+
+ /**
+ * Creates a new KeepClassSpecification.
+ * @param markClasses specifies whether to mark the classes.
+ * If false, only class members are marked.
+ * If true, the classes are marked as well.
+ * @param markConditionally specifies whether to mark the classes and
+ * class members conditionally. If true,
+ * classes and class members are marked, on
+ * the condition that all specified class
+ * members are present.
+ * @param markDescriptorClasses specifies whether to mark the classes in
+ * the descriptors of the marked class members.
+ * @param allowShrinking specifies whether shrinking is allowed.
+ * @param allowOptimization specifies whether optimization is allowed.
+ * @param allowObfuscation specifies whether obfuscation is allowed.
+ * @param classSpecification the specification of classes and class
+ * members.
+ */
+ public KeepClassSpecification(boolean markClasses,
+ boolean markConditionally,
+ boolean markDescriptorClasses,
+ boolean allowShrinking,
+ boolean allowOptimization,
+ boolean allowObfuscation,
+ ClassSpecification classSpecification)
+ {
+ super(classSpecification);
+
+ this.markClasses = markClasses;
+ this.markConditionally = markConditionally;
+ this.markDescriptorClasses = markDescriptorClasses;
+ this.allowShrinking = allowShrinking;
+ this.allowOptimization = allowOptimization;
+ this.allowObfuscation = allowObfuscation;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (object == null ||
+ this.getClass() != object.getClass())
+ {
+ return false;
+ }
+
+ KeepClassSpecification other = (KeepClassSpecification)object;
+ return
+ this.markClasses == other.markClasses &&
+ this.markConditionally == other.markConditionally &&
+ this.markDescriptorClasses == other.markDescriptorClasses &&
+ this.allowShrinking == other.allowShrinking &&
+ this.allowOptimization == other.allowOptimization &&
+ this.allowObfuscation == other.allowObfuscation &&
+ super.equals(other);
+ }
+
+ public int hashCode()
+ {
+ return
+ (markClasses ? 0 : 1) ^
+ (markConditionally ? 0 : 2) ^
+ (markDescriptorClasses ? 0 : 4) ^
+ (allowShrinking ? 0 : 8) ^
+ (allowOptimization ? 0 : 16) ^
+ (allowObfuscation ? 0 : 32) ^
+ super.hashCode();
+ }
+
+ public Object clone()
+ {
+// try
+// {
+ return super.clone();
+// }
+// catch (CloneNotSupportedException e)
+// {
+// return null;
+// }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/LibraryKeepChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/LibraryKeepChecker.java
new file mode 100644
index 0000000000..1aa85ebd84
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/LibraryKeepChecker.java
@@ -0,0 +1,115 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.optimize.*;
+
+import java.util.List;
+
+/**
+ * This class checks whether some keep rules only keep library classes, no
+ * program classes. That is strange, because library classes never need to
+ * be kept explicitly.
+ *
+ * @author Eric Lafortune
+ */
+public class LibraryKeepChecker
+implements ClassVisitor
+{
+ private final ClassPool programClassPool;
+ private final ClassPool libraryClassPool;
+ private final WarningPrinter notePrinter;
+
+ // Some fields acting as parameters for the class visitor.
+ private String keepName;
+
+
+ /**
+ * Creates a new DescriptorKeepChecker.
+ */
+ public LibraryKeepChecker(ClassPool programClassPool,
+ ClassPool libraryClassPool,
+ WarningPrinter notePrinter)
+ {
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ this.notePrinter = notePrinter;
+ }
+
+
+ /**
+ * Checks the classes mentioned in the given keep specifications, printing
+ * notes if necessary.
+ */
+ public void checkClassSpecifications(List keepSpecifications)
+ {
+ if (keepSpecifications != null)
+ {
+ // Go over all individual keep specifications.
+ for (int index = 0; index < keepSpecifications.size(); index++)
+ {
+ KeepClassSpecification keepClassSpecification =
+ (KeepClassSpecification)keepSpecifications.get(index);
+
+ // Is the keep specification more specific than a general
+ // wildcard?
+ keepName = keepClassSpecification.className;
+ if (keepName != null)
+ {
+ // Doesn't the specification match any program classes?
+ ClassCounter programClassCounter = new ClassCounter();
+ programClassPool.accept(
+ ClassSpecificationVisitorFactory.createClassPoolVisitor(keepClassSpecification,
+ programClassCounter,
+ null));
+ if (programClassCounter.getCount() == 0)
+ {
+ // Print out notes about any matched library classes.
+ libraryClassPool.accept(
+ ClassSpecificationVisitorFactory.createClassPoolVisitor(keepClassSpecification,
+ this,
+ null));
+ }
+ }
+ }
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass) {}
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ String className = libraryClass.getName();
+ notePrinter.print(className,
+ "Note: the configuration explicitly specifies '" +
+ ClassUtil.externalClassName(keepName) +
+ "' to keep library class '" +
+ ClassUtil.externalClassName(className) +
+ "'");
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/LineWordReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/LineWordReader.java
new file mode 100644
index 0000000000..556feeb6c8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/LineWordReader.java
@@ -0,0 +1,74 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.io.*;
+
+
+/**
+ * A <code>WordReader</code> that returns words from a line number reader.
+ *
+ * @author Eric Lafortune
+ */
+public class LineWordReader extends WordReader
+{
+ private final LineNumberReader reader;
+ private final String description;
+
+
+ /**
+ * Creates a new LineWordReader for the given input.
+ */
+ public LineWordReader(LineNumberReader lineNumberReader,
+ String description,
+ File baseDir) throws IOException
+ {
+ super(baseDir);
+
+ this.reader = lineNumberReader;
+ this.description = description;
+ }
+
+
+ // Implementations for WordReader.
+
+ protected String nextLine() throws IOException
+ {
+ return reader.readLine();
+ }
+
+
+ protected String lineLocationDescription()
+ {
+ return "line " + reader.getLineNumber() + " of " + description;
+ }
+
+
+ public void close() throws IOException
+ {
+ super.close();
+
+ if (reader != null)
+ {
+ reader.close();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/MANIFEST.MF b/third_party/java/proguard/proguard5.3.3/src/proguard/MANIFEST.MF
new file mode 100644
index 0000000000..3bad15ec1d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+Main-Class: proguard.ProGuard
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/MemberSpecification.java b/third_party/java/proguard/proguard5.3.3/src/proguard/MemberSpecification.java
new file mode 100644
index 0000000000..b5ed86bb8e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/MemberSpecification.java
@@ -0,0 +1,114 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+
+/**
+ * This class stores a specification of class members. The specification is
+ * template-based: the class member names and descriptors can contain wildcards.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberSpecification
+{
+ public int requiredSetAccessFlags;
+ public int requiredUnsetAccessFlags;
+ public final String annotationType;
+ public final String name;
+ public final String descriptor;
+
+
+ /**
+ * Creates a new option to keep all possible class members.
+ */
+ public MemberSpecification()
+ {
+ this(0,
+ 0,
+ null,
+ null,
+ null);
+ }
+
+
+ /**
+ * Creates a new option to keep the specified class member(s).
+ *
+ * @param requiredSetAccessFlags the class access flags that must be set
+ * in order for the class to apply.
+ * @param requiredUnsetAccessFlags the class access flags that must be unset
+ * in order for the class to apply.
+ * @param annotationType the name of the class that must be an
+ * annotation in order for the class member
+ * to apply. The name may be null to specify
+ * that no annotation is required.
+ * @param name the class member name. The name may be
+ * null to specify any class member or it
+ * may contain "*" or "?" wildcards.
+ * @param descriptor the class member descriptor. The
+ * descriptor may be null to specify any
+ * class member or it may contain
+ * "**", "*", or "?" wildcards.
+ */
+ public MemberSpecification(int requiredSetAccessFlags,
+ int requiredUnsetAccessFlags,
+ String annotationType,
+ String name,
+ String descriptor)
+ {
+ this.requiredSetAccessFlags = requiredSetAccessFlags;
+ this.requiredUnsetAccessFlags = requiredUnsetAccessFlags;
+ this.annotationType = annotationType;
+ this.name = name;
+ this.descriptor = descriptor;
+ }
+
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (object == null ||
+ this.getClass() != object.getClass())
+ {
+ return false;
+ }
+
+ MemberSpecification other = (MemberSpecification)object;
+ return
+ (this.requiredSetAccessFlags == other.requiredSetAccessFlags ) &&
+ (this.requiredUnsetAccessFlags == other.requiredUnsetAccessFlags ) &&
+ (this.annotationType == null ? other.annotationType == null : this.annotationType.equals(other.annotationType)) &&
+ (this.name == null ? other.name == null : this.name.equals(other.name) ) &&
+ (this.descriptor == null ? other.descriptor == null : this.descriptor.equals(other.descriptor) );
+ }
+
+ public int hashCode()
+ {
+ return
+ (requiredSetAccessFlags ) ^
+ (requiredUnsetAccessFlags ) ^
+ (annotationType == null ? 0 : annotationType.hashCode()) ^
+ (name == null ? 0 : name.hashCode() ) ^
+ (descriptor == null ? 0 : descriptor.hashCode() );
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/OutputWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/OutputWriter.java
new file mode 100644
index 0000000000..ed3b279306
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/OutputWriter.java
@@ -0,0 +1,219 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.ClassPool;
+import proguard.classfile.util.ClassUtil;
+import proguard.io.*;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * This class writes the output class files.
+ *
+ * @author Eric Lafortune
+ */
+public class OutputWriter
+{
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new OutputWriter to write output class files as specified by
+ * the given configuration.
+ */
+ public OutputWriter(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Writes the given class pool to class files, based on the current
+ * configuration.
+ */
+ public void execute(ClassPool programClassPool) throws IOException
+ {
+ ClassPath programJars = configuration.programJars;
+
+ int firstInputIndex = 0;
+ int lastInputIndex = 0;
+
+ // Go over all program class path entries.
+ for (int index = 0; index < programJars.size(); index++)
+ {
+ // Is it an input entry?
+ ClassPathEntry entry = programJars.get(index);
+ if (!entry.isOutput())
+ {
+ // Remember the index of the last input entry.
+ lastInputIndex = index;
+ }
+ else
+ {
+ // Check if this the last output entry in a series.
+ int nextIndex = index + 1;
+ if (nextIndex == programJars.size() ||
+ !programJars.get(nextIndex).isOutput())
+ {
+ // Write the processed input entries to the output entries.
+ writeOutput(programClassPool,
+ programJars,
+ firstInputIndex,
+ lastInputIndex + 1,
+ nextIndex);
+
+ // Start with the next series of input entries.
+ firstInputIndex = nextIndex;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Transfers the specified input jars to the specified output jars.
+ */
+ private void writeOutput(ClassPool programClassPool,
+ ClassPath classPath,
+ int fromInputIndex,
+ int fromOutputIndex,
+ int toOutputIndex)
+ throws IOException
+ {
+ try
+ {
+ // Construct the writer that can write jars, wars, ears, zips, and
+ // directories, cascading over the specified output entries.
+ DataEntryWriter writer =
+ DataEntryWriterFactory.createDataEntryWriter(classPath,
+ fromOutputIndex,
+ toOutputIndex);
+
+ // The writer will be used to write possibly obfuscated class files.
+ DataEntryReader classRewriter =
+ new ClassRewriter(programClassPool, writer);
+
+ // The writer will also be used to write resource files.
+ DataEntryReader resourceCopier =
+ new DataEntryCopier(writer);
+
+ DataEntryReader resourceRewriter = resourceCopier;
+
+ // Adapt resource file contents and names, if necessary.
+ if (configuration.obfuscate)
+ {
+ // Wrap the resource writer with a filter and a data entry
+ // rewriter, if required.
+ if (configuration.adaptResourceFileContents != null)
+ {
+ resourceRewriter =
+ new NameFilter(configuration.adaptResourceFileContents,
+ new NameFilter("META-INF/MANIFEST.MF,META-INF/*.SF",
+ new ManifestRewriter(programClassPool, writer),
+ new DataEntryRewriter(programClassPool, writer)),
+ resourceRewriter);
+ }
+
+ // Wrap the resource writer with a filter and a data entry
+ // renamer, if required.
+ if (configuration.adaptResourceFileNames != null)
+ {
+ Map packagePrefixMap = createPackagePrefixMap(programClassPool);
+
+ resourceRewriter =
+ new NameFilter(configuration.adaptResourceFileNames,
+ new DataEntryObfuscator(programClassPool,
+ packagePrefixMap,
+ resourceRewriter),
+ resourceRewriter);
+ }
+ }
+
+ DataEntryReader directoryRewriter = null;
+
+ // Wrap the directory writer with a filter and a data entry renamer,
+ // if required.
+ if (configuration.keepDirectories != null)
+ {
+ Map packagePrefixMap = createPackagePrefixMap(programClassPool);
+
+ directoryRewriter =
+ new NameFilter(configuration.keepDirectories,
+ new DataEntryRenamer(packagePrefixMap,
+ resourceCopier,
+ resourceCopier));
+ }
+
+ // Create the reader that can write class files and copy directories
+ // and resource files to the main writer.
+ DataEntryReader reader =
+ new ClassFilter( classRewriter,
+ new DirectoryFilter(directoryRewriter,
+ resourceRewriter));
+
+ // Go over the specified input entries and write their processed
+ // versions.
+ new InputReader(configuration).readInput(" Copying resources from program ",
+ classPath,
+ fromInputIndex,
+ fromOutputIndex,
+ reader);
+
+ // Close all output entries.
+ writer.close();
+ }
+ catch (IOException ex)
+ {
+ throw (IOException)new IOException("Can't write [" + classPath.get(fromOutputIndex).getName() + "] (" + ex.getMessage() + ")").initCause(ex);
+ }
+ }
+
+
+ /**
+ * Creates a map of old package prefixes to new package prefixes, based on
+ * the given class pool.
+ */
+ private static Map createPackagePrefixMap(ClassPool classPool)
+ {
+ Map packagePrefixMap = new HashMap();
+
+ Iterator iterator = classPool.classNames();
+ while (iterator.hasNext())
+ {
+ String className = (String)iterator.next();
+ String packagePrefix = ClassUtil.internalPackagePrefix(className);
+
+ String mappedNewPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
+ if (mappedNewPackagePrefix == null ||
+ !mappedNewPackagePrefix.equals(packagePrefix))
+ {
+ String newClassName = classPool.getClass(className).getName();
+ String newPackagePrefix = ClassUtil.internalPackagePrefix(newClassName);
+
+ packagePrefixMap.put(packagePrefix, newPackagePrefix);
+ }
+ }
+
+ return packagePrefixMap;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ParseException.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ParseException.java
new file mode 100644
index 0000000000..d937b7c008
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ParseException.java
@@ -0,0 +1,51 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+
+/**
+ * This <code>Exception</code> signals that a parse exception of some
+ * sort has occurred.
+ *
+ * @author Eric Lafortune
+ */
+public class ParseException extends Exception {
+
+ /**
+ * Constructs a <code>ParseException</code> with <code>null</code>
+ * as its error detail message.
+ */
+ public ParseException() {
+ super();
+ }
+
+ /**
+ * Constructs a <code>ParseException</code> with the specified detail
+ * message. The error message string <code>s</code> can later be
+ * retrieved by the <code>{@link Throwable#getMessage}</code>
+ * method of class <code>Throwable</code>.
+ *
+ * @param s the detail message.
+ */
+ public ParseException(String s) {
+ super(s);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java
new file mode 100644
index 0000000000..73dce7323b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java
@@ -0,0 +1,558 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AllAttributeVisitor;
+import proguard.classfile.editor.*;
+import proguard.classfile.visitor.*;
+import proguard.obfuscate.Obfuscator;
+import proguard.optimize.Optimizer;
+import proguard.optimize.peephole.LineNumberLinearizer;
+import proguard.preverify.*;
+import proguard.shrink.Shrinker;
+
+import java.io.*;
+
+/**
+ * Tool for shrinking, optimizing, obfuscating, and preverifying Java classes.
+ *
+ * @author Eric Lafortune
+ */
+public class ProGuard
+{
+ public static final String VERSION = "ProGuard, version 5.3.3";
+
+ private final Configuration configuration;
+ private ClassPool programClassPool = new ClassPool();
+ private final ClassPool libraryClassPool = new ClassPool();
+
+
+ /**
+ * Creates a new ProGuard object to process jars as specified by the given
+ * configuration.
+ */
+ public ProGuard(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Performs all subsequent ProGuard operations.
+ */
+ public void execute() throws IOException
+ {
+ System.out.println(VERSION);
+
+ GPL.check();
+
+ if (configuration.printConfiguration != null)
+ {
+ printConfiguration();
+ }
+
+ new ConfigurationChecker(configuration).check();
+
+ if (configuration.programJars != null &&
+ configuration.programJars.hasOutput() &&
+ new UpToDateChecker(configuration).check())
+ {
+ return;
+ }
+
+ readInput();
+
+ if (configuration.shrink ||
+ configuration.optimize ||
+ configuration.obfuscate ||
+ configuration.preverify)
+ {
+ clearPreverification();
+ }
+
+ if (configuration.printSeeds != null ||
+ configuration.shrink ||
+ configuration.optimize ||
+ configuration.obfuscate ||
+ configuration.preverify)
+ {
+ initialize();
+ }
+
+ if (configuration.targetClassVersion != 0)
+ {
+ target();
+ }
+
+ if (configuration.printSeeds != null)
+ {
+ printSeeds();
+ }
+
+ if (configuration.shrink)
+ {
+ shrink();
+ }
+
+ if (configuration.preverify)
+ {
+ inlineSubroutines();
+ }
+
+ if (configuration.optimize)
+ {
+ for (int optimizationPass = 0;
+ optimizationPass < configuration.optimizationPasses;
+ optimizationPass++)
+ {
+ if (!optimize())
+ {
+ // Stop optimizing if the code doesn't improve any further.
+ break;
+ }
+
+ // Shrink again, if we may.
+ if (configuration.shrink)
+ {
+ // Don't print any usage this time around.
+ configuration.printUsage = null;
+ configuration.whyAreYouKeeping = null;
+
+ shrink();
+ }
+ }
+ }
+
+ if (configuration.optimize)
+ {
+ linearizeLineNumbers();
+ }
+
+ if (configuration.obfuscate)
+ {
+ obfuscate();
+ }
+
+ if (configuration.optimize)
+ {
+ trimLineNumbers();
+ }
+
+ if (configuration.preverify)
+ {
+ preverify();
+ }
+
+ if (configuration.shrink ||
+ configuration.optimize ||
+ configuration.obfuscate ||
+ configuration.preverify)
+ {
+ sortClassElements();
+ }
+
+ if (configuration.programJars.hasOutput())
+ {
+ writeOutput();
+ }
+
+ if (configuration.dump != null)
+ {
+ dump();
+ }
+ }
+
+
+ /**
+ * Prints out the configuration that ProGuard is using.
+ */
+ private void printConfiguration() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Printing configuration to [" + fileName(configuration.printConfiguration) + "]...");
+ }
+
+ PrintStream ps = createPrintStream(configuration.printConfiguration);
+ try
+ {
+ new ConfigurationWriter(ps).write(configuration);
+ }
+ finally
+ {
+ closePrintStream(ps);
+ }
+ }
+
+
+ /**
+ * Reads the input class files.
+ */
+ private void readInput() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Reading input...");
+ }
+
+ // Fill the program class pool and the library class pool.
+ new InputReader(configuration).execute(programClassPool, libraryClassPool);
+ }
+
+
+ /**
+ * Initializes the cross-references between all classes, performs some
+ * basic checks, and shrinks the library class pool.
+ */
+ private void initialize() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Initializing...");
+ }
+
+ new Initializer(configuration).execute(programClassPool, libraryClassPool);
+ }
+
+
+ /**
+ * Sets that target versions of the program classes.
+ */
+ private void target() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Setting target versions...");
+ }
+
+ new Targeter(configuration).execute(programClassPool);
+ }
+
+
+ /**
+ * Prints out classes and class members that are used as seeds in the
+ * shrinking and obfuscation steps.
+ */
+ private void printSeeds() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Printing kept classes, fields, and methods...");
+ }
+
+ PrintStream ps = createPrintStream(configuration.printSeeds);
+ try
+ {
+ new SeedPrinter(ps).write(configuration, programClassPool, libraryClassPool);
+ }
+ finally
+ {
+ closePrintStream(ps);
+ }
+ }
+
+
+ /**
+ * Performs the shrinking step.
+ */
+ private void shrink() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Shrinking...");
+
+ // We'll print out some explanation, if requested.
+ if (configuration.whyAreYouKeeping != null)
+ {
+ System.out.println("Explaining why classes and class members are being kept...");
+ }
+
+ // We'll print out the usage, if requested.
+ if (configuration.printUsage != null)
+ {
+ System.out.println("Printing usage to [" + fileName(configuration.printUsage) + "]...");
+ }
+ }
+
+ // Perform the actual shrinking.
+ programClassPool =
+ new Shrinker(configuration).execute(programClassPool, libraryClassPool);
+ }
+
+
+ /**
+ * Performs the subroutine inlining step.
+ */
+ private void inlineSubroutines()
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Inlining subroutines...");
+ }
+
+ // Perform the actual inlining.
+ new SubroutineInliner(configuration).execute(programClassPool);
+ }
+
+
+ /**
+ * Performs the optimization step.
+ */
+ private boolean optimize() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Optimizing...");
+ }
+
+ // Perform the actual optimization.
+ return new Optimizer(configuration).execute(programClassPool, libraryClassPool);
+ }
+
+
+ /**
+ * Performs the obfuscation step.
+ */
+ private void obfuscate() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Obfuscating...");
+
+ // We'll apply a mapping, if requested.
+ if (configuration.applyMapping != null)
+ {
+ System.out.println("Applying mapping [" + fileName(configuration.applyMapping) + "]");
+ }
+
+ // We'll print out the mapping, if requested.
+ if (configuration.printMapping != null)
+ {
+ System.out.println("Printing mapping to [" + fileName(configuration.printMapping) + "]...");
+ }
+ }
+
+ // Perform the actual obfuscation.
+ new Obfuscator(configuration).execute(programClassPool, libraryClassPool);
+ }
+
+
+ /**
+ * Disambiguates the line numbers of all program classes, after
+ * optimizations like method inlining and class merging.
+ */
+ private void linearizeLineNumbers()
+ {
+ programClassPool.classesAccept(new LineNumberLinearizer());
+ }
+
+
+ /**
+ * Trims the line number table attributes of all program classes.
+ */
+ private void trimLineNumbers()
+ {
+ programClassPool.classesAccept(new AllAttributeVisitor(true,
+ new LineNumberTableAttributeTrimmer()));
+ }
+
+
+ /**
+ * Clears any JSE preverification information from the program classes.
+ */
+ private void clearPreverification()
+ {
+ programClassPool.classesAccept(
+ new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_6,
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new NamedAttributeDeleter(ClassConstants.ATTR_StackMapTable)))));
+ }
+
+
+ /**
+ * Performs the preverification step.
+ */
+ private void preverify()
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Preverifying...");
+ }
+
+ // Perform the actual preverification.
+ new Preverifier(configuration).execute(programClassPool);
+ }
+
+
+ /**
+ * Sorts the elements of all program classes.
+ */
+ private void sortClassElements()
+ {
+ programClassPool.classesAccept(new ClassElementSorter());
+ }
+
+
+ /**
+ * Writes the output class files.
+ */
+ private void writeOutput() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Writing output...");
+ }
+
+ // Write out the program class pool.
+ new OutputWriter(configuration).execute(programClassPool);
+ }
+
+
+ /**
+ * Prints out the contents of the program classes.
+ */
+ private void dump() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Printing classes to [" + fileName(configuration.dump) + "]...");
+ }
+
+ PrintStream ps = createPrintStream(configuration.dump);
+ try
+ {
+ programClassPool.classesAccept(new ClassPrinter(ps));
+ }
+ finally
+ {
+ closePrintStream(ps);
+ }
+ }
+
+
+ /**
+ * Returns a print stream for the given file, or the standard output if
+ * the file name is empty.
+ */
+ private PrintStream createPrintStream(File file)
+ throws FileNotFoundException
+ {
+ return file == Configuration.STD_OUT ? System.out :
+ new PrintStream(
+ new BufferedOutputStream(
+ new FileOutputStream(file)));
+ }
+
+
+ /**
+ * Closes the given print stream, or closes it if is the standard output.
+ * @param printStream
+ */
+ private void closePrintStream(PrintStream printStream)
+ {
+ if (printStream == System.out)
+ {
+ printStream.flush();
+ }
+ else
+ {
+ printStream.close();
+ }
+ }
+
+
+ /**
+ * Returns the canonical file name for the given file, or "standard output"
+ * if the file name is empty.
+ */
+ private String fileName(File file)
+ {
+ if (file == Configuration.STD_OUT)
+ {
+ return "standard output";
+ }
+ else
+ {
+ try
+ {
+ return file.getCanonicalPath();
+ }
+ catch (IOException ex)
+ {
+ return file.getPath();
+ }
+ }
+ }
+
+
+ /**
+ * The main method for ProGuard.
+ */
+ public static void main(String[] args)
+ {
+ if (args.length == 0)
+ {
+ System.out.println(VERSION);
+ System.out.println("Usage: java proguard.ProGuard [options ...]");
+ System.exit(1);
+ }
+
+ // Create the default options.
+ Configuration configuration = new Configuration();
+
+ try
+ {
+ // Parse the options specified in the command line arguments.
+ ConfigurationParser parser = new ConfigurationParser(args,
+ System.getProperties());
+ try
+ {
+ parser.parse(configuration);
+ }
+ finally
+ {
+ parser.close();
+ }
+
+ // Execute ProGuard with these options.
+ new ProGuard(configuration).execute();
+ }
+ catch (Exception ex)
+ {
+ if (configuration.verbose)
+ {
+ // Print a verbose stack trace.
+ ex.printStackTrace();
+ }
+ else
+ {
+ // Print just the stack trace message.
+ System.err.println("Error: "+ex.getMessage());
+ }
+
+ System.exit(1);
+ }
+
+ System.exit(0);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/SeedPrinter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/SeedPrinter.java
new file mode 100644
index 0000000000..b6a04c4aa7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/SeedPrinter.java
@@ -0,0 +1,91 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.ClassPool;
+import proguard.classfile.visitor.*;
+import proguard.optimize.*;
+
+import java.io.*;
+
+/**
+ * This class prints out the seeds specified by keep options.
+ *
+ * @author Eric Lafortune
+ */
+public class SeedPrinter
+{
+ private final PrintStream ps;
+
+
+ /**
+ * Creates a new ConfigurationWriter for the given PrintStream.
+ */
+ public SeedPrinter(PrintStream ps) throws IOException
+ {
+ this.ps = ps;
+ }
+
+
+ /**
+ * Prints out the seeds for the classes in the given program class pool.
+ * @param configuration the configuration containing the keep options.
+ * @throws IOException if an IO error occurs while writing the configuration.
+ */
+ public void write(Configuration configuration,
+ ClassPool programClassPool,
+ ClassPool libraryClassPool) throws IOException
+ {
+ // Check if we have at least some keep commands.
+ if (configuration.keep == null)
+ {
+ throw new IOException("You have to specify '-keep' options for the shrinking step.");
+ }
+
+ // Clean up any old visitor info.
+ programClassPool.classesAccept(new ClassCleaner());
+ libraryClassPool.classesAccept(new ClassCleaner());
+
+ // Create a visitor for printing out the seeds. We're printing out
+ // the program elements that are preserved against shrinking,
+ // optimization, or obfuscation.
+ KeepMarker keepMarker = new KeepMarker();
+ ClassPoolVisitor classPoolvisitor =
+ ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep,
+ keepMarker,
+ keepMarker,
+ true,
+ true,
+ true);
+ // Mark the seeds.
+ programClassPool.accept(classPoolvisitor);
+ libraryClassPool.accept(classPoolvisitor);
+
+ // Print out the seeds.
+ SimpleClassPrinter printer = new SimpleClassPrinter(false, ps);
+ programClassPool.classesAcceptAlphabetically(new MultiClassVisitor(
+ new ClassVisitor[]
+ {
+ new KeptClassFilter(printer),
+ new AllMemberVisitor(new KeptMemberFilter(printer))
+ }));
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/SubclassedClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/SubclassedClassFilter.java
new file mode 100644
index 0000000000..47d73bab35
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/SubclassedClassFilter.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are being subclassed.
+ *
+ * @author Eric Lafortune
+ */
+final class SubclassedClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public SubclassedClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (programClass.subClasses != null)
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (libraryClass.subClasses != null)
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/Targeter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/Targeter.java
new file mode 100644
index 0000000000..4618d5dc84
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/Targeter.java
@@ -0,0 +1,88 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import proguard.classfile.ClassPool;
+import proguard.classfile.util.ClassUtil;
+import proguard.classfile.visitor.ClassVersionSetter;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * This class sets the target version on program classes.
+ *
+ * @author Eric Lafortune
+ */
+public class Targeter
+{
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new Targeter to set the target version on program classes
+ * according to the given configuration.
+ */
+ public Targeter(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Sets the target version on classes in the given program class pool.
+ */
+ public void execute(ClassPool programClassPool) throws IOException
+ {
+ Set newerClassVersions = configuration.warn != null ? null : new HashSet();
+
+ programClassPool.classesAccept(new ClassVersionSetter(configuration.targetClassVersion,
+ newerClassVersions));
+
+ if (newerClassVersions != null &&
+ newerClassVersions.size() > 0)
+ {
+ System.err.print("Warning: some classes have more recent versions (");
+
+ Iterator iterator = newerClassVersions.iterator();
+ while (iterator.hasNext())
+ {
+ Integer classVersion = (Integer)iterator.next();
+ System.err.print(ClassUtil.externalClassVersion(classVersion.intValue()));
+
+ if (iterator.hasNext())
+ {
+ System.err.print(",");
+ }
+ }
+
+ System.err.println(")");
+ System.err.println(" than the target version ("+ClassUtil.externalClassVersion(configuration.targetClassVersion)+").");
+
+ if (!configuration.ignoreWarnings)
+ {
+ System.err.println(" If you are sure this is not a problem,");
+ System.err.println(" you could try your luck using the '-ignorewarnings' option.");
+ throw new IOException("Please correct the above warnings first.");
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/UpToDateChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/UpToDateChecker.java
new file mode 100644
index 0000000000..97c4aea95f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/UpToDateChecker.java
@@ -0,0 +1,232 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.io.File;
+
+/**
+ * This class checks whether the output is up to date.
+ *
+ * @author Eric Lafortune
+ */
+public class UpToDateChecker
+{
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new UpToDateChecker with the given configuration.
+ */
+ public UpToDateChecker(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Returns whether the output is up to date, based on the modification times
+ * of the input jars, output jars, and library jars (or directories).
+ */
+ public boolean check()
+ {
+ try
+ {
+ ModificationTimeChecker checker = new ModificationTimeChecker();
+
+ checker.updateInputModificationTime(configuration.lastModified);
+
+ ClassPath programJars = configuration.programJars;
+ ClassPath libraryJars = configuration.libraryJars;
+
+ // Check the dates of the program jars, if any.
+ if (programJars != null)
+ {
+ for (int index = 0; index < programJars.size(); index++)
+ {
+ // Update the input and output modification times.
+ ClassPathEntry classPathEntry = programJars.get(index);
+
+ checker.updateModificationTime(classPathEntry.getFile(),
+ classPathEntry.isOutput());
+ }
+ }
+
+ // Check the dates of the library jars, if any.
+ if (libraryJars != null)
+ {
+ for (int index = 0; index < libraryJars.size(); index++)
+ {
+ // Update the input modification time.
+ ClassPathEntry classPathEntry = libraryJars.get(index);
+
+ checker.updateModificationTime(classPathEntry.getFile(),
+ false);
+ }
+ }
+
+ // Check the dates of the auxiliary input files.
+ checker.updateInputModificationTime(configuration.applyMapping);
+ checker.updateInputModificationTime(configuration.obfuscationDictionary);
+ checker.updateInputModificationTime(configuration.classObfuscationDictionary);
+ checker.updateInputModificationTime(configuration.packageObfuscationDictionary);
+
+ // Check the dates of the auxiliary output files.
+ checker.updateOutputModificationTime(configuration.printSeeds);
+ checker.updateOutputModificationTime(configuration.printUsage);
+ checker.updateOutputModificationTime(configuration.printMapping);
+ checker.updateOutputModificationTime(configuration.printConfiguration);
+ checker.updateOutputModificationTime(configuration.dump);
+ }
+ catch (IllegalStateException e)
+ {
+ // The output is outdated.
+ return false;
+ }
+
+ System.out.println("The output seems up to date");
+
+ return true;
+ }
+
+
+ /**
+ * This class maintains the modification times of input and output.
+ * The methods throw an IllegalStateException if the output appears
+ * outdated.
+ */
+ private static class ModificationTimeChecker {
+
+ private long inputModificationTime = Long.MIN_VALUE;
+ private long outputModificationTime = Long.MAX_VALUE;
+
+
+ /**
+ * Updates the input modification time based on the given file or
+ * directory (recursively).
+ */
+ public void updateInputModificationTime(File file)
+ {
+ if (file != null)
+ {
+ updateModificationTime(file, false);
+ }
+ }
+
+
+ /**
+ * Updates the input modification time based on the given file or
+ * directory (recursively).
+ */
+ public void updateOutputModificationTime(File file)
+ {
+ if (file != null && file.getName().length() > 0)
+ {
+ updateModificationTime(file, true);
+ }
+ }
+
+
+ /**
+ * Updates the specified modification time based on the given file or
+ * directory (recursively).
+ */
+ public void updateModificationTime(File file, boolean isOutput)
+ {
+ // Is it a directory?
+ if (file.isDirectory())
+ {
+ // Ignore the directory's modification time; just recurse on
+ // its files.
+ File[] files = file.listFiles();
+
+ // Still, an empty output directory is probably a sign that it
+ // is not up to date.
+ if (files.length == 0 && isOutput)
+ {
+ updateOutputModificationTime(Long.MIN_VALUE);
+ }
+
+ for (int index = 0; index < files.length; index++)
+ {
+ updateModificationTime(files[index], isOutput);
+ }
+ }
+ else
+ {
+ // Update with the file's modification time.
+ updateModificationTime(file.lastModified(), isOutput);
+ }
+ }
+
+
+ /**
+ * Updates the specified modification time.
+ */
+ public void updateModificationTime(long time, boolean isOutput)
+ {
+ if (isOutput)
+ {
+ updateOutputModificationTime(time);
+ }
+ else
+ {
+ updateInputModificationTime(time);
+ }
+ }
+
+
+ /**
+ * Updates the input modification time.
+ */
+ public void updateInputModificationTime(long time)
+ {
+ if (inputModificationTime < time)
+ {
+ inputModificationTime = time;
+
+ checkModificationTimes();
+ }
+ }
+
+
+ /**
+ * Updates the output modification time.
+ */
+ public void updateOutputModificationTime(long time)
+ {
+ if (outputModificationTime > time)
+ {
+ outputModificationTime = time;
+
+ checkModificationTimes();
+ }
+ }
+
+
+ private void checkModificationTimes()
+ {
+ if (inputModificationTime > outputModificationTime)
+ {
+ throw new IllegalStateException("The output is outdated");
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/WordReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/WordReader.java
new file mode 100644
index 0000000000..cc7cebd860
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/WordReader.java
@@ -0,0 +1,387 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.io.*;
+
+
+/**
+ * An abstract reader of words, with the possibility to include other readers.
+ * Words are separated by spaces or broken off at delimiters. Words containing
+ * spaces or delimiters can be quoted with single or double quotes.
+ * Comments (everything starting with '#' on a single line) are ignored.
+ *
+ * @author Eric Lafortune
+ * @noinspection TailRecursion
+ */
+public abstract class WordReader
+{
+ private static final char COMMENT_CHARACTER = '#';
+
+
+ private File baseDir;
+ private WordReader includeWordReader;
+ private String currentLine;
+ private int currentLineLength;
+ private int currentIndex;
+ private String currentWord;
+ private String currentComments;
+
+
+ /**
+ * Creates a new WordReader with the given base directory.
+ */
+ protected WordReader(File baseDir)
+ {
+ this.baseDir = baseDir;
+ }
+
+
+ /**
+ * Sets the base directory of this reader.
+ */
+ public void setBaseDir(File baseDir)
+ {
+ if (includeWordReader != null)
+ {
+ includeWordReader.setBaseDir(baseDir);
+ }
+ else
+ {
+ this.baseDir = baseDir;
+ }
+ }
+
+
+ /**
+ * Returns the base directory of this reader, if any.
+ */
+ public File getBaseDir()
+ {
+ return includeWordReader != null ?
+ includeWordReader.getBaseDir() :
+ baseDir;
+ }
+
+
+ /**
+ * Specifies to start reading words from the given WordReader. When it is
+ * exhausted, this WordReader will continue to provide its own words.
+ *
+ * @param newIncludeWordReader the WordReader that will start reading words.
+ */
+ public void includeWordReader(WordReader newIncludeWordReader)
+ {
+ if (includeWordReader == null)
+ {
+ includeWordReader = newIncludeWordReader;
+ }
+ else
+ {
+ includeWordReader.includeWordReader(newIncludeWordReader);
+ }
+ }
+
+
+ /**
+ * Reads a word from this WordReader, or from one of its active included
+ * WordReader objects.
+ *
+ * @param isFileName return a complete line (or argument), if the word
+ * isn't an option (it doesn't start with '-').
+ * @return the read word.
+ */
+ public String nextWord(boolean isFileName) throws IOException
+ {
+ currentWord = null;
+
+ // See if we have an included reader to produce a word.
+ if (includeWordReader != null)
+ {
+ // Does the included word reader still produce a word?
+ currentWord = includeWordReader.nextWord(isFileName);
+ if (currentWord != null)
+ {
+ // Return it if so.
+ return currentWord;
+ }
+
+ // Otherwise close and ditch the word reader.
+ includeWordReader.close();
+ includeWordReader = null;
+ }
+
+ // Get a word from this reader.
+
+ // Skip any whitespace and comments left on the current line.
+ if (currentLine != null)
+ {
+ // Skip any leading whitespace.
+ while (currentIndex < currentLineLength &&
+ Character.isWhitespace(currentLine.charAt(currentIndex)))
+ {
+ currentIndex++;
+ }
+
+ // Skip any comments.
+ if (currentIndex < currentLineLength &&
+ isComment(currentLine.charAt(currentIndex)))
+ {
+ currentIndex = currentLineLength;
+ }
+ }
+
+ // Make sure we have a non-blank line.
+ while (currentLine == null || currentIndex == currentLineLength)
+ {
+ currentLine = nextLine();
+ if (currentLine == null)
+ {
+ return null;
+ }
+
+ currentLineLength = currentLine.length();
+
+ // Skip any leading whitespace.
+ currentIndex = 0;
+ while (currentIndex < currentLineLength &&
+ Character.isWhitespace(currentLine.charAt(currentIndex)))
+ {
+ currentIndex++;
+ }
+
+ // Remember any leading comments.
+ if (currentIndex < currentLineLength &&
+ isComment(currentLine.charAt(currentIndex)))
+ {
+ // Remember the comments.
+ String comment = currentLine.substring(currentIndex + 1);
+ currentComments = currentComments == null ?
+ comment :
+ currentComments + '\n' + comment;
+
+ // Skip the comments.
+ currentIndex = currentLineLength;
+ }
+ }
+
+ // Find the word starting at the current index.
+ int startIndex = currentIndex;
+ int endIndex;
+
+ char startChar = currentLine.charAt(startIndex);
+
+ if (isQuote(startChar))
+ {
+ // The next word is starting with a quote character.
+ // Skip the opening quote.
+ startIndex++;
+
+ // The next word is a quoted character string.
+ // Find the closing quote.
+ do
+ {
+ currentIndex++;
+
+ if (currentIndex == currentLineLength)
+ {
+ currentWord = currentLine.substring(startIndex-1, currentIndex);
+ throw new IOException("Missing closing quote for "+locationDescription());
+ }
+ }
+ while (currentLine.charAt(currentIndex) != startChar);
+
+ endIndex = currentIndex++;
+ }
+ else if (isFileName &&
+ !isOption(startChar))
+ {
+ // The next word is a (possibly optional) file name.
+ // Find the end of the line, the first path separator, the first
+ // option, or the first comment.
+ while (currentIndex < currentLineLength)
+ {
+ char currentCharacter = currentLine.charAt(currentIndex);
+ if (isFileDelimiter(currentCharacter) ||
+ ((isOption(currentCharacter) ||
+ isComment(currentCharacter)) &&
+ Character.isWhitespace(currentLine.charAt(currentIndex-1)))) {
+ break;
+ }
+
+ currentIndex++;
+ }
+
+ endIndex = currentIndex;
+
+ // Trim any trailing whitespace.
+ while (endIndex > startIndex &&
+ Character.isWhitespace(currentLine.charAt(endIndex-1)))
+ {
+ endIndex--;
+ }
+ }
+ else if (isDelimiter(startChar))
+ {
+ // The next word is a single delimiting character.
+ endIndex = ++currentIndex;
+ }
+ else
+ {
+ // The next word is a simple character string.
+ // Find the end of the line, the first delimiter, or the first
+ // white space.
+ while (currentIndex < currentLineLength)
+ {
+ char currentCharacter = currentLine.charAt(currentIndex);
+ if (isDelimiter(currentCharacter) ||
+ Character.isWhitespace(currentCharacter) ||
+ isComment(currentCharacter)) {
+ break;
+ }
+
+ currentIndex++;
+ }
+
+ endIndex = currentIndex;
+ }
+
+ // Remember and return the parsed word.
+ currentWord = currentLine.substring(startIndex, endIndex);
+
+ return currentWord;
+ }
+
+
+ /**
+ * Returns the comments collected before returning the last word.
+ * Starts collecting new comments.
+ *
+ * @return the collected comments, or <code>null</code> if there weren't any.
+ */
+ public String lastComments() throws IOException
+ {
+ if (includeWordReader == null)
+ {
+ String comments = currentComments;
+ currentComments = null;
+ return comments;
+ }
+ else
+ {
+ return includeWordReader.lastComments();
+ }
+ }
+
+
+ /**
+ * Constructs a readable description of the current position in this
+ * WordReader and its included WordReader objects.
+ *
+ * @return the description.
+ */
+ public String locationDescription()
+ {
+ return
+ (includeWordReader == null ?
+ (currentWord == null ?
+ "end of " :
+ "'" + currentWord + "' in " ) :
+ (includeWordReader.locationDescription() + ",\n" +
+ " included from ")) +
+ lineLocationDescription();
+ }
+
+
+ /**
+ * Reads a line from this WordReader, or from one of its active included
+ * WordReader objects.
+ *
+ * @return the read line.
+ */
+ protected abstract String nextLine() throws IOException;
+
+
+ /**
+ * Returns a readable description of the current WordReader position.
+ *
+ * @return the description.
+ */
+ protected abstract String lineLocationDescription();
+
+
+ /**
+ * Closes the FileWordReader.
+ */
+ public void close() throws IOException
+ {
+ // Close and ditch the included word reader, if any.
+ if (includeWordReader != null)
+ {
+ includeWordReader.close();
+ includeWordReader = null;
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean isOption(char character)
+ {
+ return character == '-';
+ }
+
+
+ private boolean isComment(char character)
+ {
+ return character == COMMENT_CHARACTER;
+ }
+
+
+ private boolean isDelimiter(char character)
+ {
+ return character == '@' ||
+ character == '{' ||
+ character == '}' ||
+ character == '(' ||
+ character == ')' ||
+ character == ',' ||
+ character == ';' ||
+ character == File.pathSeparatorChar;
+ }
+
+
+ private boolean isFileDelimiter(char character)
+ {
+ return character == '(' ||
+ character == ')' ||
+ character == ',' ||
+ character == ';' ||
+ character == File.pathSeparatorChar;
+ }
+
+
+ private boolean isQuote(char character)
+ {
+ return character == '\'' ||
+ character == '"';
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ClassPathElement.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ClassPathElement.java
new file mode 100644
index 0000000000..e87fb4ce60
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ClassPathElement.java
@@ -0,0 +1,207 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.ant;
+
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.types.*;
+import proguard.*;
+import proguard.util.ListUtil;
+
+import java.io.File;
+
+/**
+ * This FileSet represents a class path entry (or a set of class path entries)
+ * in Ant.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassPathElement extends Path
+{
+ private String filter;
+ private String apkFilter;
+ private String jarFilter;
+ private String aarFilter;
+ private String warFilter;
+ private String earFilter;
+ private String zipFilter;
+
+
+ /**
+ * @see Path#Path(Project)
+ */
+ public ClassPathElement(Project project)
+ {
+ super(project);
+ }
+
+
+ /**
+ * Adds the contents of this class path element to the given class path.
+ * @param classPath the class path to be extended.
+ * @param output specifies whether this is an output entry or not.
+ */
+ public void appendClassPathEntriesTo(ClassPath classPath, boolean output)
+ {
+ File baseDir = getProject().getBaseDir();
+ String[] fileNames;
+
+ if (isReference())
+ {
+ // Get the referenced path or file set.
+ Object referencedObject = getCheckedRef(DataType.class,
+ DataType.class.getName());
+
+ if (referencedObject instanceof Path)
+ {
+ Path path = (Path)referencedObject;
+
+ // Get the names of the files in the referenced path.
+ fileNames = path.list();
+ }
+ else if (referencedObject instanceof AbstractFileSet)
+ {
+ AbstractFileSet fileSet = (AbstractFileSet)referencedObject;
+
+ // Get the names of the existing input files in the referenced file set.
+ DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject());
+ baseDir = scanner.getBasedir();
+ fileNames = scanner.getIncludedFiles();
+ }
+ else
+ {
+ throw new BuildException("The refid attribute doesn't point to a <path> element or a <fileset> element");
+ }
+ }
+ else
+ {
+ // Get the names of the files in this path.
+ fileNames = list();
+ }
+
+ if (output)
+ {
+ if (fileNames.length != 1)
+ {
+ throw new BuildException("The <outjar> element must specify exactly one file or directory ["+fileNames.length+"]");
+ }
+ }
+ //else
+ //{
+ // if (fileNames.length < 1)
+ // {
+ // throw new BuildException("The <injar> element must specify at least one file or directory");
+ // }
+ //}
+
+ for (int index = 0; index < fileNames.length; index++)
+ {
+ // Create a new class path entry, with the proper file name and
+ // any filters.
+ String fileName = fileNames[index];
+ File file = new File(fileName);
+
+ ClassPathEntry entry =
+ new ClassPathEntry(file.isAbsolute() ? file : new File(baseDir, fileName),
+ output);
+ entry.setFilter(ListUtil.commaSeparatedList(filter));
+ entry.setApkFilter(ListUtil.commaSeparatedList(apkFilter));
+ entry.setJarFilter(ListUtil.commaSeparatedList(jarFilter));
+ entry.setAarFilter(ListUtil.commaSeparatedList(aarFilter));
+ entry.setWarFilter(ListUtil.commaSeparatedList(warFilter));
+ entry.setEarFilter(ListUtil.commaSeparatedList(earFilter));
+ entry.setZipFilter(ListUtil.commaSeparatedList(zipFilter));
+
+ // Add it to the class path.
+ classPath.add(entry);
+ }
+ }
+
+
+ // Ant task attributes.
+
+ /**
+ * @deprecated Use {@link #setLocation(File)} instead.
+ */
+ public void setFile(File file)
+ {
+ setLocation(file);
+ }
+
+
+ /**
+ * @deprecated Use {@link #setLocation(File)} instead.
+ */
+ public void setDir(File file)
+ {
+ setLocation(file);
+ }
+
+
+ /**
+ * @deprecated Use {@link #setLocation(File)} instead.
+ */
+ public void setName(File file)
+ {
+ setLocation(file);
+ }
+
+
+ public void setFilter(String filter)
+ {
+ this.filter = filter;
+ }
+
+
+ public void setApkfilter(String apkFilter)
+ {
+ this.apkFilter = apkFilter;
+ }
+
+
+ public void setJarfilter(String jarFilter)
+ {
+ this.jarFilter = jarFilter;
+ }
+
+
+ public void setAarfilter(String aarFilter)
+ {
+ this.aarFilter = aarFilter;
+ }
+
+
+ public void setWarfilter(String warFilter)
+ {
+ this.warFilter = warFilter;
+ }
+
+
+ public void setEarfilter(String earFilter)
+ {
+ this.earFilter = earFilter;
+ }
+
+
+ public void setZipfilter(String zipFilter)
+ {
+ this.zipFilter = zipFilter;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ClassSpecificationElement.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ClassSpecificationElement.java
new file mode 100644
index 0000000000..a765b1856f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ClassSpecificationElement.java
@@ -0,0 +1,259 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.ant;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.DataType;
+import proguard.*;
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+
+import java.util.*;
+
+/**
+ * This DataType represents a class specification in Ant.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassSpecificationElement extends DataType
+{
+ private static final String ANY_CLASS_KEYWORD = "*";
+
+ private String access;
+ private String annotation;
+ private String type;
+ private String name;
+ private String extendsAnnotation;
+ private String extends_;
+ private List fieldSpecifications = new ArrayList();
+ private List methodSpecifications = new ArrayList();
+
+
+ /**
+ * Adds the contents of this class specification element to the given list.
+ * @param classSpecifications the class specifications to be extended.
+ */
+ public void appendTo(List classSpecifications)
+ {
+ // Get the referenced file set, or else this one.
+ ClassSpecificationElement classSpecificationElement = isReference() ?
+ (ClassSpecificationElement)getCheckedRef(this.getClass(),
+ this.getClass().getName()) :
+ this;
+
+ ClassSpecification classSpecification =
+ createClassSpecification(classSpecificationElement);
+
+ // Add it to the list.
+ classSpecifications.add(classSpecification);
+ }
+
+
+ /**
+ * Creates a new class specification corresponding to the contents of this
+ * class specification element.
+ */
+ protected ClassSpecification createClassSpecification(ClassSpecificationElement classSpecificationElement)
+ {
+ String access = classSpecificationElement.access;
+ String annotation = classSpecificationElement.annotation;
+ String type = classSpecificationElement.type;
+ String name = classSpecificationElement.name;
+ String extendsAnnotation = classSpecificationElement.extendsAnnotation;
+ String extends_ = classSpecificationElement.extends_;
+
+ // For backward compatibility, allow a single "*" wildcard to match
+ // any class.
+ if (name != null &&
+ name.equals(ANY_CLASS_KEYWORD))
+ {
+ name = null;
+ }
+
+ ClassSpecification classSpecification =
+ new ClassSpecification(null,
+ requiredAccessFlags(true, access, type),
+ requiredAccessFlags(false, access, type),
+ annotation != null ? ClassUtil.internalType(annotation) : null,
+ name != null ? ClassUtil.internalClassName(name) : null,
+ extendsAnnotation != null ? ClassUtil.internalType(extendsAnnotation) : null,
+ extends_ != null ? ClassUtil.internalClassName(extends_) : null);
+
+ for (int index = 0; index < fieldSpecifications.size(); index++)
+ {
+ classSpecification.addField((MemberSpecification)fieldSpecifications.get(index));
+ }
+
+ for (int index = 0; index < methodSpecifications.size(); index++)
+ {
+ classSpecification.addMethod((MemberSpecification)methodSpecifications.get(index));
+ }
+
+ return classSpecification;
+ }
+
+
+ // Ant task attributes.
+
+ public void setAccess(String access)
+ {
+ this.access = access;
+ }
+
+
+ public void setAnnotation(String annotation)
+ {
+ this.annotation = annotation;
+ }
+
+
+ public void setType(String type)
+ {
+ this.type = type;
+ }
+
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+
+ public void setExtendsannotation(String extendsAnnotation)
+ {
+ this.extendsAnnotation = extendsAnnotation;
+ }
+
+
+ public void setExtends(String extends_)
+ {
+ this.extends_ = extends_;
+ }
+
+
+ public void setImplements(String implements_)
+ {
+ this.extends_ = implements_;
+ }
+
+
+ // Ant task nested elements.
+
+ public void addConfiguredField(MemberSpecificationElement memberSpecificationElement)
+ {
+ if (fieldSpecifications == null)
+ {
+ fieldSpecifications = new ArrayList();
+ }
+
+ memberSpecificationElement.appendTo(fieldSpecifications,
+ false,
+ false);
+ }
+
+
+ public void addConfiguredMethod(MemberSpecificationElement memberSpecificationElement)
+ {
+ if (methodSpecifications == null)
+ {
+ methodSpecifications = new ArrayList();
+ }
+
+ memberSpecificationElement.appendTo(methodSpecifications,
+ true,
+ false);
+ }
+
+
+ public void addConfiguredConstructor(MemberSpecificationElement memberSpecificationElement)
+ {
+ if (methodSpecifications == null)
+ {
+ methodSpecifications = new ArrayList();
+ }
+
+ memberSpecificationElement.appendTo(methodSpecifications,
+ true,
+ true);
+ }
+
+
+ // Small utility methods.
+
+ private int requiredAccessFlags(boolean set,
+ String access,
+ String type)
+ throws BuildException
+ {
+ int accessFlags = 0;
+
+ if (access != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(access, " ,");
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken();
+
+ if (token.startsWith("!") ^ set)
+ {
+ String strippedToken = token.startsWith("!") ?
+ token.substring(1) :
+ token;
+
+ int accessFlag =
+ strippedToken.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC :
+ strippedToken.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL :
+ strippedToken.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT :
+ strippedToken.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC :
+ strippedToken.equals(JavaConstants.ACC_ANNOTATION) ? ClassConstants.ACC_ANNOTATTION :
+ 0;
+
+ if (accessFlag == 0)
+ {
+ throw new BuildException("Incorrect class access modifier ["+strippedToken+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+ }
+ }
+
+ if (type != null && (type.startsWith("!") ^ set))
+ {
+ int accessFlag =
+ type.equals("class") ? 0 :
+ type.equals( JavaConstants.ACC_INTERFACE) ||
+ type.equals("!" + JavaConstants.ACC_INTERFACE) ? ClassConstants.ACC_INTERFACE :
+ type.equals( JavaConstants.ACC_ENUM) ||
+ type.equals("!" + JavaConstants.ACC_ENUM) ? ClassConstants.ACC_ENUM :
+ -1;
+
+ if (accessFlag == -1)
+ {
+ throw new BuildException("Incorrect class type ["+type+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+
+ return accessFlags;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ConfigurationElement.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ConfigurationElement.java
new file mode 100644
index 0000000000..e98cbee1ee
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ConfigurationElement.java
@@ -0,0 +1,123 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.ant;
+
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.types.*;
+import proguard.*;
+
+import java.io.*;
+import java.util.Properties;
+
+/**
+ * This DataType represents a reference to an XML-style ProGuard configuration
+ * in Ant, or a file set of ProGuard-style configuration files.
+ *
+ * @author Eric Lafortune
+ */
+public class ConfigurationElement extends FileSet
+{
+ /**
+ * Adds the contents of this configuration element to the given
+ * configuration.
+ * @param configuration the configuration to be extended.
+ */
+ public void appendTo(Configuration configuration)
+ {
+ File baseDir;
+ String[] fileNames;
+
+ if (isReference())
+ {
+ // Get the referenced path or file set.
+ Object referencedObject = getCheckedRef(Object.class,
+ Object.class.getName());
+
+ if (referencedObject instanceof ConfigurationTask)
+ {
+ // The reference doesn't point to a file set, but to a
+ // configuration task.
+ ConfigurationTask configurationTask =
+ (ConfigurationTask)referencedObject;
+
+ // Append the contents of the referenced configuration to the
+ // current configuration.
+ configurationTask.appendTo(configuration);
+
+ return;
+ }
+ else if (referencedObject instanceof AbstractFileSet)
+ {
+ AbstractFileSet fileSet = (AbstractFileSet)referencedObject;
+
+ // Get the names of the existing input files in the referenced file set.
+ DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject());
+ baseDir = scanner.getBasedir();
+ fileNames = scanner.getIncludedFiles();
+ }
+ else
+ {
+ throw new BuildException("The refid attribute doesn't point to a <proguardconfiguration> element or a <fileset> element");
+ }
+ }
+ else
+ {
+ // Get the names of the existing input files in the referenced file set.
+ DirectoryScanner scanner = getDirectoryScanner(getProject());
+ baseDir = scanner.getBasedir();
+ fileNames = scanner.getIncludedFiles();
+ }
+
+ // Get the combined system properties and Ant properties, for
+ // replacing ProGuard-style properties ('<...>').
+ Properties properties = new Properties();
+ properties.putAll(getProject().getProperties());
+
+ try
+ {
+ // Append the contents of the configuration files to the current
+ // configuration.
+ for (int index = 0; index < fileNames.length; index++)
+ {
+ File configurationFile = new File(baseDir, fileNames[index]);
+
+ ConfigurationParser parser =
+ new ConfigurationParser(configurationFile, properties);
+ try
+ {
+ parser.parse(configuration);
+ }
+ catch (ParseException ex)
+ {
+ throw new BuildException(ex.getMessage());
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ }
+ catch (IOException ex)
+ {
+ throw new BuildException(ex.getMessage());
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ConfigurationTask.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ConfigurationTask.java
new file mode 100644
index 0000000000..44979acba6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ConfigurationTask.java
@@ -0,0 +1,450 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.ant;
+
+import org.apache.tools.ant.*;
+import proguard.*;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * This Task allows to define a ProGuard configuration from Ant.
+ *
+ * @author Eric Lafortune
+ */
+public class ConfigurationTask extends Task
+{
+ protected final Configuration configuration = new Configuration();
+
+
+ /**
+ * Adds the contents of this configuration task to the given configuration.
+ * @param configuration the configuration to be extended.
+ */
+ public void appendTo(Configuration configuration)
+ {
+ // Append all of these configuration entries to the given configuration.
+ configuration.programJars = extendClassPath(configuration.programJars,
+ this.configuration.programJars);
+
+ configuration.libraryJars = extendClassPath(configuration.libraryJars,
+ this.configuration.libraryJars);
+
+ configuration.keep = extendClassSpecifications(configuration.keep,
+ this.configuration.keep);
+
+ configuration.keepDirectories = extendList(configuration.keepDirectories,
+ this.configuration.keepDirectories);
+
+ configuration.whyAreYouKeeping = extendClassSpecifications(configuration.whyAreYouKeeping,
+ this.configuration.whyAreYouKeeping);
+
+ configuration.optimizations = extendClassSpecifications(configuration.optimizations,
+ this.configuration.optimizations);
+
+ configuration.assumeNoSideEffects = extendClassSpecifications(configuration.assumeNoSideEffects,
+ this.configuration.assumeNoSideEffects);
+
+ configuration.keepPackageNames = extendList(configuration.keepPackageNames,
+ this.configuration.keepPackageNames);
+
+ configuration.keepAttributes = extendList(configuration.keepAttributes,
+ this.configuration.keepAttributes);
+
+ configuration.adaptClassStrings = extendList(configuration.adaptClassStrings,
+ this.configuration.adaptClassStrings);
+
+ configuration.adaptResourceFileNames = extendList(configuration.adaptResourceFileNames,
+ this.configuration.adaptResourceFileNames);
+
+ configuration.adaptResourceFileContents = extendList(configuration.adaptResourceFileContents,
+ this.configuration.adaptResourceFileContents);
+
+ configuration.note = extendList(configuration.note,
+ this.configuration.note);
+
+ configuration.warn = extendList(configuration.warn,
+ this.configuration.warn);
+ }
+
+
+ // Ant task nested elements.
+
+ public void addConfiguredInjar(ClassPathElement classPathElement)
+ {
+ configuration.programJars = extendClassPath(configuration.programJars,
+ classPathElement,
+ false);
+ }
+
+
+ public void addConfiguredOutjar(ClassPathElement classPathElement)
+ {
+ configuration.programJars = extendClassPath(configuration.programJars,
+ classPathElement,
+ true);
+ }
+
+
+ public void addConfiguredLibraryjar(ClassPathElement classPathElement)
+ {
+ configuration.libraryJars = extendClassPath(configuration.libraryJars,
+ classPathElement,
+ false);
+ }
+
+
+ public void addConfiguredKeepdirectory(FilterElement filterElement)
+ {
+ configuration.keepDirectories = extendFilter(configuration.keepDirectories,
+ filterElement);
+ }
+
+
+ public void addConfiguredKeepdirectories(FilterElement filterElement)
+ {
+ configuration.keepDirectories = extendFilter(configuration.keepDirectories,
+ filterElement);
+ }
+
+
+ public void addConfiguredKeep(KeepSpecificationElement keepSpecificationElement)
+ {
+ configuration.keep = extendKeepSpecifications(configuration.keep,
+ keepSpecificationElement,
+ true,
+ false);
+ }
+
+
+ public void addConfiguredKeepclassmembers(KeepSpecificationElement keepSpecificationElement)
+ {
+ configuration.keep = extendKeepSpecifications(configuration.keep,
+ keepSpecificationElement,
+ false,
+ false);
+ }
+
+
+ public void addConfiguredKeepclasseswithmembers(KeepSpecificationElement keepSpecificationElement)
+ {
+ configuration.keep = extendKeepSpecifications(configuration.keep,
+ keepSpecificationElement,
+ true,
+ true);
+ }
+
+
+ public void addConfiguredKeepnames(KeepSpecificationElement keepSpecificationElement)
+ {
+ // Set the shrinking flag, based on the name (backward compatibility).
+ keepSpecificationElement.setAllowshrinking(true);
+
+ configuration.keep = extendKeepSpecifications(configuration.keep,
+ keepSpecificationElement,
+ true,
+ false);
+ }
+
+
+ public void addConfiguredKeepclassmembernames(KeepSpecificationElement keepSpecificationElement)
+ {
+ // Set the shrinking flag, based on the name (backward compatibility).
+ keepSpecificationElement.setAllowshrinking(true);
+
+ configuration.keep = extendKeepSpecifications(configuration.keep,
+ keepSpecificationElement,
+ false,
+ false);
+ }
+
+
+ public void addConfiguredKeepclasseswithmembernames(KeepSpecificationElement keepSpecificationElement)
+ {
+ // Set the shrinking flag, based on the name (backward compatibility).
+ keepSpecificationElement.setAllowshrinking(true);
+
+ configuration.keep = extendKeepSpecifications(configuration.keep,
+ keepSpecificationElement,
+ true,
+ true);
+ }
+
+
+ public void addConfiguredWhyareyoukeeping(ClassSpecificationElement classSpecificationElement)
+ {
+ configuration.whyAreYouKeeping = extendClassSpecifications(configuration.whyAreYouKeeping,
+ classSpecificationElement);
+ }
+
+
+ public void addConfiguredAssumenosideeffects(ClassSpecificationElement classSpecificationElement)
+ {
+ configuration.assumeNoSideEffects = extendClassSpecifications(configuration.assumeNoSideEffects,
+ classSpecificationElement);
+ }
+
+
+ public void addConfiguredOptimizations(FilterElement filterElement)
+ {
+ addConfiguredOptimization(filterElement);
+ }
+
+
+ public void addConfiguredOptimization(FilterElement filterElement)
+ {
+ configuration.optimizations = extendFilter(configuration.optimizations,
+ filterElement);
+ }
+
+
+ public void addConfiguredKeeppackagename(FilterElement filterElement)
+ {
+ configuration.keepPackageNames = extendFilter(configuration.keepPackageNames,
+ filterElement,
+ true);
+ }
+
+
+ public void addConfiguredKeeppackagenames(FilterElement filterElement)
+ {
+ configuration.keepPackageNames = extendFilter(configuration.keepPackageNames,
+ filterElement,
+ true);
+ }
+
+
+ public void addConfiguredKeepattributes(FilterElement filterElement)
+ {
+ addConfiguredKeepattribute(filterElement);
+ }
+
+
+ public void addConfiguredKeepattribute(FilterElement filterElement)
+ {
+ configuration.keepAttributes = extendFilter(configuration.keepAttributes,
+ filterElement);
+ }
+
+
+ public void addConfiguredAdaptclassstrings(FilterElement filterElement)
+ {
+ configuration.adaptClassStrings = extendFilter(configuration.adaptClassStrings,
+ filterElement, true);
+ }
+
+
+ public void addConfiguredAdaptresourcefilenames(FilterElement filterElement)
+ {
+ configuration.adaptResourceFileNames = extendFilter(configuration.adaptResourceFileNames,
+ filterElement);
+ }
+
+
+ public void addConfiguredAdaptresourcefilecontents(FilterElement filterElement)
+ {
+ configuration.adaptResourceFileContents = extendFilter(configuration.adaptResourceFileContents,
+ filterElement);
+ }
+
+
+ public void addConfiguredDontnote(FilterElement filterElement)
+ {
+ configuration.note = extendFilter(configuration.note, filterElement, true);
+ }
+
+
+ public void addConfiguredDontwarn(FilterElement filterElement)
+ {
+ configuration.warn = extendFilter(configuration.warn, filterElement, true);
+ }
+
+
+ public void addConfiguredConfiguration(ConfigurationElement configurationElement)
+ {
+ configurationElement.appendTo(configuration);
+ }
+
+
+ // Implementations for Task.
+
+ public void addText(String text) throws BuildException
+ {
+ try
+ {
+ Project project = getProject();
+
+ // Replace Ant-style properties ('${...}').
+ String arg = project.replaceProperties(text);
+
+ // Get the combined system properties and Ant properties, for
+ // replacing ProGuard-style properties ('<...>').
+ Properties properties = new Properties();
+ properties.putAll(project.getProperties());
+
+ ConfigurationParser parser = new ConfigurationParser(arg,
+ "embedded configuration",
+ project.getBaseDir(),
+ properties);
+
+ try
+ {
+ parser.parse(configuration);
+ }
+ catch (ParseException ex)
+ {
+ throw new BuildException(ex.getMessage());
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ catch (IOException ex)
+ {
+ throw new BuildException(ex.getMessage());
+ }
+ }
+
+
+ // Small utility methods.
+
+ private ClassPath extendClassPath(ClassPath classPath,
+ ClassPathElement classPathElement,
+ boolean output)
+ {
+ if (classPath == null)
+ {
+ classPath = new ClassPath();
+ }
+
+ classPathElement.appendClassPathEntriesTo(classPath,
+ output);
+
+ return classPath;
+ }
+
+
+ private ClassPath extendClassPath(ClassPath classPath,
+ ClassPath additionalClassPath)
+ {
+ if (additionalClassPath != null)
+ {
+ if (classPath == null)
+ {
+ classPath = new ClassPath();
+ }
+
+ classPath.addAll(additionalClassPath);
+ }
+
+ return classPath;
+ }
+
+
+ private List extendKeepSpecifications(List keepSpecifications,
+ KeepSpecificationElement keepSpecificationElement,
+ boolean markClasses,
+ boolean markClassesConditionally)
+ {
+ if (keepSpecifications == null)
+ {
+ keepSpecifications = new ArrayList();
+ }
+
+ keepSpecificationElement.appendTo(keepSpecifications,
+ markClasses,
+ markClassesConditionally);
+
+ return keepSpecifications;
+ }
+
+
+ private List extendClassSpecifications(List classSpecifications,
+ ClassSpecificationElement classSpecificationElement)
+ {
+ if (classSpecifications == null)
+ {
+ classSpecifications = new ArrayList();
+ }
+
+ classSpecificationElement.appendTo(classSpecifications);
+
+ return classSpecifications;
+ }
+
+
+ private List extendClassSpecifications(List classSpecifications,
+ List additionalClassSpecifications)
+ {
+ if (additionalClassSpecifications != null)
+ {
+ if (classSpecifications == null)
+ {
+ classSpecifications = new ArrayList();
+ }
+
+ classSpecifications.addAll(additionalClassSpecifications);
+ }
+
+ return classSpecifications;
+ }
+
+
+ private List extendFilter(List filter,
+ FilterElement filterElement)
+ {
+ return extendFilter(filter, filterElement, false);
+ }
+
+
+ private List extendFilter(List filter,
+ FilterElement filterElement,
+ boolean internal)
+ {
+ if (filter == null)
+ {
+ filter = new ArrayList();
+ }
+
+ filterElement.appendTo(filter, internal);
+
+ return filter;
+ }
+
+
+ private List extendList(List list,
+ List additionalList)
+ {
+ if (additionalList != null)
+ {
+ if (list == null)
+ {
+ list = new ArrayList();
+ }
+
+ list.addAll(additionalList);
+ }
+
+ return list;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ant/FilterElement.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/FilterElement.java
new file mode 100644
index 0000000000..b9323cf5ef
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/FilterElement.java
@@ -0,0 +1,85 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.ant;
+
+import org.apache.tools.ant.types.DataType;
+import proguard.classfile.util.ClassUtil;
+import proguard.util.ListUtil;
+
+import java.util.List;
+
+/**
+ * This DataType represents a name filter in Ant.
+ *
+ * @author Eric Lafortune
+ */
+public class FilterElement extends DataType
+{
+ private String filter;
+
+
+ /**
+ * Adds the contents of this element to the given name filter.
+ * @param filter the list of attributes to be extended.
+ * @param internal specifies whether the filter string should be converted
+ * to internal types.
+ */
+ public void appendTo(List filter, boolean internal)
+ {
+ // Get the referenced element, or else this one.
+ FilterElement filterElement = isReference() ?
+ (FilterElement)getCheckedRef(this.getClass(),
+ this.getClass().getName()) :
+ this;
+
+ String filterString = filterElement.filter;
+
+ if (filterString == null)
+ {
+ // Clear the filter to keep all names.
+ filter.clear();
+ }
+ else
+ {
+ if (internal)
+ {
+ filterString = ClassUtil.internalClassName(filterString);
+ }
+
+ // Append the filter.
+ filter.addAll(ListUtil.commaSeparatedList(filterString));
+ }
+ }
+
+
+ // Ant task attributes.
+
+ public void setName(String name)
+ {
+ this.filter = name;
+ }
+
+
+ public void setFilter(String filter)
+ {
+ this.filter = filter;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ant/KeepSpecificationElement.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/KeepSpecificationElement.java
new file mode 100644
index 0000000000..dec01361e8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/KeepSpecificationElement.java
@@ -0,0 +1,95 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.ant;
+
+import proguard.KeepClassSpecification;
+
+import java.util.List;
+
+/**
+ * This DataType represents a class specification in Ant.
+ *
+ * @author Eric Lafortune
+ */
+public class KeepSpecificationElement extends ClassSpecificationElement
+{
+ private boolean markDescriptorClasses;
+ private boolean allowShrinking;
+ private boolean allowOptimization;
+ private boolean allowObfuscation;
+
+
+ /**
+ * Adds the contents of this class specification element to the given list.
+ * @param keepSpecifications the class specifications to be extended.
+ * @param markClasses specifies whether to mark the classes.
+ * @param markConditionally specifies whether to mark the classes
+ * and class members conditionally.
+ */
+ public void appendTo(List keepSpecifications,
+ boolean markClasses,
+ boolean markConditionally)
+ {
+ // Get the referenced file set, or else this one.
+ KeepSpecificationElement keepSpecificationElement = isReference() ?
+ (KeepSpecificationElement)getCheckedRef(this.getClass(),
+ this.getClass().getName()) :
+ this;
+
+ KeepClassSpecification keepClassSpecification =
+ new KeepClassSpecification(markClasses,
+ markConditionally,
+ markDescriptorClasses,
+ allowShrinking,
+ allowOptimization,
+ allowObfuscation,
+ createClassSpecification(keepSpecificationElement));
+
+ // Add it to the list.
+ keepSpecifications.add(keepClassSpecification);
+ }
+
+
+ // Ant task attributes.
+
+ public void setIncludedescriptorclasses(boolean markDescriptorClasses)
+ {
+ this.markDescriptorClasses = markDescriptorClasses;
+ }
+
+
+ public void setAllowshrinking(boolean allowShrinking)
+ {
+ this.allowShrinking = allowShrinking;
+ }
+
+
+ public void setAllowoptimization(boolean allowOptimization)
+ {
+ this.allowOptimization = allowOptimization;
+ }
+
+
+ public void setAllowobfuscation(boolean allowObfuscation)
+ {
+ this.allowObfuscation = allowObfuscation;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ant/MemberSpecificationElement.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/MemberSpecificationElement.java
new file mode 100644
index 0000000000..3eb712f601
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/MemberSpecificationElement.java
@@ -0,0 +1,218 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.ant;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.DataType;
+import proguard.MemberSpecification;
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+import proguard.util.ListUtil;
+
+import java.util.*;
+
+/**
+ * This DataType represents a class member specification in Ant.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberSpecificationElement extends DataType
+{
+ private String access;
+ private String annotation;
+ private String type;
+ private String name;
+ private String parameters;
+
+
+ /**
+ * Adds the contents of this class member specification element to the given
+ * list.
+ * @param memberSpecifications the class member specifications to be
+ * extended.
+ * @param isMethod specifies whether this specification
+ * refers to a method.
+ * @param isConstructor specifies whether this specification
+ * refers to a constructor.
+ */
+ public void appendTo(List memberSpecifications,
+ boolean isMethod,
+ boolean isConstructor)
+ {
+ // Get the referenced file set, or else this one.
+ MemberSpecificationElement memberSpecificationElement = isReference() ?
+ (MemberSpecificationElement)getCheckedRef(this.getClass(),
+ this.getClass().getName()) :
+ this;
+
+ // Create a new class member specification.
+ String access = memberSpecificationElement.access;
+ String type = memberSpecificationElement.type;
+ String annotation = memberSpecificationElement.annotation;
+ String name = memberSpecificationElement.name;
+ String parameters = memberSpecificationElement.parameters;
+
+ // Perform some basic conversions and checks on the attributes.
+ if (annotation != null)
+ {
+ annotation = ClassUtil.internalType(annotation);
+ }
+
+ if (isMethod)
+ {
+ if (isConstructor)
+ {
+ if (type != null)
+ {
+ throw new BuildException("Type attribute not allowed in constructor specification ["+type+"]");
+ }
+
+ if (parameters != null)
+ {
+ type = JavaConstants.TYPE_VOID;
+ }
+
+ name = ClassConstants.METHOD_NAME_INIT;
+ }
+ else if ((type != null) ^ (parameters != null))
+ {
+ throw new BuildException("Type and parameters attributes must always be present in combination in method specification");
+ }
+ }
+ else
+ {
+ if (parameters != null)
+ {
+ throw new BuildException("Parameters attribute not allowed in field specification ["+parameters+"]");
+ }
+ }
+
+ List parameterList = ListUtil.commaSeparatedList(parameters);
+
+ String descriptor =
+ parameters != null ? ClassUtil.internalMethodDescriptor(type, parameterList) :
+ type != null ? ClassUtil.internalType(type) :
+ null;
+
+ MemberSpecification memberSpecification =
+ new MemberSpecification(requiredAccessFlags(true, access),
+ requiredAccessFlags(false, access),
+ annotation,
+ name,
+ descriptor);
+
+ // Add it to the list.
+ memberSpecifications.add(memberSpecification);
+ }
+
+
+ // Ant task attributes.
+
+ public void setAccess(String access)
+ {
+ this.access = access;
+ }
+
+
+ public void setAnnotation(String annotation)
+ {
+ this.annotation = annotation;
+ }
+
+
+ public void setType(String type)
+ {
+ this.type = type;
+ }
+
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+
+ public void setParameters(String parameters)
+ {
+ this.parameters = parameters;
+ }
+
+
+ /**
+ * @deprecated Use {@link #setParameters(String)} instead.
+ */
+ public void setParam(String parameters)
+ {
+ this.parameters = parameters;
+ }
+
+
+ // Small utility methods.
+
+ private int requiredAccessFlags(boolean set,
+ String access)
+ throws BuildException
+ {
+ int accessFlags = 0;
+
+ if (access != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(access, " ,");
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken();
+
+ if (token.startsWith("!") ^ set)
+ {
+ String strippedToken = token.startsWith("!") ?
+ token.substring(1) :
+ token;
+
+ int accessFlag =
+ strippedToken.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC :
+ strippedToken.equals(JavaConstants.ACC_PRIVATE) ? ClassConstants.ACC_PRIVATE :
+ strippedToken.equals(JavaConstants.ACC_PROTECTED) ? ClassConstants.ACC_PROTECTED :
+ strippedToken.equals(JavaConstants.ACC_STATIC) ? ClassConstants.ACC_STATIC :
+ strippedToken.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL :
+ strippedToken.equals(JavaConstants.ACC_SYNCHRONIZED) ? ClassConstants.ACC_SYNCHRONIZED :
+ strippedToken.equals(JavaConstants.ACC_VOLATILE) ? ClassConstants.ACC_VOLATILE :
+ strippedToken.equals(JavaConstants.ACC_TRANSIENT) ? ClassConstants.ACC_TRANSIENT :
+ strippedToken.equals(JavaConstants.ACC_BRIDGE) ? ClassConstants.ACC_BRIDGE :
+ strippedToken.equals(JavaConstants.ACC_VARARGS) ? ClassConstants.ACC_VARARGS :
+ strippedToken.equals(JavaConstants.ACC_NATIVE) ? ClassConstants.ACC_NATIVE :
+ strippedToken.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT :
+ strippedToken.equals(JavaConstants.ACC_STRICT) ? ClassConstants.ACC_STRICT :
+ strippedToken.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC :
+ 0;
+
+ if (accessFlag == 0)
+ {
+ throw new BuildException("Incorrect class member access modifier ["+strippedToken+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+ }
+ }
+
+ return accessFlags;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ProGuardTask.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ProGuardTask.java
new file mode 100644
index 0000000000..130ca6535d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/ProGuardTask.java
@@ -0,0 +1,357 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.ant;
+
+import org.apache.tools.ant.BuildException;
+import proguard.*;
+import proguard.classfile.util.ClassUtil;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This Task allows to configure and run ProGuard from Ant.
+ *
+ * @author Eric Lafortune
+ */
+public class ProGuardTask extends ConfigurationTask
+{
+ // Ant task attributes.
+
+ public void setConfiguration(File configurationFile) throws BuildException
+ {
+ try
+ {
+ // Get the combined system properties and Ant properties, for
+ // replacing ProGuard-style properties ('<...>').
+ Properties properties = new Properties();
+ properties.putAll(getProject().getProperties());
+
+ ConfigurationParser parser = new ConfigurationParser(configurationFile,
+ properties);
+ try
+ {
+ parser.parse(configuration);
+ }
+ catch (ParseException e)
+ {
+ throw new BuildException(e.getMessage(), e);
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new BuildException(e.getMessage(), e);
+ }
+ }
+
+
+ /**
+ * @deprecated Use the nested outjar element instead.
+ */
+ public void setOutjar(String parameters)
+ {
+ throw new BuildException("Use the <outjar> nested element instead of the 'outjar' attribute");
+ }
+
+
+ public void setSkipnonpubliclibraryclasses(boolean skipNonPublicLibraryClasses)
+ {
+ configuration.skipNonPublicLibraryClasses = skipNonPublicLibraryClasses;
+ }
+
+
+ public void setSkipnonpubliclibraryclassmembers(boolean skipNonPublicLibraryClassMembers)
+ {
+ configuration.skipNonPublicLibraryClassMembers = skipNonPublicLibraryClassMembers;
+ }
+
+
+ public void setTarget(String target)
+ {
+ configuration.targetClassVersion = ClassUtil.internalClassVersion(target);
+ if (configuration.targetClassVersion == 0)
+ {
+ throw new BuildException("Unsupported target '"+target+"'");
+ }
+ }
+
+
+ public void setForceprocessing(boolean forceProcessing)
+ {
+ configuration.lastModified = forceProcessing ? Long.MAX_VALUE : 0;
+ }
+
+
+ public void setPrintseeds(File printSeeds)
+ {
+ configuration.printSeeds = optionalFile(printSeeds);
+ }
+
+
+ public void setShrink(boolean shrink)
+ {
+ configuration.shrink = shrink;
+ }
+
+
+ public void setPrintusage(File printUsage)
+ {
+ configuration.printUsage = optionalFile(printUsage);
+ }
+
+
+ public void setOptimize(boolean optimize)
+ {
+ configuration.optimize = optimize;
+ }
+
+
+ public void setOptimizationpasses(int optimizationPasses)
+ {
+ configuration.optimizationPasses = optimizationPasses;
+ }
+
+
+ public void setAllowaccessmodification(boolean allowAccessModification)
+ {
+ configuration.allowAccessModification = allowAccessModification;
+ }
+
+
+ public void setMergeinterfacesaggressively(boolean mergeinterfacesaggressively)
+ {
+ configuration.mergeInterfacesAggressively = mergeinterfacesaggressively;
+ }
+
+
+ public void setObfuscate(boolean obfuscate)
+ {
+ configuration.obfuscate = obfuscate;
+ }
+
+
+ public void setPrintmapping(File printMapping)
+ {
+ configuration.printMapping = optionalFile(printMapping);
+ }
+
+
+ public void setApplymapping(File applyMapping)
+ {
+ configuration.applyMapping = resolvedFile(applyMapping);
+ }
+
+
+ public void setObfuscationdictionary(File obfuscationDictionary)
+ {
+ configuration.obfuscationDictionary = resolvedFile(obfuscationDictionary);
+ }
+
+
+ public void setClassobfuscationdictionary(File classObfuscationDictionary)
+ {
+ configuration.classObfuscationDictionary = resolvedFile(classObfuscationDictionary);
+ }
+
+
+ public void setPackageobfuscationdictionary(File packageObfuscationDictionary)
+ {
+ configuration.packageObfuscationDictionary = resolvedFile(packageObfuscationDictionary);
+ }
+
+
+ public void setOverloadaggressively(boolean overloadAggressively)
+ {
+ configuration.overloadAggressively = overloadAggressively;
+ }
+
+
+ public void setUseuniqueclassmembernames(boolean useUniqueClassMemberNames)
+ {
+ configuration.useUniqueClassMemberNames = useUniqueClassMemberNames;
+ }
+
+
+ public void setUsemixedcaseclassnames(boolean useMixedCaseClassNames)
+ {
+ configuration.useMixedCaseClassNames = useMixedCaseClassNames;
+ }
+
+
+ public void setFlattenpackagehierarchy(String flattenPackageHierarchy)
+ {
+ configuration.flattenPackageHierarchy = ClassUtil.internalClassName(flattenPackageHierarchy);
+ }
+
+
+ public void setRepackageclasses(String repackageClasses)
+ {
+ configuration.repackageClasses = ClassUtil.internalClassName(repackageClasses);
+ }
+
+ /**
+ * @deprecated Use the repackageclasses attribute instead.
+ */
+ public void setDefaultpackage(String defaultPackage)
+ {
+ configuration.repackageClasses = ClassUtil.internalClassName(defaultPackage);
+ }
+
+
+ public void setKeepparameternames(boolean keepParameterNames)
+ {
+ configuration.keepParameterNames = keepParameterNames;
+ }
+
+
+ public void setRenamesourcefileattribute(String newSourceFileAttribute)
+ {
+ configuration.newSourceFileAttribute = newSourceFileAttribute;
+ }
+
+
+ public void setPreverify(boolean preverify)
+ {
+ configuration.preverify = preverify;
+ }
+
+
+ public void setMicroedition(boolean microEdition)
+ {
+ configuration.microEdition = microEdition;
+ }
+
+
+ public void setVerbose(boolean verbose)
+ {
+ configuration.verbose = verbose;
+ }
+
+
+ public void setNote(boolean note)
+ {
+ if (note)
+ {
+ // Switch on notes if they were completely disabled.
+ if (configuration.note != null &&
+ configuration.note.isEmpty())
+ {
+ configuration.note = null;
+ }
+ }
+ else
+ {
+ // Switch off notes.
+ configuration.note = new ArrayList();
+ }
+ }
+
+
+ public void setWarn(boolean warn)
+ {
+ if (warn)
+ {
+ // Switch on warnings if they were completely disabled.
+ if (configuration.warn != null &&
+ configuration.warn.isEmpty())
+ {
+ configuration.warn = null;
+ }
+ }
+ else
+ {
+ // Switch off warnings.
+ configuration.warn = new ArrayList();
+ }
+ }
+
+
+ public void setIgnorewarnings(boolean ignoreWarnings)
+ {
+ configuration.ignoreWarnings = ignoreWarnings;
+ }
+
+
+ public void setPrintconfiguration(File printConfiguration)
+ {
+ configuration.printConfiguration = optionalFile(printConfiguration);
+ }
+
+
+ public void setDump(File dump)
+ {
+ configuration.dump = optionalFile(dump);
+ }
+
+
+ // Implementations for Task.
+
+ public void execute() throws BuildException
+ {
+ try
+ {
+ ProGuard proGuard = new ProGuard(configuration);
+ proGuard.execute();
+ }
+ catch (IOException e)
+ {
+ throw new BuildException(e.getMessage(), e);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns a file that is properly resolved with respect to the project
+ * directory, or <code>null</code> or empty if its name is actually a
+ * boolean flag.
+ */
+ private File optionalFile(File file)
+ {
+ String fileName = file.getName();
+
+ return
+ fileName.equalsIgnoreCase("false") ||
+ fileName.equalsIgnoreCase("no") ||
+ fileName.equalsIgnoreCase("off") ? null :
+ fileName.equalsIgnoreCase("true") ||
+ fileName.equalsIgnoreCase("yes") ||
+ fileName.equalsIgnoreCase("on") ? Configuration.STD_OUT :
+ resolvedFile(file);
+ }
+
+
+ /**
+ * Returns a file that is properly resolved with respect to the project
+ * directory.
+ */
+ private File resolvedFile(File file)
+ {
+ return file.isAbsolute() ? file :
+ new File(getProject().getBaseDir(),
+ file.getName());
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ant/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/package.html
new file mode 100644
index 0000000000..75e0466df7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains the Ant task for ProGuard.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ant/task.properties b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/task.properties
new file mode 100644
index 0000000000..82d0f3f419
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ant/task.properties
@@ -0,0 +1,2 @@
+proguard = proguard.ant.ProGuardTask
+proguardconfiguration = proguard.ant.ConfigurationTask
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ClassConstants.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ClassConstants.java
new file mode 100644
index 0000000000..a5057ad665
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ClassConstants.java
@@ -0,0 +1,345 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+/**
+ * Constants used in representing a Java class file (*.class).
+ *
+ * @author Eric Lafortune
+ */
+public class ClassConstants
+{
+ public static final String CLASS_FILE_EXTENSION = ".class";
+
+ public static final int MAGIC = 0xCAFEBABE;
+
+ public static final int CLASS_VERSION_1_0_MAJOR = 45;
+ public static final int CLASS_VERSION_1_0_MINOR = 3;
+ public static final int CLASS_VERSION_1_2_MAJOR = 46;
+ public static final int CLASS_VERSION_1_2_MINOR = 0;
+ public static final int CLASS_VERSION_1_3_MAJOR = 47;
+ public static final int CLASS_VERSION_1_3_MINOR = 0;
+ public static final int CLASS_VERSION_1_4_MAJOR = 48;
+ public static final int CLASS_VERSION_1_4_MINOR = 0;
+ public static final int CLASS_VERSION_1_5_MAJOR = 49;
+ public static final int CLASS_VERSION_1_5_MINOR = 0;
+ public static final int CLASS_VERSION_1_6_MAJOR = 50;
+ public static final int CLASS_VERSION_1_6_MINOR = 0;
+ public static final int CLASS_VERSION_1_7_MAJOR = 51;
+ public static final int CLASS_VERSION_1_7_MINOR = 0;
+ public static final int CLASS_VERSION_1_8_MAJOR = 52;
+ public static final int CLASS_VERSION_1_8_MINOR = 0;
+
+ public static final int CLASS_VERSION_1_0 = (CLASS_VERSION_1_0_MAJOR << 16) | CLASS_VERSION_1_0_MINOR;
+ public static final int CLASS_VERSION_1_2 = (CLASS_VERSION_1_2_MAJOR << 16) | CLASS_VERSION_1_2_MINOR;
+ public static final int CLASS_VERSION_1_3 = (CLASS_VERSION_1_3_MAJOR << 16) | CLASS_VERSION_1_3_MINOR;
+ public static final int CLASS_VERSION_1_4 = (CLASS_VERSION_1_4_MAJOR << 16) | CLASS_VERSION_1_4_MINOR;
+ public static final int CLASS_VERSION_1_5 = (CLASS_VERSION_1_5_MAJOR << 16) | CLASS_VERSION_1_5_MINOR;
+ public static final int CLASS_VERSION_1_6 = (CLASS_VERSION_1_6_MAJOR << 16) | CLASS_VERSION_1_6_MINOR;
+ public static final int CLASS_VERSION_1_7 = (CLASS_VERSION_1_7_MAJOR << 16) | CLASS_VERSION_1_7_MINOR;
+ public static final int CLASS_VERSION_1_8 = (CLASS_VERSION_1_8_MAJOR << 16) | CLASS_VERSION_1_8_MINOR;
+
+ public static final int ACC_PUBLIC = 0x0001;
+ public static final int ACC_PRIVATE = 0x0002;
+ public static final int ACC_PROTECTED = 0x0004;
+ public static final int ACC_STATIC = 0x0008;
+ public static final int ACC_FINAL = 0x0010;
+ public static final int ACC_SUPER = 0x0020;
+ public static final int ACC_SYNCHRONIZED = 0x0020;
+ public static final int ACC_VOLATILE = 0x0040;
+ public static final int ACC_TRANSIENT = 0x0080;
+ public static final int ACC_BRIDGE = 0x0040;
+ public static final int ACC_VARARGS = 0x0080;
+ public static final int ACC_NATIVE = 0x0100;
+ public static final int ACC_INTERFACE = 0x0200;
+ public static final int ACC_ABSTRACT = 0x0400;
+ public static final int ACC_STRICT = 0x0800;
+ public static final int ACC_SYNTHETIC = 0x1000;
+ public static final int ACC_ANNOTATTION = 0x2000;
+ public static final int ACC_ENUM = 0x4000;
+ public static final int ACC_MANDATED = 0x8000;
+
+ public static final int VALID_ACC_CLASS = ACC_PUBLIC |
+ ACC_FINAL |
+ ACC_SUPER |
+ ACC_INTERFACE |
+ ACC_ABSTRACT |
+ ACC_SYNTHETIC |
+ ACC_ANNOTATTION |
+ ACC_ENUM;
+ public static final int VALID_ACC_FIELD = ACC_PUBLIC |
+ ACC_PRIVATE |
+ ACC_PROTECTED |
+ ACC_STATIC |
+ ACC_FINAL |
+ ACC_VOLATILE |
+ ACC_TRANSIENT |
+ ACC_SYNTHETIC |
+ ACC_ENUM;
+ public static final int VALID_ACC_METHOD = ACC_PUBLIC |
+ ACC_PRIVATE |
+ ACC_PROTECTED |
+ ACC_STATIC |
+ ACC_FINAL |
+ ACC_SYNCHRONIZED |
+ ACC_BRIDGE |
+ ACC_VARARGS |
+ ACC_NATIVE |
+ ACC_ABSTRACT |
+ ACC_STRICT |
+ ACC_SYNTHETIC;
+ public static final int VALID_ACC_PARAMETER = ACC_FINAL |
+ ACC_SYNTHETIC |
+ ACC_MANDATED;
+
+ public static final int CONSTANT_Utf8 = 1;
+ public static final int CONSTANT_Integer = 3;
+ public static final int CONSTANT_Float = 4;
+ public static final int CONSTANT_Long = 5;
+ public static final int CONSTANT_Double = 6;
+ public static final int CONSTANT_Class = 7;
+ public static final int CONSTANT_String = 8;
+ public static final int CONSTANT_Fieldref = 9;
+ public static final int CONSTANT_Methodref = 10;
+ public static final int CONSTANT_InterfaceMethodref = 11;
+ public static final int CONSTANT_NameAndType = 12;
+ public static final int CONSTANT_MethodHandle = 15;
+ public static final int CONSTANT_MethodType = 16;
+ public static final int CONSTANT_InvokeDynamic = 18;
+
+ public static final int REF_getField = 1;
+ public static final int REF_getStatic = 2;
+ public static final int REF_putField = 3;
+ public static final int REF_putStatic = 4;
+ public static final int REF_invokeVirtual = 5;
+ public static final int REF_invokeStatic = 6;
+ public static final int REF_invokeSpecial = 7;
+ public static final int REF_newInvokeSpecial = 8;
+ public static final int REF_invokeInterface = 9;
+
+ public static final String ATTR_BootstrapMethods = "BootstrapMethods";
+ public static final String ATTR_SourceFile = "SourceFile";
+ public static final String ATTR_SourceDir = "SourceDir";
+ public static final String ATTR_InnerClasses = "InnerClasses";
+ public static final String ATTR_EnclosingMethod = "EnclosingMethod";
+ public static final String ATTR_Deprecated = "Deprecated";
+ public static final String ATTR_Synthetic = "Synthetic";
+ public static final String ATTR_Signature = "Signature";
+ public static final String ATTR_ConstantValue = "ConstantValue";
+ public static final String ATTR_MethodParameters = "MethodParameters";
+ public static final String ATTR_Exceptions = "Exceptions";
+ public static final String ATTR_Code = "Code";
+ public static final String ATTR_StackMap = "StackMap";
+ public static final String ATTR_StackMapTable = "StackMapTable";
+ public static final String ATTR_LineNumberTable = "LineNumberTable";
+ public static final String ATTR_LocalVariableTable = "LocalVariableTable";
+ public static final String ATTR_LocalVariableTypeTable = "LocalVariableTypeTable";
+ public static final String ATTR_RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations";
+ public static final String ATTR_RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
+ public static final String ATTR_RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
+ public static final String ATTR_RuntimeInvisibleParameterAnnotations = "RuntimeInvisibleParameterAnnotations";
+ public static final String ATTR_RuntimeVisibleTypeAnnotations = "RuntimeVisibleTypeAnnotations";
+ public static final String ATTR_RuntimeInvisibleTypeAnnotations = "RuntimeInvisibleTypeAnnotations";
+ public static final String ATTR_AnnotationDefault = "AnnotationDefault";
+
+ public static final int ANNOTATION_TARGET_ParameterGenericClass = 0x00;
+ public static final int ANNOTATION_TARGET_ParameterGenericMethod = 0x01;
+ public static final int ANNOTATION_TARGET_Extends = 0x10;
+ public static final int ANNOTATION_TARGET_BoundGenericClass = 0x11;
+ public static final int ANNOTATION_TARGET_BoundGenericMethod = 0x12;
+ public static final int ANNOTATION_TARGET_Field = 0x13;
+ public static final int ANNOTATION_TARGET_Return = 0x14;
+ public static final int ANNOTATION_TARGET_Receiver = 0x15;
+ public static final int ANNOTATION_TARGET_Parameter = 0x16;
+ public static final int ANNOTATION_TARGET_Throws = 0x17;
+ public static final int ANNOTATION_TARGET_LocalVariable = 0x40;
+ public static final int ANNOTATION_TARGET_ResourceVariable = 0x41;
+ public static final int ANNOTATION_TARGET_Catch = 0x42;
+ public static final int ANNOTATION_TARGET_InstanceOf = 0x43;
+ public static final int ANNOTATION_TARGET_New = 0x44;
+ public static final int ANNOTATION_TARGET_MethodReferenceNew = 0x45;
+ public static final int ANNOTATION_TARGET_MethodReference = 0x46;
+ public static final int ANNOTATION_TARGET_Cast = 0x47;
+ public static final int ANNOTATION_TARGET_ArgumentGenericMethodNew = 0x48;
+ public static final int ANNOTATION_TARGET_ArgumentGenericMethod = 0x49;
+ public static final int ANNOTATION_TARGET_ArgumentGenericMethodReferenceNew = 0x4a;
+ public static final int ANNOTATION_TARGET_ArgumentGenericMethodReference = 0x4b;
+
+ public static final char ELEMENT_VALUE_STRING_CONSTANT = 's';
+ public static final char ELEMENT_VALUE_ENUM_CONSTANT = 'e';
+ public static final char ELEMENT_VALUE_CLASS = 'c';
+ public static final char ELEMENT_VALUE_ANNOTATION = '@';
+ public static final char ELEMENT_VALUE_ARRAY = '[';
+
+ public static final char PACKAGE_SEPARATOR = '/';
+ public static final char INNER_CLASS_SEPARATOR = '$';
+ public static final char SPECIAL_CLASS_CHARACTER = '-';
+ public static final char SPECIAL_MEMBER_SEPARATOR = '$';
+
+ public static final char METHOD_ARGUMENTS_OPEN = '(';
+ public static final char METHOD_ARGUMENTS_CLOSE = ')';
+
+ public static final String PACKAGE_JAVA_LANG = "java/lang/";
+ public static final String NAME_JAVA_LANG_OBJECT = "java/lang/Object";
+ public static final String TYPE_JAVA_LANG_OBJECT = "Ljava/lang/Object;";
+ public static final String NAME_JAVA_LANG_CLONEABLE = "java/lang/Cloneable";
+ public static final String NAME_JAVA_LANG_THROWABLE = "java/lang/Throwable";
+ public static final String NAME_JAVA_LANG_CLASS = "java/lang/Class";
+ public static final String NAME_JAVA_LANG_STRING = "java/lang/String";
+ public static final String NAME_JAVA_LANG_STRING_BUFFER = "java/lang/StringBuffer";
+ public static final String NAME_JAVA_LANG_STRING_BUILDER = "java/lang/StringBuilder";
+ public static final String NAME_JAVA_LANG_INVOKE_METHOD_HANDLE = "java/lang/invoke/MethodHandle";
+ public static final String NAME_JAVA_LANG_INVOKE_METHOD_TYPE = "java/lang/invoke/MethodType";
+ public static final String NAME_JAVA_LANG_VOID = "java/lang/Void";
+ public static final String NAME_JAVA_LANG_BOOLEAN = "java/lang/Boolean";
+ public static final String NAME_JAVA_LANG_BYTE = "java/lang/Byte";
+ public static final String NAME_JAVA_LANG_SHORT = "java/lang/Short";
+ public static final String NAME_JAVA_LANG_CHARACTER = "java/lang/Character";
+ public static final String NAME_JAVA_LANG_INTEGER = "java/lang/Integer";
+ public static final String NAME_JAVA_LANG_LONG = "java/lang/Long";
+ public static final String NAME_JAVA_LANG_FLOAT = "java/lang/Float";
+ public static final String NAME_JAVA_LANG_DOUBLE = "java/lang/Double";
+ public static final String NAME_JAVA_LANG_MATH = "java/lang/Math";
+ public static final String NAME_JAVA_LANG_SYSTEM = "java/lang/System";
+ public static final String NAME_JAVA_LANG_RUNTIME = "java/lang/Runtime";
+ public static final String NAME_JAVA_LANG_REFLECT_ARRAY = "java/lang/reflect/Array";
+ public static final String NAME_JAVA_LANG_REFLECT_FIELD = "java/lang/reflect/Field";
+ public static final String NAME_JAVA_LANG_REFLECT_METHOD = "java/lang/reflect/Method";
+ public static final String NAME_JAVA_LANG_REFLECT_CONSTRUCTOR = "java/lang/reflect/Constructor";
+ public static final String NAME_JAVA_LANG_REFLECT_ACCESSIBLE_OBJECT = "java/lang/reflect/AccessibleObject";
+ public static final String NAME_JAVA_IO_SERIALIZABLE = "java/io/Serializable";
+
+ public static final String NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicIntegerFieldUpdater";
+ public static final String NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_LONG_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicLongFieldUpdater";
+ public static final String NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_REFERENCE_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicReferenceFieldUpdater";
+
+ public static final String METHOD_NAME_INIT = "<init>";
+ public static final String METHOD_TYPE_INIT = "()V";
+ public static final String METHOD_NAME_CLINIT = "<clinit>";
+ public static final String METHOD_TYPE_CLINIT = "()V";
+
+ public static final String METHOD_NAME_CLASS_FOR_NAME = "forName";
+ public static final String METHOD_TYPE_CLASS_FOR_NAME = "(Ljava/lang/String;)Ljava/lang/Class;";
+ public static final String METHOD_NAME_CLASS_GET_COMPONENT_TYPE = "getComponentType";
+ public static final String METHOD_TYPE_CLASS_GET_COMPONENT_TYPE = "()Ljava/lang/Class;";
+ public static final String METHOD_NAME_CLASS_GET_FIELD = "getField";
+ public static final String METHOD_TYPE_CLASS_GET_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;";
+ public static final String METHOD_NAME_CLASS_GET_DECLARED_FIELD = "getDeclaredField";
+ public static final String METHOD_TYPE_CLASS_GET_DECLARED_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;";
+ public static final String CONSTRUCTOR_NAME_CLASS_GET_CONSTRUCTOR = "getConstructor";
+ public static final String CONSTRUCTOR_TYPE_CLASS_GET_CONSTRUCTOR = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;";
+ public static final String CONSTRUCTOR_NAME_CLASS_GET_DECLARED_CONSTRUCTOR = "getDeclaredConstructor";
+ public static final String CONSTRUCTOR_TYPE_CLASS_GET_DECLARED_CONSTRUCTOR = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;";
+ public static final String METHOD_NAME_CLASS_GET_METHOD = "getMethod";
+ public static final String METHOD_TYPE_CLASS_GET_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;";
+ public static final String METHOD_NAME_CLASS_GET_DECLARED_METHOD = "getDeclaredMethod";
+ public static final String METHOD_TYPE_CLASS_GET_DECLARED_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;";
+ public static final String METHOD_NAME_CLASS_GET_DECLARING_CLASS = "getDeclaringClass";
+ public static final String METHOD_NAME_CLASS_GET_ENCLOSING_CLASS = "getEnclosingClass";
+ public static final String METHOD_NAME_CLASS_GET_ENCLOSING_CONSTRUCTOR = "getEnclosingConstructor";
+ public static final String METHOD_NAME_CLASS_GET_ENCLOSING_METHOD = "getEnclosingMethod";
+ public static final String METHOD_NAME_GET_ANNOTATION = "getAnnotation";
+ public static final String METHOD_NAME_GET_ANNOTATIONS = "getAnnotations";
+ public static final String METHOD_NAME_GET_DECLARED_ANNOTATIONS = "getDeclaredAnnotations";
+ public static final String METHOD_NAME_GET_PARAMETER_ANNOTATIONS = "getParameterAnnotations";
+ public static final String METHOD_NAME_GET_TYPE_PREFIX = "getType";
+ public static final String METHOD_NAME_GET_GENERIC_PREFIX = "getGeneric";
+ public static final String METHOD_NAME_NEW_UPDATER = "newUpdater";
+ public static final String METHOD_TYPE_NEW_INTEGER_UPDATER = "(Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater;";
+ public static final String METHOD_TYPE_NEW_LONG_UPDATER = "(Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicLongFieldUpdater;";
+ public static final String METHOD_TYPE_NEW_REFERENCE_UPDATER = "(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;";
+
+ public static final String METHOD_NAME_DOT_CLASS_JAVAC = "class$";
+ public static final String METHOD_TYPE_DOT_CLASS_JAVAC = "(Ljava/lang/String;)Ljava/lang/Class;";
+ public static final String METHOD_NAME_DOT_CLASS_JIKES = "class";
+ public static final String METHOD_TYPE_DOT_CLASS_JIKES = "(Ljava/lang/String;Z)Ljava/lang/Class;";
+
+ public static final String METHOD_TYPE_INIT_ENUM = "(Ljava/lang/String;I)V";
+
+ public static final String METHOD_NAME_NEW_INSTANCE = "newInstance";
+ public static final String METHOD_TYPE_NEW_INSTANCE = "()Ljava/lang/Object;";
+
+ public static final String METHOD_NAME_EQUALS = "equals";
+ public static final String METHOD_TYPE_EQUALS = "(Ljava/lang/Object;)Z";
+ public static final String METHOD_NAME_LENGTH = "length";
+ public static final String METHOD_NAME_VALUEOF = "valueOf";
+ public static final String METHOD_TYPE_VALUEOF_BOOLEAN = "(Z)Ljava/lang/String;";
+ public static final String METHOD_TYPE_VALUEOF_CHAR = "(C)Ljava/lang/String;";
+ public static final String METHOD_TYPE_VALUEOF_INT = "(I)Ljava/lang/String;";
+ public static final String METHOD_TYPE_VALUEOF_LONG = "(J)Ljava/lang/String;";
+ public static final String METHOD_TYPE_VALUEOF_FLOAT = "(F)Ljava/lang/String;";
+ public static final String METHOD_TYPE_VALUEOF_DOUBLE = "(D)Ljava/lang/String;";
+ public static final String METHOD_TYPE_VALUEOF_OBJECT = "(Ljava/lang/Object;)Ljava/lang/String;";
+
+ public static final String METHOD_TYPE_LENGTH = "()I";
+ public static final String METHOD_NAME_APPEND = "append";
+ public static final String METHOD_TYPE_STRING_VOID = "(Ljava/lang/String;)V";
+ public static final String METHOD_TYPE_BOOLEAN_STRING_BUFFER = "(Z)Ljava/lang/StringBuffer;";
+ public static final String METHOD_TYPE_CHAR_STRING_BUFFER = "(C)Ljava/lang/StringBuffer;";
+ public static final String METHOD_TYPE_INT_STRING_BUFFER = "(I)Ljava/lang/StringBuffer;";
+ public static final String METHOD_TYPE_LONG_STRING_BUFFER = "(J)Ljava/lang/StringBuffer;";
+ public static final String METHOD_TYPE_FLOAT_STRING_BUFFER = "(F)Ljava/lang/StringBuffer;";
+ public static final String METHOD_TYPE_DOUBLE_STRING_BUFFER = "(D)Ljava/lang/StringBuffer;";
+ public static final String METHOD_TYPE_STRING_STRING_BUFFER = "(Ljava/lang/String;)Ljava/lang/StringBuffer;";
+ public static final String METHOD_TYPE_OBJECT_STRING_BUFFER = "(Ljava/lang/Object;)Ljava/lang/StringBuffer;";
+ public static final String METHOD_TYPE_BOOLEAN_STRING_BUILDER = "(Z)Ljava/lang/StringBuilder;";
+ public static final String METHOD_TYPE_CHAR_STRING_BUILDER = "(C)Ljava/lang/StringBuilder;";
+ public static final String METHOD_TYPE_INT_STRING_BUILDER = "(I)Ljava/lang/StringBuilder;";
+ public static final String METHOD_TYPE_LONG_STRING_BUILDER = "(J)Ljava/lang/StringBuilder;";
+ public static final String METHOD_TYPE_FLOAT_STRING_BUILDER = "(F)Ljava/lang/StringBuilder;";
+ public static final String METHOD_TYPE_DOUBLE_STRING_BUILDER = "(D)Ljava/lang/StringBuilder;";
+ public static final String METHOD_TYPE_STRING_STRING_BUILDER = "(Ljava/lang/String;)Ljava/lang/StringBuilder;";
+ public static final String METHOD_TYPE_OBJECT_STRING_BUILDER = "(Ljava/lang/Object;)Ljava/lang/StringBuilder;";
+ public static final String METHOD_NAME_TOSTRING = "toString";
+ public static final String METHOD_TYPE_TOSTRING = "()Ljava/lang/String;";
+ public static final String METHOD_NAME_CLONE = "clone";
+ public static final String METHOD_TYPE_CLONE = "()Ljava/lang/Object;";
+
+ public static final String METHOD_NAME_VALUES = "values";
+ public static final String METHOD_NAME_ORDINAL = "ordinal";
+ public static final String METHOD_TYPE_ORDINAL = "()I";
+
+ public static final char TYPE_VOID = 'V';
+ public static final char TYPE_BOOLEAN = 'Z';
+ public static final char TYPE_BYTE = 'B';
+ public static final char TYPE_CHAR = 'C';
+ public static final char TYPE_SHORT = 'S';
+ public static final char TYPE_INT = 'I';
+ public static final char TYPE_LONG = 'J';
+ public static final char TYPE_FLOAT = 'F';
+ public static final char TYPE_DOUBLE = 'D';
+ public static final char TYPE_CLASS_START = 'L';
+ public static final char TYPE_CLASS_END = ';';
+ public static final char TYPE_ARRAY = '[';
+ public static final char TYPE_GENERIC_VARIABLE_START = 'T';
+ public static final char TYPE_GENERIC_START = '<';
+ public static final char TYPE_GENERIC_BOUND = ':';
+ public static final char TYPE_GENERIC_END = '>';
+
+ public static final int TYPICAL_CONSTANT_POOL_SIZE = 256;
+ public static final int TYPICAL_FIELD_COUNT = 64;
+ public static final int TYPICAL_METHOD_COUNT = 64;
+ public static final int TYPICAL_CODE_LENGTH = 1024;
+ public static final int TYPICAL_LINE_NUMBER_TABLE_LENGTH = 1024;
+ public static final int TYPICAL_EXCEPTION_TABLE_LENGTH = 16;
+ public static final int TYPICAL_VARIABLES_SIZE = 64;
+ public static final int TYPICAL_STACK_SIZE = 16;
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ClassPool.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ClassPool.java
new file mode 100644
index 0000000000..0904d11541
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ClassPool.java
@@ -0,0 +1,160 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+import proguard.classfile.visitor.*;
+
+import java.util.*;
+
+/**
+ * This is a set of representations of classes. They can be enumerated or
+ * retrieved by name. They can also be accessed by means of class visitors.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassPool
+{
+ // We're using a sorted tree map instead of a hash map to store the classes,
+ // in order to make the processing more deterministic.
+ private final Map classes = new TreeMap();
+
+
+ /**
+ * Clears the class pool.
+ */
+ public void clear()
+ {
+ classes.clear();
+ }
+
+
+ /**
+ * Adds the given Clazz to the class pool.
+ */
+ public void addClass(Clazz clazz)
+ {
+ classes.put(clazz.getName(), clazz);
+ }
+
+
+ /**
+ * Removes the given Clazz from the class pool.
+ */
+ public void removeClass(Clazz clazz)
+ {
+ removeClass(clazz.getName());
+ }
+
+
+ /**
+ * Removes the specified Clazz from the class pool.
+ */
+ public void removeClass(String className)
+ {
+ classes.remove(className);
+ }
+
+
+ /**
+ * Returns a Clazz from the class pool based on its name. Returns
+ * <code>null</code> if the class with the given name is not in the class
+ * pool.
+ */
+ public Clazz getClass(String className)
+ {
+ return (Clazz)classes.get(className);
+ }
+
+
+ /**
+ * Returns an Iterator of all class names in the class pool.
+ */
+ public Iterator classNames()
+ {
+ return classes.keySet().iterator();
+ }
+
+
+ /**
+ * Returns the number of classes in the class pool.
+ */
+ public int size()
+ {
+ return classes.size();
+ }
+
+
+ /**
+ * Applies the given ClassPoolVisitor to the class pool.
+ */
+ public void accept(ClassPoolVisitor classPoolVisitor)
+ {
+ classPoolVisitor.visitClassPool(this);
+ }
+
+
+ /**
+ * Applies the given ClassVisitor to all classes in the class pool,
+ * in random order.
+ */
+ public void classesAccept(ClassVisitor classVisitor)
+ {
+ Iterator iterator = classes.values().iterator();
+ while (iterator.hasNext())
+ {
+ Clazz clazz = (Clazz)iterator.next();
+ clazz.accept(classVisitor);
+ }
+ }
+
+
+ /**
+ * Applies the given ClassVisitor to all classes in the class pool,
+ * in sorted order.
+ */
+ public void classesAcceptAlphabetically(ClassVisitor classVisitor)
+ {
+ // We're already using a tree map.
+ //TreeMap sortedClasses = new TreeMap(classes);
+ //Iterator iterator = sortedClasses.values().iterator();
+
+ Iterator iterator = classes.values().iterator();
+ while (iterator.hasNext())
+ {
+ Clazz clazz = (Clazz)iterator.next();
+ clazz.accept(classVisitor);
+ }
+ }
+
+
+ /**
+ * Applies the given ClassVisitor to the class with the given name,
+ * if it is present in the class pool.
+ */
+ public void classAccept(String className, ClassVisitor classVisitor)
+ {
+ Clazz clazz = getClass(className);
+ if (clazz != null)
+ {
+ clazz.accept(classVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Clazz.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Clazz.java
new file mode 100644
index 0000000000..dca81c4e6c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Clazz.java
@@ -0,0 +1,266 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.visitor.*;
+
+
+/**
+ * This interface provides access to the representation of a Java class.
+ *
+ * @author Eric Lafortune
+ */
+public interface Clazz extends VisitorAccepter
+{
+ /**
+ * Returns the access flags of this class.
+ * @see ClassConstants
+ */
+ public int getAccessFlags();
+
+ /**
+ * Returns the full internal name of this class.
+ */
+ public String getName();
+
+ /**
+ * Returns the full internal name of the super class of this class, or
+ * null if this class represents java.lang.Object.
+ */
+ public String getSuperName();
+
+ /**
+ * Returns the number of interfaces that this class implements.
+ */
+ public int getInterfaceCount();
+
+ /**
+ * Returns the full internal name of the interface at the given index of
+ * this class.
+ */
+ public String getInterfaceName(int index);
+
+ /**
+ * Returns the tag value of the Constant at the specified index.
+ */
+ public int getTag(int constantIndex);
+
+ /**
+ * Returns the String value of the Utf8Constant at the specified index.
+ */
+ public String getString(int constantIndex);
+
+ /**
+ * Returns the String value of the StringConstant at the specified index.
+ */
+ public String getStringString(int constantIndex);
+
+ /**
+ * Returns the class name of ClassConstant at the specified index.
+ */
+ public String getClassName(int constantIndex);
+
+ /**
+ * Returns the name of the NameAndTypeConstant at the specified index.
+ */
+ public String getName(int constantIndex);
+
+ /**
+ * Returns the type of the NameAndTypeConstant at the specified index.
+ */
+ public String getType(int constantIndex);
+
+ /**
+ * Returns the class name of the RefConstant at the specified index.
+ */
+ public String getRefClassName(int constantIndex);
+
+ /**
+ * Returns the name of the RefConstant at the specified index.
+ */
+ public String getRefName(int constantIndex);
+
+ /**
+ * Returns the type of the RefConstant at the specified index.
+ */
+ public String getRefType(int constantIndex);
+
+
+ // Methods pertaining to related classes.
+
+ /**
+ * Notifies this Clazz that it is being subclassed by another class.
+ */
+ public void addSubClass(Clazz clazz);
+
+ /**
+ * Returns the super class of this class.
+ */
+ public Clazz getSuperClass();
+
+ /**
+ * Returns the interface at the given index.
+ */
+ public Clazz getInterface(int index);
+
+ /**
+ * Returns whether this class extends the given class.
+ * A class is always considered to extend itself.
+ * Interfaces are considered to only extend the root Object class.
+ */
+ public boolean extends_(Clazz clazz);
+
+ /**
+ * Returns whether this class extends the specified class.
+ * A class is always considered to extend itself.
+ * Interfaces are considered to only extend the root Object class.
+ */
+ public boolean extends_(String className);
+
+ /**
+ * Returns whether this class implements the given class.
+ * A class is always considered to implement itself.
+ * Interfaces are considered to implement all their superinterfaces.
+ */
+ public boolean extendsOrImplements(Clazz clazz);
+
+ /**
+ * Returns whether this class implements the specified class.
+ * A class is always considered to implement itself.
+ * Interfaces are considered to implement all their superinterfaces.
+ */
+ public boolean extendsOrImplements(String className);
+
+
+ // Methods for getting specific class members.
+
+ /**
+ * Returns the field with the given name and descriptor.
+ */
+ Field findField(String name, String descriptor);
+
+ /**
+ * Returns the method with the given name and descriptor.
+ */
+ Method findMethod(String name, String descriptor);
+
+
+ // Methods for accepting various types of visitors.
+
+ /**
+ * Accepts the given class visitor.
+ */
+ public void accept(ClassVisitor classVisitor);
+
+ /**
+ * Accepts the given class visitor in the class hierarchy.
+ * @param visitThisClass specifies whether to visit this class.
+ * @param visitSuperClass specifies whether to visit the super classes.
+ * @param visitInterfaces specifies whether to visit the interfaces.
+ * @param visitSubclasses specifies whether to visit the subclasses.
+ * @param classVisitor the <code>ClassVisitor</code> that will
+ * visit the class hierarchy.
+ */
+ public void hierarchyAccept(boolean visitThisClass,
+ boolean visitSuperClass,
+ boolean visitInterfaces,
+ boolean visitSubclasses,
+ ClassVisitor classVisitor);
+
+ /**
+ * Lets the given class visitor visit all known subclasses.
+ * @param classVisitor the <code>ClassVisitor</code> that will visit the
+ * subclasses.
+ */
+ public void subclassesAccept(ClassVisitor classVisitor);
+
+ /**
+ * Lets the given constant pool entry visitor visit all constant pool entries
+ * of this class.
+ */
+ public void constantPoolEntriesAccept(ConstantVisitor constantVisitor);
+
+ /**
+ * Lets the given constant pool entry visitor visit the constant pool entry
+ * at the specified index.
+ */
+ public void constantPoolEntryAccept(int index, ConstantVisitor constantVisitor);
+
+ /**
+ * Lets the given constant pool entry visitor visit the class constant pool
+ * entry of this class.
+ */
+ public void thisClassConstantAccept(ConstantVisitor constantVisitor);
+
+ /**
+ * Lets the given constant pool entry visitor visit the class constant pool
+ * entry of the super class of this class, if there is one.
+ */
+ public void superClassConstantAccept(ConstantVisitor constantVisitor);
+
+ /**
+ * Lets the given constant pool entry visitor visit the class constant pool
+ * entries for all interfaces of this class.
+ */
+ public void interfaceConstantsAccept(ConstantVisitor constantVisitor);
+
+ /**
+ * Lets the given member info visitor visit all fields of this class.
+ */
+ public void fieldsAccept(MemberVisitor memberVisitor);
+
+ /**
+ * Lets the given member info visitor visit the specified field.
+ */
+ public void fieldAccept(String name, String descriptor, MemberVisitor memberVisitor);
+
+ /**
+ * Lets the given member info visitor visit all methods of this class.
+ */
+ public void methodsAccept(MemberVisitor memberVisitor);
+
+ /**
+ * Lets the given member info visitor visit the specified method.
+ */
+ public void methodAccept(String name, String descriptor, MemberVisitor memberVisitor);
+
+ /**
+ * Returns whether the given method may possibly have implementing or
+ * overriding methods down the class hierarchy. This can only be true
+ * if the class is not final, and the method is not private, static, or
+ * final, or a constructor.
+ * @param method the method that may have implementations.
+ * @return whether it may have implementations.
+ */
+ public boolean mayHaveImplementations(Method method);
+
+ /**
+ * Lets the given attribute info visitor visit all attributes of this class.
+ */
+ public void attributesAccept(AttributeVisitor attributeVisitor);
+
+ /**
+ * Lets the given attribute info visitor visit the specified attribute.
+ */
+ public void attributeAccept(String name, AttributeVisitor attributeVisitor);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Field.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Field.java
new file mode 100644
index 0000000000..15f82dc552
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Field.java
@@ -0,0 +1,32 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+
+
+/**
+ * Representation of a field from a class.
+ *
+ * @author Eric Lafortune
+ */
+public interface Field extends Member
+{
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/JavaConstants.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/JavaConstants.java
new file mode 100644
index 0000000000..9512b25b4c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/JavaConstants.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+/**
+ * Constants used in representing a Java source file (*.java).
+ *
+ * @author Eric Lafortune
+ */
+public interface JavaConstants
+{
+ public static final String JAVA_FILE_EXTENSION = ".java";
+
+ public static final String CLASS_VERSION_1_0 = "1.0";
+ public static final String CLASS_VERSION_1_1 = "1.1";
+ public static final String CLASS_VERSION_1_2 = "1.2";
+ public static final String CLASS_VERSION_1_3 = "1.3";
+ public static final String CLASS_VERSION_1_4 = "1.4";
+ public static final String CLASS_VERSION_1_5 = "1.5";
+ public static final String CLASS_VERSION_1_6 = "1.6";
+ public static final String CLASS_VERSION_1_7 = "1.7";
+ public static final String CLASS_VERSION_1_8 = "1.8";
+ public static final String CLASS_VERSION_1_5_ALIAS = "5";
+ public static final String CLASS_VERSION_1_6_ALIAS = "6";
+ public static final String CLASS_VERSION_1_7_ALIAS = "7";
+ public static final String CLASS_VERSION_1_8_ALIAS = "8";
+
+ public static final String ACC_PUBLIC = "public";
+ public static final String ACC_PRIVATE = "private";
+ public static final String ACC_PROTECTED = "protected";
+ public static final String ACC_STATIC = "static";
+ public static final String ACC_FINAL = "final";
+// public static final String ACC_SUPER = "super";
+ public static final String ACC_SYNCHRONIZED = "synchronized";
+ public static final String ACC_VOLATILE = "volatile";
+ public static final String ACC_TRANSIENT = "transient";
+ public static final String ACC_BRIDGE = "bridge";
+ public static final String ACC_VARARGS = "varargs";
+ public static final String ACC_NATIVE = "native";
+ public static final String ACC_INTERFACE = "interface";
+ public static final String ACC_ABSTRACT = "abstract";
+ public static final String ACC_STRICT = "strictfp";
+ public static final String ACC_SYNTHETIC = "synthetic";
+ public static final String ACC_ANNOTATION = "@";
+ public static final String ACC_ENUM = "enum";
+ public static final String ACC_MANDATED = "mandated";
+// public static final String ACC_CONSTRUCTOR = "constructor";
+
+ public static final char PACKAGE_SEPARATOR = '.';
+ public static final char INNER_CLASS_SEPARATOR = '.';
+ public static final char SPECIAL_CLASS_CHARACTER = '-';
+ public static final char SPECIAL_MEMBER_SEPARATOR = '$';
+
+ public static final char METHOD_ARGUMENTS_OPEN = '(';
+ public static final char METHOD_ARGUMENTS_CLOSE = ')';
+ public static final char METHOD_ARGUMENTS_SEPARATOR = ',';
+
+ public static final String TYPE_JAVA_LANG_OBJECT = "java.lang.Object";
+ public static final String PACKAGE_JAVA_LANG = "java.lang.";
+
+ public static final String TYPE_VOID = "void";
+ public static final String TYPE_BOOLEAN = "boolean";
+ public static final String TYPE_BYTE = "byte";
+ public static final String TYPE_CHAR = "char";
+ public static final String TYPE_SHORT = "short";
+ public static final String TYPE_INT = "int";
+ public static final String TYPE_FLOAT = "float";
+ public static final String TYPE_LONG = "long";
+ public static final String TYPE_DOUBLE = "double";
+ public static final String TYPE_ARRAY = "[]";
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryClass.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryClass.java
new file mode 100644
index 0000000000..26ddff9f7e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryClass.java
@@ -0,0 +1,553 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This Clazz is a compact representation of the essential data in a Java class.
+ *
+ * @author Eric Lafortune
+ */
+public class LibraryClass implements Clazz
+{
+ public int u2accessFlags;
+ public String thisClassName;
+ public String superClassName;
+ public String[] interfaceNames;
+ public LibraryField[] fields;
+ public LibraryMethod[] methods;
+
+ /**
+ * An extra field pointing to the superclass of this class.
+ * This field is filled out by the {@link ClassSuperHierarchyInitializer}.
+ */
+ public Clazz superClass;
+
+ /**
+ * An extra field pointing to the interfaces of this class.
+ * This field is filled out by the {@link ClassSuperHierarchyInitializer}.
+ */
+ public Clazz[] interfaceClasses;
+
+ /**
+ * An extra field pointing to the subclasses of this class.
+ * This field is filled out by the {@link ClassSubHierarchyInitializer}.
+ */
+ public Clazz[] subClasses;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an empty LibraryClass.
+ */
+ public LibraryClass() {}
+
+
+ /**
+ * Returns whether this library class is visible to the outside world.
+ */
+ boolean isVisible()
+ {
+ return (u2accessFlags & ClassConstants.ACC_PUBLIC) != 0;
+ }
+
+
+ // Implementations for Clazz.
+
+ public int getAccessFlags()
+ {
+ return u2accessFlags;
+ }
+
+ public String getName()
+ {
+ return thisClassName;
+ }
+
+ public String getSuperName()
+ {
+ // This may be java/lang/Object, in which case there is no super.
+ return superClassName;
+ }
+
+ public int getInterfaceCount()
+ {
+ return interfaceClasses.length;
+ }
+
+ public String getInterfaceName(int index)
+ {
+ return interfaceNames[index];
+ }
+
+ public int getTag(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+ public String getString(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+ public String getStringString(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+ public String getClassName(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+ public String getName(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+ public String getType(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+
+ public String getRefClassName(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+ public String getRefName(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+ public String getRefType(int constantIndex)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool");
+ }
+
+
+ public void addSubClass(Clazz clazz)
+ {
+ if (subClasses == null)
+ {
+ subClasses = new Clazz[1];
+ }
+ else
+ {
+ // Copy the old elements into new larger array.
+ Clazz[] temp = new Clazz[subClasses.length+1];
+ System.arraycopy(subClasses, 0, temp, 0, subClasses.length);
+ subClasses = temp;
+ }
+
+ subClasses[subClasses.length-1] = clazz;
+ }
+
+
+ public Clazz getSuperClass()
+ {
+ return superClass;
+ }
+
+
+ public Clazz getInterface(int index)
+ {
+ return interfaceClasses[index];
+ }
+
+
+ public boolean extends_(Clazz clazz)
+ {
+ if (this.equals(clazz))
+ {
+ return true;
+ }
+
+ return superClass != null &&
+ superClass.extends_(clazz);
+ }
+
+
+ public boolean extends_(String className)
+ {
+ if (getName().equals(className))
+ {
+ return true;
+ }
+
+ return superClass != null &&
+ superClass.extends_(className);
+ }
+
+
+ public boolean extendsOrImplements(Clazz clazz)
+ {
+ if (this.equals(clazz))
+ {
+ return true;
+ }
+
+ if (superClass != null &&
+ superClass.extendsOrImplements(clazz))
+ {
+ return true;
+ }
+
+ if (interfaceClasses != null)
+ {
+ for (int index = 0; index < interfaceClasses.length; index++)
+ {
+ Clazz interfaceClass = interfaceClasses[index];
+ if (interfaceClass != null &&
+ interfaceClass.extendsOrImplements(clazz))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ public boolean extendsOrImplements(String className)
+ {
+ if (getName().equals(className))
+ {
+ return true;
+ }
+
+ if (superClass != null &&
+ superClass.extendsOrImplements(className))
+ {
+ return true;
+ }
+
+ if (interfaceClasses != null)
+ {
+ for (int index = 0; index < interfaceClasses.length; index++)
+ {
+ Clazz interfaceClass = interfaceClasses[index];
+ if (interfaceClass != null &&
+ interfaceClass.extendsOrImplements(className))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ public Field findField(String name, String descriptor)
+ {
+ for (int index = 0; index < fields.length; index++)
+ {
+ Field field = fields[index];
+ if (field != null &&
+ (name == null || field.getName(this).equals(name)) &&
+ (descriptor == null || field.getDescriptor(this).equals(descriptor)))
+ {
+ return field;
+ }
+ }
+
+ return null;
+ }
+
+
+ public Method findMethod(String name, String descriptor)
+ {
+ for (int index = 0; index < methods.length; index++)
+ {
+ Method method = methods[index];
+ if (method != null &&
+ (name == null || method.getName(this).equals(name)) &&
+ (descriptor == null || method.getDescriptor(this).equals(descriptor)))
+ {
+ return method;
+ }
+ }
+
+ return null;
+ }
+
+
+ public void accept(ClassVisitor classVisitor)
+ {
+ classVisitor.visitLibraryClass(this);
+ }
+
+
+ public void hierarchyAccept(boolean visitThisClass,
+ boolean visitSuperClass,
+ boolean visitInterfaces,
+ boolean visitSubclasses,
+ ClassVisitor classVisitor)
+ {
+ // First visit the current classfile.
+ if (visitThisClass)
+ {
+ accept(classVisitor);
+ }
+
+ // Then visit its superclass, recursively.
+ if (visitSuperClass)
+ {
+ if (superClass != null)
+ {
+ superClass.hierarchyAccept(true,
+ true,
+ visitInterfaces,
+ false,
+ classVisitor);
+ }
+ }
+
+ // Then visit its interfaces, recursively.
+ if (visitInterfaces)
+ {
+ // Visit the interfaces of the superclasses, if we haven't done so yet.
+ if (!visitSuperClass)
+ {
+ if (superClass != null)
+ {
+ superClass.hierarchyAccept(false,
+ false,
+ true,
+ false,
+ classVisitor);
+ }
+ }
+
+ // Visit the interfaces.
+ if (interfaceClasses != null)
+ {
+ for (int index = 0; index < interfaceClasses.length; index++)
+ {
+ Clazz interfaceClass = interfaceClasses[index];
+ if (interfaceClass != null)
+ {
+ interfaceClass.hierarchyAccept(true,
+ false,
+ true,
+ false,
+ classVisitor);
+ }
+ }
+ }
+ }
+
+ // Then visit its subclasses, recursively.
+ if (visitSubclasses)
+ {
+ if (subClasses != null)
+ {
+ for (int index = 0; index < subClasses.length; index++)
+ {
+ subClasses[index].hierarchyAccept(true,
+ false,
+ false,
+ true,
+ classVisitor);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Lets the given class visitor visit the superclass, if it is known.
+ * @param classVisitor the <code>ClassVisitor</code> that will visit the
+ * superclass.
+ */
+ public void superClassAccept(ClassVisitor classVisitor)
+ {
+ if (superClass != null)
+ {
+ superClass.accept(classVisitor);
+ }
+ }
+
+
+ /**
+ * Lets the given class visitor visit all known direct interfaces.
+ * @param classVisitor the <code>ClassVisitor</code> that will visit the
+ * interfaces.
+ */
+ public void interfacesAccept(ClassVisitor classVisitor)
+ {
+ if (interfaceClasses != null)
+ {
+ for (int index = 0; index < interfaceClasses.length; index++)
+ {
+ Clazz interfaceClass = interfaceClasses[index];
+ if (interfaceClass != null)
+ {
+ interfaceClass.accept(classVisitor);
+ }
+ }
+ }
+ }
+
+
+ public void subclassesAccept(ClassVisitor classVisitor)
+ {
+ if (subClasses != null)
+ {
+ for (int index = 0; index < subClasses.length; index++)
+ {
+ subClasses[index].accept(classVisitor);
+ }
+ }
+ }
+
+
+ public void constantPoolEntriesAccept(ConstantVisitor constantVisitor)
+ {
+ // This class doesn't keep references to its constant pool entries.
+ }
+
+
+ public void constantPoolEntryAccept(int index, ConstantVisitor constantVisitor)
+ {
+ // This class doesn't keep references to its constant pool entries.
+ }
+
+
+ public void thisClassConstantAccept(ConstantVisitor constantVisitor)
+ {
+ // This class doesn't keep references to its constant pool entries.
+ }
+
+
+ public void superClassConstantAccept(ConstantVisitor constantVisitor)
+ {
+ // This class doesn't keep references to its constant pool entries.
+ }
+
+
+ public void interfaceConstantsAccept(ConstantVisitor constantVisitor)
+ {
+ // This class doesn't keep references to its constant pool entries.
+ }
+
+
+ public void fieldsAccept(MemberVisitor memberVisitor)
+ {
+ for (int index = 0; index < fields.length; index++)
+ {
+ Field field = fields[index];
+ if (field != null)
+ {
+ field.accept(this, memberVisitor);
+ }
+ }
+ }
+
+
+ public void fieldAccept(String name, String descriptor, MemberVisitor memberVisitor)
+ {
+ Field field = findField(name, descriptor);
+ if (field != null)
+ {
+ field.accept(this, memberVisitor);
+ }
+ }
+
+
+ public void methodsAccept(MemberVisitor memberVisitor)
+ {
+ for (int index = 0; index < methods.length; index++)
+ {
+ Method method = methods[index];
+ if (method != null)
+ {
+ method.accept(this, memberVisitor);
+ }
+ }
+ }
+
+
+ public void methodAccept(String name, String descriptor, MemberVisitor memberVisitor)
+ {
+ Method method = findMethod(name, descriptor);
+ if (method != null)
+ {
+ method.accept(this, memberVisitor);
+ }
+ }
+
+
+ public boolean mayHaveImplementations(Method method)
+ {
+ return
+ (u2accessFlags & ClassConstants.ACC_FINAL) == 0 &&
+ (method == null ||
+ ((method.getAccessFlags() & (ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC |
+ ClassConstants.ACC_FINAL)) == 0 &&
+ !method.getName(this).equals(ClassConstants.METHOD_NAME_INIT)));
+ }
+
+
+ public void attributesAccept(AttributeVisitor attributeVisitor)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store attributes");
+ }
+
+
+ public void attributeAccept(String name, AttributeVisitor attributeVisitor)
+ {
+ throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store attributes");
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return "LibraryClass("+getName()+")";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryField.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryField.java
new file mode 100644
index 0000000000..843a9f9625
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryField.java
@@ -0,0 +1,77 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+import proguard.classfile.visitor.*;
+
+/**
+ * Representation of a field from a class-file.
+ *
+ * @author Eric Lafortune
+ */
+public class LibraryField extends LibraryMember implements Field
+{
+ /**
+ * An extra field pointing to the Clazz object referenced in the
+ * descriptor string. This field is filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}</code>.
+ * References to primitive types are ignored.
+ */
+ public Clazz referencedClass;
+
+
+ /**
+ * Creates an uninitialized LibraryField.
+ */
+ public LibraryField()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LibraryField.
+ */
+ public LibraryField(int u2accessFlags,
+ String name,
+ String descriptor)
+ {
+ super(u2accessFlags, name, descriptor);
+ }
+
+
+ // Implementations for LibraryMember.
+
+ public void accept(LibraryClass libraryClass, MemberVisitor memberVisitor)
+ {
+ memberVisitor.visitLibraryField(libraryClass, this);
+ }
+
+
+ // Implementations for Member.
+
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryMember.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryMember.java
new file mode 100644
index 0000000000..085e31a2d0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryMember.java
@@ -0,0 +1,104 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * Representation of a field or method from a library class.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class LibraryMember implements Member
+{
+ public int u2accessFlags;
+ public String name;
+ public String descriptor;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized LibraryMember.
+ */
+ protected LibraryMember()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LibraryMember.
+ */
+ protected LibraryMember(int u2accessFlags,
+ String name,
+ String descriptor)
+ {
+ this.u2accessFlags = u2accessFlags;
+ this.name = name;
+ this.descriptor = descriptor;
+ }
+
+
+ /**
+ * Accepts the given member info visitor.
+ */
+ public abstract void accept(LibraryClass libraryClass,
+ MemberVisitor memberVisitor);
+
+
+ // Implementations for Member.
+
+ public int getAccessFlags()
+ {
+ return u2accessFlags;
+ }
+
+ public String getName(Clazz clazz)
+ {
+ return name;
+ }
+
+ public String getDescriptor(Clazz clazz)
+ {
+ return descriptor;
+ }
+
+ public void accept(Clazz clazz, MemberVisitor memberVisitor)
+ {
+ accept((LibraryClass)clazz, memberVisitor);
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryMethod.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryMethod.java
new file mode 100644
index 0000000000..81012edb99
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/LibraryMethod.java
@@ -0,0 +1,85 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+import proguard.classfile.visitor.*;
+
+/**
+ * Representation of a method from a class-file.
+ *
+ * @author Eric Lafortune
+ */
+public class LibraryMethod extends LibraryMember implements Method
+{
+ /**
+ * An extra field containing all the classes referenced in the
+ * descriptor string. This field is filled out by the {@link
+ * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}.
+ * The size of the array is the number of classes in the descriptor.
+ * Primitive types and arrays of primitive types are ignored.
+ * Unknown classes are represented as null values.
+ */
+ public Clazz[] referencedClasses;
+
+
+ /**
+ * Creates an uninitialized LibraryMethod.
+ */
+ public LibraryMethod()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LibraryMethod.
+ */
+ public LibraryMethod(int u2accessFlags,
+ String name,
+ String descriptor)
+ {
+ super(u2accessFlags, name, descriptor);
+ }
+
+
+ // Implementations for LibraryMember.
+
+ public void accept(LibraryClass libraryClass, MemberVisitor memberVisitor)
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, this);
+ }
+
+
+ // Implementations for Member.
+
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ if (referencedClasses[index] != null)
+ {
+ referencedClasses[index].accept(classVisitor);
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Member.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Member.java
new file mode 100644
index 0000000000..92ccdd20c7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Member.java
@@ -0,0 +1,57 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+import proguard.classfile.visitor.*;
+
+/**
+ * Representation of a field or method from a class.
+ *
+ * @author Eric Lafortune
+ */
+public interface Member extends VisitorAccepter
+{
+ /**
+ * Returns the access flags.
+ */
+ public int getAccessFlags();
+
+ /**
+ * Returns the class member name.
+ */
+ public String getName(Clazz clazz);
+
+ /**
+ * Returns the class member's descriptor.
+ */
+ public String getDescriptor(Clazz clazz);
+
+ /**
+ * Accepts the given class visitor.
+ */
+ public void accept(Clazz clazz, MemberVisitor memberVisitor);
+
+ /**
+ * Lets the Clazz objects referenced in the descriptor string
+ * accept the given visitor.
+ */
+ public void referencedClassesAccept(ClassVisitor classVisitor);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Method.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Method.java
new file mode 100644
index 0000000000..2d48f83657
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/Method.java
@@ -0,0 +1,32 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+
+
+/**
+ * Representation of a method from a class.
+ *
+ * @author Eric Lafortune
+ */
+public interface Method extends Member
+{
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramClass.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramClass.java
new file mode 100644
index 0000000000..a2137f19f1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramClass.java
@@ -0,0 +1,584 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.ClassSubHierarchyInitializer;
+import proguard.classfile.visitor.*;
+
+/**
+ * This Clazz is a complete representation of the data in a Java class.
+ *
+ * @author Eric Lafortune
+ */
+public class ProgramClass implements Clazz
+{
+ public int u4magic;
+ public int u4version;
+ public int u2constantPoolCount;
+ public Constant[] constantPool;
+ public int u2accessFlags;
+ public int u2thisClass;
+ public int u2superClass;
+ public int u2interfacesCount;
+ public int[] u2interfaces;
+ public int u2fieldsCount;
+ public ProgramField[] fields;
+ public int u2methodsCount;
+ public ProgramMethod[] methods;
+ public int u2attributesCount;
+ public Attribute[] attributes;
+
+ /**
+ * An extra field pointing to the subclasses of this class.
+ * This field is filled out by the {@link ClassSubHierarchyInitializer}.
+ */
+ public Clazz[] subClasses;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized ProgramClass.
+ */
+ public ProgramClass() {}
+
+
+ /**
+ * Returns the Constant at the given index in the constant pool.
+ */
+ public Constant getConstant(int constantIndex)
+ {
+ return constantPool[constantIndex];
+ }
+
+
+ // Implementations for Clazz.
+
+ public int getAccessFlags()
+ {
+ return u2accessFlags;
+ }
+
+ public String getName()
+ {
+ return getClassName(u2thisClass);
+ }
+
+ public String getSuperName()
+ {
+ return u2superClass == 0 ? null : getClassName(u2superClass);
+ }
+
+ public int getInterfaceCount()
+ {
+ return u2interfacesCount;
+ }
+
+ public String getInterfaceName(int index)
+ {
+ return getClassName(u2interfaces[index]);
+ }
+
+ public int getTag(int constantIndex)
+ {
+ return constantPool[constantIndex].getTag();
+ }
+
+ public String getString(int constantIndex)
+ {
+ try
+ {
+ return ((Utf8Constant)constantPool[constantIndex]).getString();
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected Utf8Constant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
+ }
+ }
+
+ public String getStringString(int constantIndex)
+ {
+ try
+ {
+ return ((StringConstant)constantPool[constantIndex]).getString(this);
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected StringConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
+ }
+ }
+
+ public String getClassName(int constantIndex)
+ {
+ try
+ {
+ return ((ClassConstant)constantPool[constantIndex]).getName(this);
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected ClassConstant at index ["+constantIndex+"]").initCause(ex));
+ }
+ }
+
+ public String getName(int constantIndex)
+ {
+ try
+ {
+ return ((NameAndTypeConstant)constantPool[constantIndex]).getName(this);
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
+ }
+ }
+
+ public String getType(int constantIndex)
+ {
+ try
+ {
+ return ((NameAndTypeConstant)constantPool[constantIndex]).getType(this);
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
+ }
+ }
+
+
+ public String getRefClassName(int constantIndex)
+ {
+ try
+ {
+ return ((RefConstant)constantPool[constantIndex]).getClassName(this);
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected RefConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
+ }
+ }
+
+ public String getRefName(int constantIndex)
+ {
+ try
+ {
+ return ((RefConstant)constantPool[constantIndex]).getName(this);
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected RefConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
+ }
+ }
+
+ public String getRefType(int constantIndex)
+ {
+ try
+ {
+ return ((RefConstant)constantPool[constantIndex]).getType(this);
+ }
+ catch (ClassCastException ex)
+ {
+ throw ((IllegalStateException)new IllegalStateException("Expected RefConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex));
+ }
+ }
+
+
+ public void addSubClass(Clazz clazz)
+ {
+ if (subClasses == null)
+ {
+ subClasses = new Clazz[1];
+ }
+ else
+ {
+ // Copy the old elements into new larger array.
+ Clazz[] temp = new Clazz[subClasses.length+1];
+ System.arraycopy(subClasses, 0, temp, 0, subClasses.length);
+ subClasses = temp;
+ }
+
+ subClasses[subClasses.length-1] = clazz;
+ }
+
+
+ public Clazz getSuperClass()
+ {
+ return u2superClass != 0 ?
+ ((ClassConstant)constantPool[u2superClass]).referencedClass :
+ null;
+ }
+
+
+ public Clazz getInterface(int index)
+ {
+ return ((ClassConstant)constantPool[u2interfaces[index]]).referencedClass;
+ }
+
+
+ public boolean extends_(Clazz clazz)
+ {
+ if (this.equals(clazz))
+ {
+ return true;
+ }
+
+ Clazz superClass = getSuperClass();
+ return superClass != null &&
+ superClass.extends_(clazz);
+ }
+
+
+ public boolean extends_(String className)
+ {
+ if (getName().equals(className))
+ {
+ return true;
+ }
+
+ Clazz superClass = getSuperClass();
+ return superClass != null &&
+ superClass.extends_(className);
+ }
+
+
+ public boolean extendsOrImplements(Clazz clazz)
+ {
+ if (this.equals(clazz))
+ {
+ return true;
+ }
+
+ Clazz superClass = getSuperClass();
+ if (superClass != null &&
+ superClass.extendsOrImplements(clazz))
+ {
+ return true;
+ }
+
+ for (int index = 0; index < u2interfacesCount; index++)
+ {
+ Clazz interfaceClass = getInterface(index);
+ if (interfaceClass != null &&
+ interfaceClass.extendsOrImplements(clazz))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ public boolean extendsOrImplements(String className)
+ {
+ if (getName().equals(className))
+ {
+ return true;
+ }
+
+ Clazz superClass = getSuperClass();
+ if (superClass != null &&
+ superClass.extendsOrImplements(className))
+ {
+ return true;
+ }
+
+ for (int index = 0; index < u2interfacesCount; index++)
+ {
+ Clazz interfaceClass = getInterface(index);
+ if (interfaceClass != null &&
+ interfaceClass.extendsOrImplements(className))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ public Field findField(String name, String descriptor)
+ {
+ for (int index = 0; index < u2fieldsCount; index++)
+ {
+ Field field = fields[index];
+ if ((name == null || field.getName(this).equals(name)) &&
+ (descriptor == null || field.getDescriptor(this).equals(descriptor)))
+ {
+ return field;
+ }
+ }
+
+ return null;
+ }
+
+
+ public Method findMethod(String name, String descriptor)
+ {
+ for (int index = 0; index < u2methodsCount; index++)
+ {
+ Method method = methods[index];
+ if ((name == null || method.getName(this).equals(name)) &&
+ (descriptor == null || method.getDescriptor(this).equals(descriptor)))
+ {
+ return method;
+ }
+ }
+
+ return null;
+ }
+
+
+ public void accept(ClassVisitor classVisitor)
+ {
+ classVisitor.visitProgramClass(this);
+ }
+
+
+ public void hierarchyAccept(boolean visitThisClass,
+ boolean visitSuperClass,
+ boolean visitInterfaces,
+ boolean visitSubclasses,
+ ClassVisitor classVisitor)
+ {
+ // First visit the current classfile.
+ if (visitThisClass)
+ {
+ accept(classVisitor);
+ }
+
+ // Then visit its superclass, recursively.
+ if (visitSuperClass)
+ {
+ Clazz superClass = getSuperClass();
+ if (superClass != null)
+ {
+ superClass.hierarchyAccept(true,
+ true,
+ visitInterfaces,
+ false,
+ classVisitor);
+ }
+ }
+
+ // Then visit its interfaces, recursively.
+ if (visitInterfaces)
+ {
+ // Visit the interfaces of the superclasses, if we haven't done so yet.
+ if (!visitSuperClass)
+ {
+ Clazz superClass = getSuperClass();
+ if (superClass != null)
+ {
+ superClass.hierarchyAccept(false,
+ false,
+ true,
+ false,
+ classVisitor);
+ }
+ }
+
+ // Visit the interfaces.
+ for (int index = 0; index < u2interfacesCount; index++)
+ {
+ Clazz interfaceClass = getInterface(index);
+ if (interfaceClass != null)
+ {
+ interfaceClass.hierarchyAccept(true,
+ false,
+ true,
+ false,
+ classVisitor);
+ }
+ }
+ }
+
+ // Then visit its subclasses, recursively.
+ if (visitSubclasses)
+ {
+ if (subClasses != null)
+ {
+ for (int index = 0; index < subClasses.length; index++)
+ {
+ Clazz subClass = subClasses[index];
+ subClass.hierarchyAccept(true,
+ false,
+ false,
+ true,
+ classVisitor);
+ }
+ }
+ }
+ }
+
+
+ public void subclassesAccept(ClassVisitor classVisitor)
+ {
+ if (subClasses != null)
+ {
+ for (int index = 0; index < subClasses.length; index++)
+ {
+ subClasses[index].accept(classVisitor);
+ }
+ }
+ }
+
+
+ public void constantPoolEntriesAccept(ConstantVisitor constantVisitor)
+ {
+ for (int index = 1; index < u2constantPoolCount; index++)
+ {
+ if (constantPool[index] != null)
+ {
+ constantPool[index].accept(this, constantVisitor);
+ }
+ }
+ }
+
+
+ public void constantPoolEntryAccept(int index, ConstantVisitor constantVisitor)
+ {
+ constantPool[index].accept(this, constantVisitor);
+ }
+
+
+ public void thisClassConstantAccept(ConstantVisitor constantVisitor)
+ {
+ constantPool[u2thisClass].accept(this, constantVisitor);
+ }
+
+
+ public void superClassConstantAccept(ConstantVisitor constantVisitor)
+ {
+ if (u2superClass != 0)
+ {
+ constantPool[u2superClass].accept(this, constantVisitor);
+ }
+ }
+
+
+ public void interfaceConstantsAccept(ConstantVisitor constantVisitor)
+ {
+ for (int index = 0; index < u2interfacesCount; index++)
+ {
+ constantPool[u2interfaces[index]].accept(this, constantVisitor);
+ }
+ }
+
+
+ public void fieldsAccept(MemberVisitor memberVisitor)
+ {
+ for (int index = 0; index < u2fieldsCount; index++)
+ {
+ fields[index].accept(this, memberVisitor);
+ }
+ }
+
+
+ public void fieldAccept(String name, String descriptor, MemberVisitor memberVisitor)
+ {
+ Field field = findField(name, descriptor);
+ if (field != null)
+ {
+ field.accept(this, memberVisitor);
+ }
+ }
+
+
+ public void methodsAccept(MemberVisitor memberVisitor)
+ {
+ for (int index = 0; index < u2methodsCount; index++)
+ {
+ methods[index].accept(this, memberVisitor);
+ }
+ }
+
+
+ public void methodAccept(String name, String descriptor, MemberVisitor memberVisitor)
+ {
+ Method method = findMethod(name, descriptor);
+ if (method != null)
+ {
+ method.accept(this, memberVisitor);
+ }
+ }
+
+
+ public boolean mayHaveImplementations(Method method)
+ {
+ return
+ (u2accessFlags & ClassConstants.ACC_FINAL) == 0 &&
+ (method == null ||
+ ((method.getAccessFlags() & (ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC |
+ ClassConstants.ACC_FINAL)) == 0 &&
+ !method.getName(this).equals(ClassConstants.METHOD_NAME_INIT)));
+ }
+
+
+ public void attributesAccept(AttributeVisitor attributeVisitor)
+ {
+ for (int index = 0; index < u2attributesCount; index++)
+ {
+ attributes[index].accept(this, attributeVisitor);
+ }
+ }
+
+
+ public void attributeAccept(String name, AttributeVisitor attributeVisitor)
+ {
+ for (int index = 0; index < u2attributesCount; index++)
+ {
+ Attribute attribute = attributes[index];
+ if (attribute.getAttributeName(this).equals(name))
+ {
+ attribute.accept(this, attributeVisitor);
+ }
+ }
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return "ProgramClass("+getName()+")";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramField.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramField.java
new file mode 100644
index 0000000000..1d3140f2e8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramField.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * Representation of a field from a program class.
+ *
+ * @author Eric Lafortune
+ */
+public class ProgramField extends ProgramMember implements Field
+{
+ /**
+ * An extra field pointing to the Clazz object referenced in the
+ * descriptor string. This field is filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}</code>.
+ * References to primitive types are ignored.
+ */
+ public Clazz referencedClass;
+
+
+ /**
+ * Creates an uninitialized ProgramField.
+ */
+ public ProgramField()
+ {
+ }
+
+
+ /**
+ * Creates an initialized ProgramField.
+ */
+ public ProgramField(int u2accessFlags,
+ int u2nameIndex,
+ int u2descriptorIndex,
+ int u2attributesCount,
+ Attribute[] attributes,
+ Clazz referencedClass)
+ {
+ super(u2accessFlags, u2nameIndex, u2descriptorIndex, u2attributesCount, attributes);
+
+ this.referencedClass = referencedClass;
+ }
+
+
+ // Implementations for ProgramMember.
+
+ public void accept(ProgramClass programClass, MemberVisitor memberVisitor)
+ {
+ memberVisitor.visitProgramField(programClass, this);
+ }
+
+
+ public void attributesAccept(ProgramClass programClass, AttributeVisitor attributeVisitor)
+ {
+ for (int index = 0; index < u2attributesCount; index++)
+ {
+ attributes[index].accept(programClass, this, attributeVisitor);
+ }
+ }
+
+
+ // Implementations for Member.
+
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramMember.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramMember.java
new file mode 100644
index 0000000000..8736bf83cb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramMember.java
@@ -0,0 +1,140 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * Representation of a field or method from a program class.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class ProgramMember implements Member
+{
+ public int u2accessFlags;
+ public int u2nameIndex;
+ public int u2descriptorIndex;
+ public int u2attributesCount;
+ public Attribute[] attributes;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized ProgramMember.
+ */
+ protected ProgramMember()
+ {
+ }
+
+
+ /**
+ * Creates an initialized ProgramMember.
+ */
+ protected ProgramMember(int u2accessFlags,
+ int u2nameIndex,
+ int u2descriptorIndex,
+ int u2attributesCount,
+ Attribute[] attributes)
+ {
+ this.u2accessFlags = u2accessFlags;
+ this.u2nameIndex = u2nameIndex;
+ this.u2descriptorIndex = u2descriptorIndex;
+ this.u2attributesCount = u2attributesCount;
+ this.attributes = attributes;
+ }
+
+
+ /**
+ * Returns the (first) attribute with the given name.
+ */
+ private Attribute getAttribute(Clazz clazz, String name)
+ {
+ for (int index = 0; index < u2attributesCount; index++)
+ {
+ Attribute attribute = attributes[index];
+ if (attribute.getAttributeName(clazz).equals(name))
+ {
+ return attribute;
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Accepts the given member info visitor.
+ */
+ public abstract void accept(ProgramClass programClass,
+ MemberVisitor memberVisitor);
+
+
+
+ /**
+ * Lets the given attribute info visitor visit all the attributes of
+ * this member info.
+ */
+ public abstract void attributesAccept(ProgramClass programClass,
+ AttributeVisitor attributeVisitor);
+
+
+ // Implementations for Member.
+
+ public int getAccessFlags()
+ {
+ return u2accessFlags;
+ }
+
+ public String getName(Clazz clazz)
+ {
+ return clazz.getString(u2nameIndex);
+ }
+
+ public String getDescriptor(Clazz clazz)
+ {
+ return clazz.getString(u2descriptorIndex);
+ }
+
+ public void accept(Clazz clazz, MemberVisitor memberVisitor)
+ {
+ accept((ProgramClass)clazz, memberVisitor);
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramMethod.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramMethod.java
new file mode 100644
index 0000000000..b13f2ef9ac
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/ProgramMethod.java
@@ -0,0 +1,101 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * Representation of a method from a program class.
+ *
+ * @author Eric Lafortune
+ */
+public class ProgramMethod extends ProgramMember implements Method
+{
+ /**
+ * An extra field containing all the classes referenced in the
+ * descriptor string. This field is filled out by the {@link
+ * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}.
+ * The size of the array is the number of classes in the descriptor.
+ * Primitive types and arrays of primitive types are ignored.
+ * Unknown classes are represented as null values.
+ */
+ public Clazz[] referencedClasses;
+
+
+ /**
+ * Creates an uninitialized ProgramMethod.
+ */
+ public ProgramMethod()
+ {
+ }
+
+
+ /**
+ * Creates an initialized ProgramMethod.
+ */
+ public ProgramMethod(int u2accessFlags,
+ int u2nameIndex,
+ int u2descriptorIndex,
+ int u2attributesCount,
+ Attribute[] attributes,
+ Clazz[] referencedClasses)
+ {
+ super(u2accessFlags, u2nameIndex, u2descriptorIndex, u2attributesCount, attributes);
+
+ this.referencedClasses = referencedClasses;
+ }
+
+
+ // Implementations for ProgramMember.
+
+ public void accept(ProgramClass programClass, MemberVisitor memberVisitor)
+ {
+ memberVisitor.visitProgramMethod(programClass, this);
+ }
+
+
+ public void attributesAccept(ProgramClass programClass, AttributeVisitor attributeVisitor)
+ {
+ for (int index = 0; index < u2attributesCount; index++)
+ {
+ attributes[index].accept(programClass, this, attributeVisitor);
+ }
+ }
+
+
+ // Implementations for Member.
+
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ if (referencedClasses[index] != null)
+ {
+ referencedClasses[index].accept(classVisitor);
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/VisitorAccepter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/VisitorAccepter.java
new file mode 100644
index 0000000000..d06766adf5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/VisitorAccepter.java
@@ -0,0 +1,47 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile;
+
+
+
+
+/**
+ * This interface is a base interface for visitor accepters. It allows
+ * visitors to set and get any temporary information they desire on the
+ * objects they are visiting. Note that every visitor accepter has only one
+ * such property, so visitors will have to take care not to overwrite each
+ * other's information, if it is still required.
+ *
+ * @author Eric Lafortune
+ */
+public interface VisitorAccepter
+{
+ /**
+ * Gets the visitor information of the visitor accepter.
+ */
+ public Object getVisitorInfo();
+
+
+ /**
+ * Sets the visitor information of the visitor accepter.
+ */
+ public void setVisitorInfo(Object visitorInfo);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/Attribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/Attribute.java
new file mode 100644
index 0000000000..4a475a02a6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/Attribute.java
@@ -0,0 +1,143 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This abstract class represents an attribute that is attached to a class,
+ * a class member, or a code attribute. Specific types of attributes are
+ * subclassed from it.
+ *
+ * @author Eric Lafortune
+ * @noinspection AbstractClassWithoutAbstractMethods
+ */
+public abstract class Attribute implements VisitorAccepter
+{
+ public int u2attributeNameIndex;
+ //public int u4attributeLength;
+ //public byte info[];
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Create an uninitialized Attribute.
+ */
+ protected Attribute()
+ {
+ }
+
+
+ /**
+ * Create an initialized Attribute.
+ */
+ protected Attribute(int u2attributeNameIndex)
+ {
+ this.u2attributeNameIndex = u2attributeNameIndex;
+ }
+
+
+ /**
+ * Returns the String name of the attribute.
+ */
+ public String getAttributeName(Clazz clazz)
+ {
+ return clazz.getString(u2attributeNameIndex);
+ }
+
+
+ // Methods to be implemented by extensions, if applicable.
+
+ /**
+ * Accepts the given visitor.
+ */
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+ /**
+ * Accepts the given visitor in the context of the given field.
+ */
+ public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor)
+ {
+ // Delegate to the default invocation if the field is null anyway.
+ if (field == null)
+ {
+ accept(clazz, attributeVisitor);
+ }
+ else
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+ }
+
+ /**
+ * Accepts the given visitor in the context of the given method.
+ */
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ // Delegate to the default invocation if the method is null anyway.
+ if (method == null)
+ {
+ accept(clazz, (Field)null, attributeVisitor);
+ }
+ else
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+ }
+
+ /**
+ * Accepts the given visitor in the context of the given code attribute.
+ */
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
+ {
+ // Delegate to the default invocation if the code attribute is null
+ // anyway.
+ if (codeAttribute == null)
+ {
+ accept(clazz, method, attributeVisitor);
+ }
+ else
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/BootstrapMethodInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/BootstrapMethodInfo.java
new file mode 100755
index 0000000000..62902571a1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/BootstrapMethodInfo.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * Representation of a bootstrap method.
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodInfo implements VisitorAccepter
+{
+ public int u2methodHandleIndex;
+ public int u2methodArgumentCount;
+ public int[] u2methodArguments;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized BootstrapMethodInfo.
+ */
+ public BootstrapMethodInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized BootstrapMethodInfo.
+ */
+ public BootstrapMethodInfo(int u2methodHandleIndex,
+ int u2methodArgumentCount,
+ int[] u2methodArguments)
+ {
+ this.u2methodHandleIndex = u2methodHandleIndex;
+ this.u2methodArgumentCount = u2methodArgumentCount;
+ this.u2methodArguments = u2methodArguments;
+ }
+
+
+ /**
+ * Applies the given constant pool visitor to the argument constants of the
+ * bootstrap method.
+ */
+ public void methodArgumentsAccept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ for (int index = 0; index < u2methodArgumentCount; index++)
+ {
+ clazz.constantPoolEntryAccept(u2methodArguments[index],
+ constantVisitor);
+ }
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java
new file mode 100755
index 0000000000..08970e1d05
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.visitor.*;
+
+/**
+ * This Attribute represents a bootstrap methods attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodsAttribute extends Attribute
+{
+ public int u2bootstrapMethodsCount;
+ public BootstrapMethodInfo[] bootstrapMethods;
+
+
+ /**
+ * Creates an uninitialized BootstrapMethodsAttribute.
+ */
+ public BootstrapMethodsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized BootstrapMethodsAttribute.
+ */
+ public BootstrapMethodsAttribute(int u2attributeNameIndex,
+ int u2bootstrapMethodsCount,
+ BootstrapMethodInfo[] bootstrapMethods)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2bootstrapMethodsCount = u2bootstrapMethodsCount;
+ this.bootstrapMethods = bootstrapMethods;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitBootstrapMethodsAttribute(clazz, this);
+ }
+
+
+ /**
+ * Applies the given visitor to all bootstrap method info entries.
+ */
+ public void bootstrapMethodEntriesAccept(Clazz clazz, BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor)
+ {
+ for (int index = 0; index < u2bootstrapMethodsCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of BootstrapMethodInfo.
+ bootstrapMethodInfoVisitor.visitBootstrapMethodInfo(clazz, bootstrapMethods[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to the specified bootstrap method info
+ * entry.
+ */
+ public void bootstrapMethodEntryAccept(Clazz clazz,
+ int bootstrapMethodIndex,
+ BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of BootstrapMethodInfo.
+ bootstrapMethodInfoVisitor.visitBootstrapMethodInfo(clazz, bootstrapMethods[bootstrapMethodIndex]);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/CodeAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/CodeAttribute.java
new file mode 100644
index 0000000000..0afd5dcbf2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/CodeAttribute.java
@@ -0,0 +1,202 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+
+/**
+ * This Attribute represents a code attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class CodeAttribute extends Attribute
+{
+ public int u2maxStack;
+ public int u2maxLocals;
+ public int u4codeLength;
+ public byte[] code;
+ public int u2exceptionTableLength;
+ public ExceptionInfo[] exceptionTable;
+ public int u2attributesCount;
+ public Attribute[] attributes;
+
+
+ /**
+ * Creates an uninitialized CodeAttribute.
+ */
+ public CodeAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized CodeAttribute.
+ */
+ public CodeAttribute(int u2attributeNameIndex,
+ int u2maxStack,
+ int u2maxLocals,
+ int u4codeLength,
+ byte[] code,
+ int u2exceptionTableLength,
+ ExceptionInfo[] exceptionTable,
+ int u2attributesCount,
+ Attribute[] attributes)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2maxStack = u2maxStack;
+ this.u2maxLocals = u2maxLocals;
+ this.u4codeLength = u4codeLength;
+ this.code = code;
+ this.u2exceptionTableLength = u2exceptionTableLength;
+ this.exceptionTable = exceptionTable;
+ this.u2attributesCount = u2attributesCount;
+ this.attributes = attributes;
+ }
+
+
+ /**
+ * Returns the (first) attribute with the given name.
+ */
+ public Attribute getAttribute(Clazz clazz, String name)
+ {
+ for (int index = 0; index < u2attributesCount; index++)
+ {
+ Attribute attribute = attributes[index];
+ if (attribute.getAttributeName(clazz).equals(name))
+ {
+ return attribute;
+ }
+ }
+
+ return null;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitCodeAttribute(clazz, method, this);
+ }
+
+
+ /**
+ * Applies the given instruction visitor to all instructions.
+ */
+ public void instructionsAccept(Clazz clazz, Method method, InstructionVisitor instructionVisitor)
+ {
+ instructionsAccept(clazz, method, 0, u4codeLength, instructionVisitor);
+ }
+
+
+ /**
+ * Applies the given instruction visitor to the instruction at the specified
+ * offset.
+ */
+ public void instructionAccept(Clazz clazz, Method method, int offset, InstructionVisitor instructionVisitor)
+ {
+ Instruction instruction = InstructionFactory.create(code, offset);
+ instruction.accept(clazz, method, this, offset, instructionVisitor);
+ }
+
+
+ /**
+ * Applies the given instruction visitor to all instructions in the
+ * specified range of offsets.
+ */
+ public void instructionsAccept(Clazz clazz, Method method, int startOffset, int endOffset, InstructionVisitor instructionVisitor)
+ {
+ int offset = startOffset;
+
+ while (offset < endOffset)
+ {
+ // Note that the instruction is only volatile.
+ Instruction instruction = InstructionFactory.create(code, offset);
+ int instructionLength = instruction.length(offset);
+ instruction.accept(clazz, method, this, offset, instructionVisitor);
+ offset += instructionLength;
+ }
+ }
+
+
+ /**
+ * Applies the given exception visitor to all exceptions.
+ */
+ public void exceptionsAccept(Clazz clazz, Method method, ExceptionInfoVisitor exceptionInfoVisitor)
+ {
+ for (int index = 0; index < u2exceptionTableLength; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of ExceptionInfo.
+ exceptionInfoVisitor.visitExceptionInfo(clazz, method, this, exceptionTable[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given exception visitor to all exceptions that are applicable
+ * to the instruction at the specified offset.
+ */
+ public void exceptionsAccept(Clazz clazz, Method method, int offset, ExceptionInfoVisitor exceptionInfoVisitor)
+ {
+ for (int index = 0; index < u2exceptionTableLength; index++)
+ {
+ ExceptionInfo exceptionInfo = exceptionTable[index];
+ if (exceptionInfo.isApplicable(offset))
+ {
+ exceptionInfoVisitor.visitExceptionInfo(clazz, method, this, exceptionInfo);
+ }
+ }
+ }
+
+
+ /**
+ * Applies the given exception visitor to all exceptions that are applicable
+ * to any of the instructions in the specified range of offsets.
+ */
+ public void exceptionsAccept(Clazz clazz, Method method, int startOffset, int endOffset, ExceptionInfoVisitor exceptionInfoVisitor)
+ {
+ for (int index = 0; index < u2exceptionTableLength; index++)
+ {
+ ExceptionInfo exceptionInfo = exceptionTable[index];
+ if (exceptionInfo.isApplicable(startOffset, endOffset))
+ {
+ exceptionInfoVisitor.visitExceptionInfo(clazz, method, this, exceptionInfo);
+ }
+ }
+ }
+
+
+ /**
+ * Applies the given attribute visitor to all attributes.
+ */
+ public void attributesAccept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ for (int index = 0; index < u2attributesCount; index++)
+ {
+ attributes[index].accept(clazz, method, this, attributeVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ConstantValueAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ConstantValueAttribute.java
new file mode 100644
index 0000000000..c4d9d808b9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ConstantValueAttribute.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a constant value attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantValueAttribute extends Attribute
+{
+ public int u2constantValueIndex;
+
+
+ /**
+ * Creates an uninitialized ConstantValueAttribute.
+ */
+ public ConstantValueAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized ConstantValueAttribute.
+ */
+ public ConstantValueAttribute(int u2attributeNameIndex,
+ int u2constantValueIndex)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2constantValueIndex = u2constantValueIndex;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitConstantValueAttribute(clazz, field, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/DeprecatedAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/DeprecatedAttribute.java
new file mode 100644
index 0000000000..ad3ac4be91
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/DeprecatedAttribute.java
@@ -0,0 +1,66 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a deprecated attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class DeprecatedAttribute extends Attribute
+{
+ /**
+ * Creates an uninitialized DeprecatedAttribute.
+ */
+ public DeprecatedAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized DeprecatedAttribute.
+ */
+ public DeprecatedAttribute(int u2attributeNameIndex)
+ {
+ super(u2attributeNameIndex);
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, this);
+ }
+
+ public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, field, this);
+ }
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, method, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/EnclosingMethodAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/EnclosingMethodAttribute.java
new file mode 100644
index 0000000000..a01fc5a7ad
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/EnclosingMethodAttribute.java
@@ -0,0 +1,132 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This Attribute represents an enclosing method attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class EnclosingMethodAttribute extends Attribute
+{
+ public int u2classIndex;
+ public int u2nameAndTypeIndex;
+
+ /**
+ * An extra field pointing to the referenced Clazz object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ */
+ public Clazz referencedClass;
+
+ /**
+ * An extra field optionally pointing to the referenced Method object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ */
+ public Method referencedMethod;
+
+
+ /**
+ * Creates an uninitialized EnclosingMethodAttribute.
+ */
+ public EnclosingMethodAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized EnclosingMethodAttribute.
+ */
+ public EnclosingMethodAttribute(int u2attributeNameIndex,
+ int u2classIndex,
+ int u2nameAndTypeIndex)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2classIndex = u2classIndex;
+ this.u2nameAndTypeIndex = u2nameAndTypeIndex;
+ }
+
+
+ /**
+ * Returns the class name.
+ */
+ public String getClassName(Clazz clazz)
+ {
+ return clazz.getClassName(u2classIndex);
+ }
+
+ /**
+ * Returns the method/field name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getName(u2nameAndTypeIndex);
+ }
+
+ /**
+ * Returns the type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getType(u2nameAndTypeIndex);
+ }
+
+
+ /**
+ * Lets the referenced class accept the given visitor.
+ */
+ public void referencedClassAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+
+
+ /**
+ * Lets the referenced class member accept the given visitor.
+ */
+ public void referencedMethodAccept(MemberVisitor memberVisitor)
+ {
+ if (referencedMethod != null)
+ {
+ referencedMethod.accept(referencedClass,
+ memberVisitor);
+ }
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitEnclosingMethodAttribute(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExceptionInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExceptionInfo.java
new file mode 100644
index 0000000000..5c35e6f12f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExceptionInfo.java
@@ -0,0 +1,100 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.VisitorAccepter;
+
+/**
+ * Representation of an Exception table entry.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionInfo implements VisitorAccepter
+{
+ public int u2startPC;
+ public int u2endPC;
+ public int u2handlerPC;
+ public int u2catchType;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized ExceptionInfo.
+ */
+ public ExceptionInfo()
+ {
+ this(0, 0, 0, 0);
+ }
+
+
+ /**
+ * Creates an ExceptionInfo with the given properties.
+ */
+ public ExceptionInfo(int u2startPC,
+ int u2endPC,
+ int u2handlerPC,
+ int u2catchType)
+ {
+ this.u2startPC = u2startPC;
+ this.u2endPC = u2endPC;
+ this.u2handlerPC = u2handlerPC;
+ this.u2catchType = u2catchType;
+ }
+
+
+ /**
+ * Returns whether the exception's try block contains the instruction at the
+ * given offset.
+ */
+ public boolean isApplicable(int instructionOffset)
+ {
+ return instructionOffset >= u2startPC &&
+ instructionOffset < u2endPC;
+ }
+
+
+ /**
+ * Returns whether the exception's try block overlaps with the specified
+ * block of instructions.
+ */
+ public boolean isApplicable(int startOffset, int endOffset)
+ {
+ return u2startPC < endOffset &&
+ u2endPC > startOffset;
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExceptionsAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExceptionsAttribute.java
new file mode 100644
index 0000000000..a47fc57e38
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExceptionsAttribute.java
@@ -0,0 +1,80 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Attribute represents an exceptions attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionsAttribute extends Attribute
+{
+ public int u2exceptionIndexTableLength;
+ public int[] u2exceptionIndexTable;
+
+
+ /**
+ * Creates an uninitialized ExceptionsAttribute.
+ */
+ public ExceptionsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized ExceptionsAttribute.
+ */
+ public ExceptionsAttribute(int u2attributeNameIndex,
+ int u2exceptionIndexTableLength,
+ int[] u2exceptionIndexTable)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2exceptionIndexTableLength = u2exceptionIndexTableLength;
+ this.u2exceptionIndexTable = u2exceptionIndexTable;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitExceptionsAttribute(clazz, method, this);
+ }
+
+
+ /**
+ * Applies the given constant pool visitor to all exception class pool info
+ * entries.
+ */
+ public void exceptionEntriesAccept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ for (int index = 0; index < u2exceptionIndexTableLength; index++)
+ {
+ clazz.constantPoolEntryAccept(u2exceptionIndexTable[index],
+ constantVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExtendedLineNumberInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExtendedLineNumberInfo.java
new file mode 100644
index 0000000000..8f910bdb87
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ExtendedLineNumberInfo.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+/**
+ * This line number table entry contains additional information about its
+ * source. This information can not be represented in class files, but it
+ * can be used internally to represent lines in inlined or merged code.
+ *
+ * @author Eric Lafortune
+ */
+public class ExtendedLineNumberInfo
+extends LineNumberInfo
+{
+ public String source;
+
+
+ /**
+ * Creates an uninitialized ExtendedLineNumberInfo.
+ */
+ public ExtendedLineNumberInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized ExtendedLineNumberInfo.
+ */
+ public ExtendedLineNumberInfo(int u2startPC,
+ int u2lineNumber,
+ String source)
+ {
+ super(u2startPC, u2lineNumber);
+
+ this.source = source;
+ }
+
+
+ // Implementations for LineNumberInfo.
+
+ public String getSource()
+ {
+ return source;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/InnerClassesAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/InnerClassesAttribute.java
new file mode 100644
index 0000000000..bb81ece462
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/InnerClassesAttribute.java
@@ -0,0 +1,80 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.visitor.*;
+
+/**
+ * This Attribute represents an inner classes attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class InnerClassesAttribute extends Attribute
+{
+ public int u2classesCount;
+ public InnerClassesInfo[] classes;
+
+
+ /**
+ * Creates an uninitialized InnerClassesAttribute.
+ */
+ public InnerClassesAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized InnerClassesAttribute.
+ */
+ public InnerClassesAttribute(int u2attributeNameIndex,
+ int u2classesCount,
+ InnerClassesInfo[] classes)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2classesCount = u2classesCount;
+ this.classes = classes;
+ }
+
+ //
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitInnerClassesAttribute(clazz, this);
+ }
+
+
+ /**
+ * Applies the given visitor to all inner classes.
+ */
+ public void innerClassEntriesAccept(Clazz clazz, InnerClassesInfoVisitor innerClassesInfoVisitor)
+ {
+ for (int index = 0; index < u2classesCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of InnerClassesInfo.
+ innerClassesInfoVisitor.visitInnerClassesInfo(clazz, classes[index]);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/InnerClassesInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/InnerClassesInfo.java
new file mode 100644
index 0000000000..21938ea292
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/InnerClassesInfo.java
@@ -0,0 +1,119 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * Representation of an Inner Classes table entry.
+ *
+ * @author Eric Lafortune
+ */
+public class InnerClassesInfo implements VisitorAccepter
+{
+ public int u2innerClassIndex;
+ public int u2outerClassIndex;
+ public int u2innerNameIndex;
+ public int u2innerClassAccessFlags;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Returns the inner class index.
+ */
+ protected int getInnerClassIndex()
+ {
+ return u2innerClassIndex;
+ }
+
+ /**
+ * Returns the name index.
+ */
+ protected int getInnerNameIndex()
+ {
+ return u2innerNameIndex;
+ }
+
+ /**
+ * Sets the name index.
+ */
+ protected void setInnerNameIndex(int index)
+ {
+ u2innerNameIndex = index;
+ }
+
+
+ /**
+ * Applies the given constant pool visitor to the class constant of the
+ * inner class, if any.
+ */
+ public void innerClassConstantAccept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ if (u2innerClassIndex != 0)
+ {
+ clazz.constantPoolEntryAccept(u2innerClassIndex, constantVisitor);
+ }
+ }
+
+
+ /**
+ * Applies the given constant pool visitor to the class constant of the
+ * outer class, if any.
+ */
+ public void outerClassConstantAccept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ if (u2outerClassIndex != 0)
+ {
+ clazz.constantPoolEntryAccept(u2outerClassIndex, constantVisitor);
+ }
+ }
+
+
+ /**
+ * Applies the given constant pool visitor to the Utf8 constant of the
+ * inner name, if any.
+ */
+ public void innerNameConstantAccept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ if (u2innerNameIndex != 0)
+ {
+ clazz.constantPoolEntryAccept(u2innerNameIndex, constantVisitor);
+ }
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LineNumberInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LineNumberInfo.java
new file mode 100644
index 0000000000..ab0ee32f0d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LineNumberInfo.java
@@ -0,0 +1,61 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+/**
+ * Representation of an Line Number table entry.
+ *
+ * @author Eric Lafortune
+ */
+public class LineNumberInfo
+{
+ public int u2startPC;
+ public int u2lineNumber;
+
+
+ /**
+ * Creates an uninitialized LineNumberInfo.
+ */
+ public LineNumberInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LineNumberInfo.
+ */
+ public LineNumberInfo(int u2startPC, int u2lineNumber)
+ {
+ this.u2startPC = u2startPC;
+ this.u2lineNumber = u2lineNumber;
+ }
+
+
+ /**
+ * Returns a description of the source of the line, if known, or null
+ * otherwise. Standard line number entries don't contain information
+ * about their source; it is assumed to be the same source file.
+ */
+ public String getSource()
+ {
+ return null;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LineNumberTableAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LineNumberTableAttribute.java
new file mode 100644
index 0000000000..bc9dd4d60a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LineNumberTableAttribute.java
@@ -0,0 +1,174 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+
+/**
+ * This Attribute represents a line number table attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class LineNumberTableAttribute extends Attribute
+{
+ public int u2lineNumberTableLength;
+ public LineNumberInfo[] lineNumberTable;
+
+
+ /**
+ * Creates an uninitialized LineNumberTableAttribute.
+ */
+ public LineNumberTableAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LineNumberTableAttribute.
+ */
+ public LineNumberTableAttribute(int u2attributeNameIndex,
+ int u2lineNumberTableLength,
+ LineNumberInfo[] lineNumberTable)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2lineNumberTableLength = u2lineNumberTableLength;
+ this.lineNumberTable = lineNumberTable;
+ }
+
+
+ /**
+ * Returns the line number corresponding to the given byte code program
+ * counter.
+ */
+ public int getLineNumber(int pc)
+ {
+ LineNumberInfo info = getLineNumberInfo(pc);
+
+ return info == null ? 0 : info.u2lineNumber;
+ }
+
+
+ /**
+ * Returns the source corresponding to the given byte code program
+ * counter.
+ */
+ public String getSource(int pc)
+ {
+ LineNumberInfo info = getLineNumberInfo(pc);
+
+ return info == null ? null : info.getSource();
+ }
+
+
+ /**
+ * Returns the line number info corresponding to the given byte code
+ * program counter.
+ */
+ public LineNumberInfo getLineNumberInfo(int pc)
+ {
+ for (int index = u2lineNumberTableLength-1; index >= 0; index--)
+ {
+ LineNumberInfo info = lineNumberTable[index];
+ if (pc >= info.u2startPC)
+ {
+ return info;
+ }
+ }
+
+ return u2lineNumberTableLength > 0 ?
+ lineNumberTable[0] :
+ null;
+ }
+
+
+ /**
+ * Returns the lowest line number with the default null source,
+ * or 0 if there aren't any such line numbers.
+ */
+ public int getLowestLineNumber()
+ {
+ int lowestLineNumber = Integer.MAX_VALUE;
+
+ for (int index = 0; index < u2lineNumberTableLength; index++)
+ {
+ LineNumberInfo info = lineNumberTable[index];
+ if (info.getSource() == null)
+ {
+ int lineNumber = info.u2lineNumber;
+ if (lineNumber < lowestLineNumber)
+ {
+ lowestLineNumber = lineNumber;
+ }
+ }
+ }
+
+ return lowestLineNumber == Integer.MAX_VALUE ? 0 : lowestLineNumber;
+ }
+
+
+ /**
+ * Returns the highest line number with the default null source,
+ * or 0 if there aren't any such line numbers.
+ */
+ public int getHighestLineNumber()
+ {
+ int highestLineNumber = 0;
+
+ for (int index = 0; index < u2lineNumberTableLength; index++)
+ {
+ LineNumberInfo info = lineNumberTable[index];
+ if (info.getSource() == null)
+ {
+ int lineNumber = info.u2lineNumber;
+ if (lineNumber > highestLineNumber)
+ {
+ highestLineNumber = lineNumber;
+ }
+ }
+ }
+
+ return highestLineNumber;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitLineNumberTableAttribute(clazz, method, codeAttribute, this);
+ }
+
+
+ /**
+ * Applies the given visitor to all line numbers.
+ */
+ public void lineNumbersAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfoVisitor lineNumberInfoVisitor)
+ {
+ for (int index = 0; index < u2lineNumberTableLength; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of LineNumberInfo.
+ lineNumberInfoVisitor.visitLineNumberInfo(clazz, method, codeAttribute, lineNumberTable[index]);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableInfo.java
new file mode 100644
index 0000000000..3cdc66ed9c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableInfo.java
@@ -0,0 +1,135 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * Representation of an Local Variable table entry.
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableInfo implements VisitorAccepter, Comparable
+{
+ public int u2startPC;
+ public int u2length;
+ public int u2nameIndex;
+ public int u2descriptorIndex;
+ public int u2index;
+
+ /**
+ * An extra field pointing to the referenced Clazz object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ */
+ public Clazz referencedClass;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized LocalVariableInfo.
+ */
+ public LocalVariableInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LocalVariableInfo.
+ */
+ public LocalVariableInfo(int u2startPC,
+ int u2length,
+ int u2nameIndex,
+ int u2descriptorIndex,
+ int u2index)
+ {
+ this.u2startPC = u2startPC;
+ this.u2length = u2length;
+ this.u2nameIndex = u2nameIndex;
+ this.u2descriptorIndex = u2descriptorIndex;
+ this.u2index = u2index;
+ }
+
+
+ /**
+ * Returns the name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getString(u2nameIndex);
+ }
+
+
+ /**
+ * Returns the descriptor.
+ */
+ public String getDescriptor(Clazz clazz)
+ {
+ return clazz.getString(u2descriptorIndex);
+ }
+
+
+ /**
+ * Lets the referenced class accept the given visitor.
+ */
+ public void referencedClassAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+
+
+ // Implementations for Comparable.
+
+ public int compareTo(Object object)
+ {
+ LocalVariableInfo other = (LocalVariableInfo)object;
+
+ return
+ this.u2startPC < other.u2startPC ? -1 : this.u2startPC > other.u2startPC ? 1 :
+ this.u2index < other.u2index ? -1 : this.u2index > other.u2index ? 1 :
+ this.u2length < other.u2length ? -1 : this.u2length > other.u2length ? 1 :
+ this.u2descriptorIndex < other.u2descriptorIndex ? -1 : this.u2descriptorIndex > other.u2descriptorIndex ? 1 :
+ this.u2nameIndex < other.u2nameIndex ? -1 : this.u2nameIndex > other.u2nameIndex ? 1 :
+ 0;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTableAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
new file mode 100644
index 0000000000..67fe03120c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
@@ -0,0 +1,79 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+
+/**
+ * This Attribute represents a local variable table attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTableAttribute extends Attribute
+{
+ public int u2localVariableTableLength;
+ public LocalVariableInfo[] localVariableTable;
+
+
+ /**
+ * Creates an uninitialized LocalVariableTableAttribute.
+ */
+ public LocalVariableTableAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LocalVariableTableAttribute.
+ */
+ public LocalVariableTableAttribute(int u2attributeNameIndex,
+ int u2localVariableTableLength,
+ LocalVariableInfo[] localVariableTable)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2localVariableTableLength = u2localVariableTableLength;
+ this.localVariableTable = localVariableTable;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitLocalVariableTableAttribute(clazz, method, codeAttribute, this);
+ }
+
+
+ /**
+ * Applies the given visitor to all local variables.
+ */
+ public void localVariablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfoVisitor localVariableInfoVisitor)
+ {
+ for (int index = 0; index < u2localVariableTableLength; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of LocalVariableInfo.
+ localVariableInfoVisitor.visitLocalVariableInfo(clazz, method, codeAttribute, localVariableTable[index]);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTypeInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTypeInfo.java
new file mode 100644
index 0000000000..918d0991bb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTypeInfo.java
@@ -0,0 +1,143 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * Representation of an Local Variable table entry.
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTypeInfo implements VisitorAccepter, Comparable
+{
+ public int u2startPC;
+ public int u2length;
+ public int u2nameIndex;
+ public int u2signatureIndex;
+ public int u2index;
+
+ /**
+ * An extra field pointing to the Clazz objects referenced in the
+ * type string. This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ * References to primitive types are ignored.
+ */
+ public Clazz[] referencedClasses;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized LocalVariableTypeInfo.
+ */
+ public LocalVariableTypeInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LocalVariableTypeInfo.
+ */
+ public LocalVariableTypeInfo(int u2startPC,
+ int u2length,
+ int u2nameIndex,
+ int u2signatureIndex,
+ int u2index)
+ {
+ this.u2startPC = u2startPC;
+ this.u2length = u2length;
+ this.u2nameIndex = u2nameIndex;
+ this.u2signatureIndex = u2signatureIndex;
+ this.u2index = u2index;
+ }
+
+
+ /**
+ * Returns the name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getString(u2nameIndex);
+ }
+
+
+ /**
+ * Returns the signature.
+ */
+ public String getSignature(Clazz clazz)
+ {
+ return clazz.getString(u2signatureIndex);
+ }
+
+
+ /**
+ * Applies the given visitor to all referenced classes.
+ */
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ Clazz referencedClass = referencedClasses[index];
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+ }
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+
+
+ // Implementations for Comparable.
+
+ public int compareTo(Object object)
+ {
+ LocalVariableTypeInfo other = (LocalVariableTypeInfo)object;
+
+ return
+ this.u2startPC < other.u2startPC ? -1 : this.u2startPC > other.u2startPC ? 1 :
+ this.u2length < other.u2length ? -1 : this.u2length > other.u2length ? 1 :
+ this.u2index < other.u2index ? -1 : this.u2index > other.u2index ? 1 :
+ this.u2signatureIndex < other.u2signatureIndex ? -1 : this.u2signatureIndex > other.u2signatureIndex ? 1 :
+ this.u2nameIndex < other.u2nameIndex ? -1 : this.u2nameIndex > other.u2nameIndex ? 1 :
+ 0;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
new file mode 100644
index 0000000000..1c644347aa
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
@@ -0,0 +1,79 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+
+/**
+ * This Attribute represents a local variable table type attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTypeTableAttribute extends Attribute
+{
+ public int u2localVariableTypeTableLength;
+ public LocalVariableTypeInfo[] localVariableTypeTable;
+
+
+ /**
+ * Creates an uninitialized LocalVariableTypeTableAttribute.
+ */
+ public LocalVariableTypeTableAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LocalVariableTypeTableAttribute.
+ */
+ public LocalVariableTypeTableAttribute(int u2attributeNameIndex,
+ int u2localVariableTypeTableLength,
+ LocalVariableTypeInfo[] localVariableTypeTable)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2localVariableTypeTableLength = u2localVariableTypeTableLength;
+ this.localVariableTypeTable = localVariableTypeTable;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, this);
+ }
+
+
+ /**
+ * Applies the given visitor to all local variable types.
+ */
+ public void localVariablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfoVisitor localVariableTypeInfoVisitor)
+ {
+ for (int index = 0; index < u2localVariableTypeTableLength; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of LocalVariableTypeInfo.
+ localVariableTypeInfoVisitor.visitLocalVariableTypeInfo(clazz, method, codeAttribute, localVariableTypeTable[index]);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/MethodParametersAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/MethodParametersAttribute.java
new file mode 100644
index 0000000000..30086ae740
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/MethodParametersAttribute.java
@@ -0,0 +1,80 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+
+/**
+ * This Attribute represents a method parameters attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodParametersAttribute extends Attribute
+{
+ public int u1parametersCount;
+ public ParameterInfo[] parameters;
+
+
+ /**
+ * Creates an uninitialized MethodParametersAttribute.
+ */
+ public MethodParametersAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized MethodParametersAttribute.
+ */
+ public MethodParametersAttribute(int u2attributeNameIndex,
+ int u1parametersCount,
+ ParameterInfo[] parameters)
+ {
+ super(u2attributeNameIndex);
+
+ this.u1parametersCount = u1parametersCount;
+ this.parameters = parameters;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitMethodParametersAttribute(clazz, method, this);
+ }
+
+
+ /**
+ * Applies the given visitor to all parameters.
+ */
+ public void parametersAccept(Clazz clazz, Method method, ParameterInfoVisitor parameterInfoVisitor)
+ {
+ // Loop over all parameters.
+ for (int index = 0; index < u1parametersCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of ParameterInfo.
+ parameterInfoVisitor.visitParameterInfo(clazz, method, index, parameters[index]);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ParameterInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ParameterInfo.java
new file mode 100644
index 0000000000..e0a8f32b54
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/ParameterInfo.java
@@ -0,0 +1,81 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+
+/**
+ * Representation of a parameter, as defined in a method parameters
+ * attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class ParameterInfo implements VisitorAccepter
+{
+ public int u2nameIndex;
+ public int u2accessFlags;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized ParameterInfo.
+ */
+ public ParameterInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized ParameterInfo.
+ */
+ public ParameterInfo(int u2nameIndex,
+ int u2accessFlags)
+ {
+ this.u2nameIndex = u2nameIndex;
+ this.u2accessFlags = u2accessFlags;
+ }
+
+
+ /**
+ * Returns the parameter name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getString(u2nameIndex);
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SignatureAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SignatureAttribute.java
new file mode 100644
index 0000000000..943056ff98
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SignatureAttribute.java
@@ -0,0 +1,111 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This Attribute represents a signature attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class SignatureAttribute extends Attribute
+{
+ public int u2signatureIndex;
+
+ /**
+ * An extra field containing all the classes referenced in the
+ * signature string. This field is filled out by the {@link
+ * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}.
+ * The size of the array is the number of classes in the signature.
+ * Primitive types and arrays of primitive types are ignored.
+ * Unknown classes are represented as null values.
+ */
+ public Clazz[] referencedClasses;
+
+
+ /**
+ * Creates an uninitialized SignatureAttribute.
+ */
+ public SignatureAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized SignatureAttribute.
+ */
+ public SignatureAttribute(int u2attributeNameIndex,
+ int u2signatureIndex)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2signatureIndex = u2signatureIndex;
+ }
+
+
+ /**
+ * Returns the signature.
+ */
+ public String getSignature(Clazz clazz)
+ {
+ return clazz.getString(u2signatureIndex);
+ }
+
+
+ /**
+ * Lets the Clazz objects referenced in the signature string accept the
+ * given visitor.
+ */
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ if (referencedClasses[index] != null)
+ {
+ referencedClasses[index].accept(classVisitor);
+ }
+ }
+ }
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, this);
+ }
+
+ public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, field, this);
+ }
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, method, this);
+ }
+ }
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SourceDirAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SourceDirAttribute.java
new file mode 100644
index 0000000000..10328cf92e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SourceDirAttribute.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a source directory attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class SourceDirAttribute extends Attribute
+{
+ public int u2sourceDirIndex;
+
+
+ /**
+ * Creates an uninitialized SourceDirAttribute.
+ */
+ public SourceDirAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized SourceDirAttribute.
+ */
+ public SourceDirAttribute(int u2attributeNameIndex,
+ int u2sourceDirIndex)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2sourceDirIndex = u2sourceDirIndex;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitSourceDirAttribute(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SourceFileAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SourceFileAttribute.java
new file mode 100644
index 0000000000..86535b4b30
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SourceFileAttribute.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a source file attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class SourceFileAttribute extends Attribute
+{
+ public int u2sourceFileIndex;
+
+
+ /**
+ * Creates an uninitialized SourceFileAttribute.
+ */
+ public SourceFileAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized SourceFileAttribute.
+ */
+ public SourceFileAttribute(int u2attributeNameIndex,
+ int u2sourceFileIndex)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2sourceFileIndex = u2sourceFileIndex;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitSourceFileAttribute(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SyntheticAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SyntheticAttribute.java
new file mode 100644
index 0000000000..b3120db198
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/SyntheticAttribute.java
@@ -0,0 +1,66 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a synthetic attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class SyntheticAttribute extends Attribute
+{
+ /**
+ * Creates an uninitialized SyntheticAttribute.
+ */
+ public SyntheticAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized SyntheticAttribute.
+ */
+ public SyntheticAttribute(int u2attributeNameIndex)
+ {
+ super(u2attributeNameIndex);
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, this);
+ }
+
+ public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, field, this);
+ }
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, method, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/UnknownAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/UnknownAttribute.java
new file mode 100644
index 0000000000..6654bf6f43
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/UnknownAttribute.java
@@ -0,0 +1,84 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute;
+
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents an unknown attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class UnknownAttribute extends Attribute
+{
+ public final int u4attributeLength;
+ public byte[] info;
+
+
+ /**
+ * Creates an uninitialized UnknownAttribute with the specified name and
+ * length.
+ */
+ public UnknownAttribute(int u2attributeNameIndex,
+ int attributeLength)
+ {
+ this(u2attributeNameIndex, attributeLength, null);
+ }
+
+
+ /**
+ * Creates an initialized UnknownAttribute.
+ */
+ public UnknownAttribute(int u2attributeNameIndex,
+ int u4attributeLength,
+ byte[] info)
+ {
+ super(u2attributeNameIndex);
+
+ this.u4attributeLength = u4attributeLength;
+ this.info = info;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitUnknownAttribute(clazz, this);
+ }
+
+ public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitUnknownAttribute(clazz, this);
+ }
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitUnknownAttribute(clazz, this);
+ }
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitUnknownAttribute(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/Annotation.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/Annotation.java
new file mode 100644
index 0000000000..1b02799e8b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/Annotation.java
@@ -0,0 +1,143 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * Representation of an annotation.
+ *
+ * @author Eric Lafortune
+ */
+public class Annotation implements VisitorAccepter
+{
+ public int u2typeIndex;
+ public int u2elementValuesCount;
+ public ElementValue[] elementValues;
+
+ /**
+ * An extra field pointing to the Clazz objects referenced in the
+ * type string. This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ * References to primitive types are ignored.
+ */
+ public Clazz[] referencedClasses;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized Annotation.
+ */
+ public Annotation()
+ {
+ }
+
+
+ /**
+ * Creates an initialized Annotation.
+ */
+ public Annotation(int u2typeIndex,
+ int u2elementValuesCount,
+ ElementValue[] elementValues)
+ {
+ this.u2typeIndex = u2typeIndex;
+ this.u2elementValuesCount = u2elementValuesCount;
+ this.elementValues = elementValues;
+ }
+
+
+ /**
+ * Returns the type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getString(u2typeIndex);
+ }
+
+
+
+ /**
+ * Applies the given visitor to the first referenced class. This is the
+ * main annotation class.
+ */
+ public void referencedClassAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ Clazz referencedClass = referencedClasses[0];
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to all referenced classes.
+ */
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ Clazz referencedClass = referencedClasses[index];
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to all element value pairs.
+ */
+ public void elementValuesAccept(Clazz clazz, ElementValueVisitor elementValueVisitor)
+ {
+ for (int index = 0; index < u2elementValuesCount; index++)
+ {
+ elementValues[index].accept(clazz, this, elementValueVisitor);
+ }
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java
new file mode 100644
index 0000000000..85fc79250e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java
@@ -0,0 +1,73 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents an annotation default attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class AnnotationDefaultAttribute extends Attribute
+{
+ public ElementValue defaultValue;
+
+
+ /**
+ * Creates an uninitialized AnnotationDefaultAttribute.
+ */
+ public AnnotationDefaultAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized AnnotationDefaultAttribute.
+ */
+ public AnnotationDefaultAttribute(int u2attributeNameIndex,
+ ElementValue defaultValue)
+ {
+ super(u2attributeNameIndex);
+
+ this.defaultValue = defaultValue;
+ }
+
+
+ /**
+ * Applies the given visitor to the default element value.
+ */
+ public void defaultValueAccept(Clazz clazz, ElementValueVisitor elementValueVisitor)
+ {
+ defaultValue.accept(clazz, null, elementValueVisitor);
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitAnnotationDefaultAttribute(clazz, method, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java
new file mode 100644
index 0000000000..b957f82f55
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java
@@ -0,0 +1,76 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+
+/**
+ * This ElementValue represents an annotation element value.
+ *
+ * @author Eric Lafortune
+ */
+public class AnnotationElementValue extends ElementValue
+{
+ public Annotation annotationValue;
+
+
+ /**
+ * Creates an uninitialized AnnotationElementValue.
+ */
+ public AnnotationElementValue()
+ {
+ }
+
+
+ /**
+ * Creates an initialized AnnotationElementValue.
+ */
+ public AnnotationElementValue(int u2elementNameIndex,
+ Annotation annotationValue)
+ {
+ super(u2elementNameIndex);
+
+ this.annotationValue = annotationValue;
+ }
+
+
+ /**
+ * Applies the given visitor to the annotation.
+ */
+ public void annotationAccept(Clazz clazz, AnnotationVisitor annotationVisitor)
+ {
+ annotationVisitor.visitAnnotation(clazz, annotationValue);
+ }
+
+
+ // Implementations for ElementValue.
+
+ public char getTag()
+ {
+ return ClassConstants.ELEMENT_VALUE_ANNOTATION;
+ }
+
+ public void accept(Clazz clazz, Annotation annotation, ElementValueVisitor elementValueVisitor)
+ {
+ elementValueVisitor.visitAnnotationElementValue(clazz, annotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java
new file mode 100644
index 0000000000..167710e01f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java
@@ -0,0 +1,114 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.visitor.AnnotationVisitor;
+
+/**
+ * This Attribute represents an annotations attribute.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class AnnotationsAttribute extends Attribute
+{
+ public int u2annotationsCount;
+ public Annotation[] annotations;
+
+
+ /**
+ * Creates an uninitialized AnnotationsAttribute.
+ */
+ protected AnnotationsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized AnnotationsAttribute.
+ */
+ protected AnnotationsAttribute(int u2attributeNameIndex,
+ int u2annotationsCount,
+ Annotation[] annotations)
+ {
+ super(u2attributeNameIndex);
+
+ this.u2annotationsCount = u2annotationsCount;
+ this.annotations = annotations;
+ }
+
+
+ /**
+ * Applies the given visitor to all class annotations.
+ */
+ public void annotationsAccept(Clazz clazz, AnnotationVisitor annotationVisitor)
+ {
+ for (int index = 0; index < u2annotationsCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of Annotation.
+ annotationVisitor.visitAnnotation(clazz, annotations[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to all field annotations.
+ */
+ public void annotationsAccept(Clazz clazz, Field field, AnnotationVisitor annotationVisitor)
+ {
+ for (int index = 0; index < u2annotationsCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of Annotation.
+ annotationVisitor.visitAnnotation(clazz, field, annotations[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to all method annotations.
+ */
+ public void annotationsAccept(Clazz clazz, Method method, AnnotationVisitor annotationVisitor)
+ {
+ for (int index = 0; index < u2annotationsCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of Annotation.
+ annotationVisitor.visitAnnotation(clazz, method, annotations[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to all code attribute annotations.
+ */
+ public void annotationsAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, AnnotationVisitor annotationVisitor)
+ {
+ for (int index = 0; index < u2annotationsCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of Annotation.
+ annotationVisitor.visitAnnotation(clazz, method, codeAttribute, annotations[index]);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ArrayElementValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ArrayElementValue.java
new file mode 100644
index 0000000000..06c84177ea
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ArrayElementValue.java
@@ -0,0 +1,82 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+
+/**
+ * This ElementValue represents an array element value.
+ *
+ * @author Eric Lafortune
+ */
+public class ArrayElementValue extends ElementValue
+{
+ public int u2elementValuesCount;
+ public ElementValue[] elementValues;
+
+
+ /**
+ * Creates an uninitialized ArrayElementValue.
+ */
+ public ArrayElementValue()
+ {
+ }
+
+
+ /**
+ * Creates an initialized ArrayElementValue.
+ */
+ public ArrayElementValue(int u2elementNameIndex,
+ int u2elementValuesCount,
+ ElementValue[] elementValues)
+ {
+ super(u2elementNameIndex);
+
+ this.u2elementValuesCount = u2elementValuesCount;
+ this.elementValues = elementValues;
+ }
+
+
+ // Implementations for ElementValue.
+
+ public char getTag()
+ {
+ return ClassConstants.ELEMENT_VALUE_ARRAY;
+ }
+
+ public void accept(Clazz clazz, Annotation annotation, ElementValueVisitor elementValueVisitor)
+ {
+ elementValueVisitor.visitArrayElementValue(clazz, annotation, this);
+ }
+
+
+ /**
+ * Applies the given visitor to all nested element values.
+ */
+ public void elementValuesAccept(Clazz clazz, Annotation annotation, ElementValueVisitor elementValueVisitor)
+ {
+ for (int index = 0; index < u2elementValuesCount; index++)
+ {
+ elementValues[index].accept(clazz, annotation, elementValueVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ClassElementValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ClassElementValue.java
new file mode 100644
index 0000000000..945d280a27
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ClassElementValue.java
@@ -0,0 +1,104 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ElementValue represents a class element value.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassElementValue extends ElementValue
+{
+ public int u2classInfoIndex;
+
+ /**
+ * An extra field pointing to the Clazz objects referenced in the
+ * type name string. This field is filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}</code>.
+ * References to primitive types are ignored.
+ */
+ public Clazz[] referencedClasses;
+
+
+ /**
+ * Creates an uninitialized ClassElementValue.
+ */
+ public ClassElementValue()
+ {
+ }
+
+
+ /**
+ * Creates an initialized ClassElementValue.
+ */
+ public ClassElementValue(int u2elementNameIndex,
+ int u2classInfoIndex)
+ {
+ super(u2elementNameIndex);
+
+ this.u2classInfoIndex = u2classInfoIndex;
+ }
+
+
+ /**
+ * Returns the class info name.
+ */
+ public String getClassName(Clazz clazz)
+ {
+ return clazz.getString(u2classInfoIndex);
+ }
+
+
+ /**
+ * Applies the given visitor to all referenced classes.
+ */
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ Clazz referencedClass = referencedClasses[index];
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+ }
+ }
+
+
+ // Implementations for ElementValue.
+
+ public char getTag()
+ {
+ return ClassConstants.ELEMENT_VALUE_CLASS;
+ }
+
+ public void accept(Clazz clazz, Annotation annotation, ElementValueVisitor elementValueVisitor)
+ {
+ elementValueVisitor.visitClassElementValue(clazz, annotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ConstantElementValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ConstantElementValue.java
new file mode 100644
index 0000000000..0e7a4b6ff9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ConstantElementValue.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+
+/**
+ * This ElementValue represents a constant element value.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantElementValue extends ElementValue
+{
+ public final char u1tag;
+ public int u2constantValueIndex;
+
+
+ /**
+ * Creates an uninitialized ConstantElementValue.
+ */
+ public ConstantElementValue(char u1tag)
+ {
+ this.u1tag = u1tag;
+ }
+
+
+ /**
+ * Creates an initialized ConstantElementValue.
+ */
+ public ConstantElementValue(char u1tag,
+ int u2elementNameIndex,
+ int u2constantValueIndex)
+ {
+ super(u2elementNameIndex);
+
+ this.u1tag = u1tag;
+ this.u2constantValueIndex = u2constantValueIndex;
+ }
+
+
+ // Implementations for ElementValue.
+
+ public char getTag()
+ {
+ return u1tag;
+ }
+
+ public void accept(Clazz clazz, Annotation annotation, ElementValueVisitor elementValueVisitor)
+ {
+ elementValueVisitor.visitConstantElementValue(clazz, annotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ElementValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ElementValue.java
new file mode 100644
index 0000000000..8d18c1f5ef
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ElementValue.java
@@ -0,0 +1,126 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This abstract class represents an element value that is attached to an
+ * annotation or an annotation default. Specific types of element values are
+ * subclassed from it.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class ElementValue implements VisitorAccepter
+{
+ /**
+ * An extra field for the optional element name. It is used in element value
+ * pairs of annotations. Otherwise, it is 0.
+ */
+ public int u2elementNameIndex;
+
+ /**
+ * An extra field pointing to the referenced <code>Clazz</code>
+ * object, if applicable. This field is typically filled out by the
+ * <code>{@link proguard.classfile.util.ClassReferenceInitializer}</code>.
+ */
+ public Clazz referencedClass;
+
+ /**
+ * An extra field pointing to the referenced <code>Method</code>
+ * object, if applicable. This field is typically filled out by the
+ * <code>{@link proguard.classfile.util.ClassReferenceInitializer}</code>.
+ */
+ public Method referencedMethod;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Creates an uninitialized ElementValue.
+ */
+ protected ElementValue()
+ {
+ }
+
+
+ /**
+ * Creates an initialized ElementValue.
+ */
+ protected ElementValue(int u2elementNameIndex)
+ {
+ this.u2elementNameIndex = u2elementNameIndex;
+ }
+
+
+ /**
+ * Returns the element name.
+ */
+ public String getMethodName(Clazz clazz)
+ {
+ return clazz.getString(u2elementNameIndex);
+ }
+
+
+ // Abstract methods to be implemented by extensions.
+
+ /**
+ * Returns the tag of this element value.
+ */
+ public abstract char getTag();
+
+
+ /**
+ * Accepts the given visitor.
+ */
+ public abstract void accept(Clazz clazz, Annotation annotation, ElementValueVisitor elementValueVisitor);
+
+
+
+ /**
+ * Applies the given visitor to the referenced method.
+ */
+ public void referencedMethodAccept(MemberVisitor memberVisitor)
+ {
+ if (referencedMethod != null)
+ {
+ referencedMethod.accept(referencedClass, memberVisitor);
+ }
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java
new file mode 100644
index 0000000000..8a82cd79a6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java
@@ -0,0 +1,138 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ElementValue represents an enumeration constant element value.
+ *
+ * @author Eric Lafortune
+ */
+public class EnumConstantElementValue extends ElementValue
+{
+ public int u2typeNameIndex;
+ public int u2constantNameIndex;
+
+ /**
+ * An extra field pointing to the Clazz objects referenced in the
+ * type name string. This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ * References to primitive types are ignored.
+ */
+ public Clazz[] referencedClasses;
+
+ /**
+ * An extra field optionally pointing to the referenced enum Field object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ */
+ public Field referencedField;
+
+
+ /**
+ * Creates an uninitialized EnumConstantElementValue.
+ */
+ public EnumConstantElementValue()
+ {
+ }
+
+
+ /**
+ * Creates an initialized EnumConstantElementValue.
+ */
+ public EnumConstantElementValue(int u2elementNameIndex,
+ int u2typeNameIndex,
+ int u2constantNameIndex)
+ {
+ super(u2elementNameIndex);
+
+ this.u2typeNameIndex = u2typeNameIndex;
+ this.u2constantNameIndex = u2constantNameIndex;
+ }
+
+
+ /**
+ * Returns the enumeration type name.
+ */
+ public String getTypeName(Clazz clazz)
+ {
+ return clazz.getString(u2typeNameIndex);
+ }
+
+
+ /**
+ * Returns the constant name.
+ */
+ public String getConstantName(Clazz clazz)
+ {
+ return clazz.getString(u2constantNameIndex);
+ }
+
+
+ /**
+ * Applies the given visitor to all referenced classes.
+ */
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ Clazz referencedClass = referencedClasses[index];
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to the referenced field.
+ */
+ public void referencedFieldAccept(MemberVisitor memberVisitor)
+ {
+ if (referencedField != null)
+ {
+ referencedField.accept(referencedClasses[0],
+ memberVisitor);
+ }
+ }
+
+
+ // Implementations for ElementValue.
+
+ public char getTag()
+ {
+ return ClassConstants.ELEMENT_VALUE_ENUM_CONSTANT;
+ }
+
+ public void accept(Clazz clazz, Annotation annotation, ElementValueVisitor elementValueVisitor)
+ {
+ elementValueVisitor.visitEnumConstantElementValue(clazz, annotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java
new file mode 100644
index 0000000000..666762f4a6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java
@@ -0,0 +1,83 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.attribute.annotation.visitor.AnnotationVisitor;
+
+/**
+ * This Attribute represents a parameter annotations attribute.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class ParameterAnnotationsAttribute extends Attribute
+{
+ public int u1parametersCount;
+ public int[] u2parameterAnnotationsCount;
+ public Annotation[][] parameterAnnotations;
+
+
+ /**
+ * Creates an uninitialized ParameterAnnotationsAttribute.
+ */
+ protected ParameterAnnotationsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized ParameterAnnotationsAttribute.
+ */
+ protected ParameterAnnotationsAttribute(int u2attributeNameIndex,
+ int u1parametersCount,
+ int[] u2parameterAnnotationsCount,
+ Annotation[][] parameterAnnotations)
+ {
+ super(u2attributeNameIndex);
+
+ this.u1parametersCount = u1parametersCount;
+ this.u2parameterAnnotationsCount = u2parameterAnnotationsCount;
+ this.parameterAnnotations = parameterAnnotations;
+ }
+
+
+ /**
+ * Applies the given visitor to all annotations.
+ */
+ public void annotationsAccept(Clazz clazz, Method method, AnnotationVisitor annotationVisitor)
+ {
+ // Loop over all parameters.
+ for (int parameterIndex = 0; parameterIndex < u1parametersCount; parameterIndex++)
+ {
+ int annotationsCount = u2parameterAnnotationsCount[parameterIndex];
+ Annotation[] annotations = parameterAnnotations[parameterIndex];
+
+ // Loop over all parameter annotations.
+ for (int index = 0; index < annotationsCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of Annotation.
+ annotationVisitor.visitAnnotation(clazz, method, parameterIndex, annotations[index]);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java
new file mode 100644
index 0000000000..6e2a416d88
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java
@@ -0,0 +1,70 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a runtime invisible annotations attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class RuntimeInvisibleAnnotationsAttribute extends AnnotationsAttribute
+{
+ /**
+ * Creates an uninitialized RuntimeInvisibleAnnotationsAttribute.
+ */
+ public RuntimeInvisibleAnnotationsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized RuntimeInvisibleAnnotationsAttribute.
+ */
+ public RuntimeInvisibleAnnotationsAttribute(int u2attributeNameIndex,
+ int u2annotationsCount,
+ Annotation[] annotations)
+ {
+ super(u2attributeNameIndex, u2annotationsCount, annotations);
+ }
+
+
+// Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, this);
+ }
+
+
+ public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, field, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, method, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java
new file mode 100644
index 0000000000..b9772bd225
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a runtime invisible parameter annotations attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class RuntimeInvisibleParameterAnnotationsAttribute extends ParameterAnnotationsAttribute
+{
+ /**
+ * Creates an uninitialized RuntimeInvisibleParameterAnnotationsAttribute.
+ */
+ public RuntimeInvisibleParameterAnnotationsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized RuntimeInvisibleParameterAnnotationsAttribute.
+ */
+ public RuntimeInvisibleParameterAnnotationsAttribute(int u2attributeNameIndex,
+ int u1parametersCount,
+ int[] u2parameterAnnotationsCount,
+ Annotation[][] parameterAnnotations)
+ {
+ super(u2attributeNameIndex,
+ u1parametersCount,
+ u2parameterAnnotationsCount,
+ parameterAnnotations);
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeInvisibleParameterAnnotationsAttribute(clazz, method, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleTypeAnnotationsAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleTypeAnnotationsAttribute.java
new file mode 100644
index 0000000000..6addf96dc7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeInvisibleTypeAnnotationsAttribute.java
@@ -0,0 +1,77 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a runtime invisible type annotations attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class RuntimeInvisibleTypeAnnotationsAttribute extends TypeAnnotationsAttribute
+{
+ /**
+ * Creates an uninitialized RuntimeInvisibleTypeAnnotationsAttribute.
+ */
+ public RuntimeInvisibleTypeAnnotationsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized RuntimeInvisibleTypeAnnotationsAttribute.
+ */
+ public RuntimeInvisibleTypeAnnotationsAttribute(int u2attributeNameIndex,
+ int u2annotationsCount,
+ TypeAnnotation[] annotations)
+ {
+ super(u2attributeNameIndex, u2annotationsCount, annotations);
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, this);
+ }
+
+
+ public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java
new file mode 100644
index 0000000000..7b5ff00304
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java
@@ -0,0 +1,70 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a runtime visible annotations attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class RuntimeVisibleAnnotationsAttribute extends AnnotationsAttribute
+{
+ /**
+ * Creates an uninitialized RuntimeVisibleAnnotationsAttribute.
+ */
+ public RuntimeVisibleAnnotationsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized RuntimeVisibleAnnotationsAttribute.
+ */
+ public RuntimeVisibleAnnotationsAttribute(int u2attributeNameIndex,
+ int u2annotationsCount,
+ Annotation[] annotations)
+ {
+ super(u2attributeNameIndex, u2annotationsCount, annotations);
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, this);
+ }
+
+
+ public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, field, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, method, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java
new file mode 100644
index 0000000000..a1a2e1abaf
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a runtime visible parameter annotations attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class RuntimeVisibleParameterAnnotationsAttribute extends ParameterAnnotationsAttribute
+{
+ /**
+ * Creates an uninitialized RuntimeVisibleParameterAnnotationsAttribute.
+ */
+ public RuntimeVisibleParameterAnnotationsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized RuntimeVisibleParameterAnnotationsAttribute.
+ */
+ public RuntimeVisibleParameterAnnotationsAttribute(int u2attributeNameIndex,
+ int u1parametersCount,
+ int[] u2parameterAnnotationsCount,
+ Annotation[][] parameterAnnotations)
+ {
+ super(u2attributeNameIndex,
+ u1parametersCount,
+ u2parameterAnnotationsCount,
+ parameterAnnotations);
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeVisibleParameterAnnotationsAttribute(clazz, method, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleTypeAnnotationsAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleTypeAnnotationsAttribute.java
new file mode 100644
index 0000000000..2652a1f6d4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/RuntimeVisibleTypeAnnotationsAttribute.java
@@ -0,0 +1,77 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a runtime visible type annotations attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class RuntimeVisibleTypeAnnotationsAttribute extends TypeAnnotationsAttribute
+{
+ /**
+ * Creates an uninitialized RuntimeVisibleTypeAnnotationsAttribute.
+ */
+ public RuntimeVisibleTypeAnnotationsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized RuntimeVisibleTypeAnnotationsAttribute.
+ */
+ public RuntimeVisibleTypeAnnotationsAttribute(int u2attributeNameIndex,
+ int u2annotationsCount,
+ TypeAnnotation[] annotations)
+ {
+ super(u2attributeNameIndex, u2annotationsCount, annotations);
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, this);
+ }
+
+
+ public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypeAnnotation.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypeAnnotation.java
new file mode 100644
index 0000000000..1246dfa63b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypeAnnotation.java
@@ -0,0 +1,162 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.target.TargetInfo;
+import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor;
+import proguard.classfile.attribute.annotation.visitor.*;
+
+/**
+ * Representation of a type annotation.
+ *
+ * @author Eric Lafortune
+ */
+public class TypeAnnotation extends Annotation
+{
+ public TargetInfo targetInfo;
+ public TypePathInfo[] typePath;
+
+
+ /**
+ * Creates an uninitialized TypeAnnotation.
+ */
+ public TypeAnnotation()
+ {
+ }
+
+
+ /**
+ * Creates an initialized TypeAnnotation.
+ */
+ public TypeAnnotation(int u2typeIndex,
+ int u2elementValuesCount,
+ ElementValue[] elementValues,
+ TargetInfo targetInfo,
+ TypePathInfo[] typePath)
+ {
+ super(u2typeIndex, u2elementValuesCount, elementValues);
+
+ this.targetInfo = targetInfo;
+ this.typePath = typePath;
+ }
+
+
+ /**
+ * Applies the given visitor to the target info.
+ */
+ public void targetInfoAccept(Clazz clazz, TargetInfoVisitor targetInfoVisitor)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of TypePathInfo.
+ targetInfo.accept(clazz, this, targetInfoVisitor);
+ }
+
+
+ /**
+ * Applies the given visitor to the target info.
+ */
+ public void targetInfoAccept(Clazz clazz, Field field, TargetInfoVisitor targetInfoVisitor)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of TypePathInfo.
+ targetInfo.accept(clazz, field, this, targetInfoVisitor);
+ }
+
+
+ /**
+ * Applies the given visitor to the target info.
+ */
+ public void targetInfoAccept(Clazz clazz, Method method, TargetInfoVisitor targetInfoVisitor)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of TypePathInfo.
+ targetInfo.accept(clazz, method, this, targetInfoVisitor);
+ }
+
+
+ /**
+ * Applies the given visitor to the target info.
+ */
+ public void targetInfoAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, TargetInfoVisitor targetInfoVisitor)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of TypePathInfo.
+ targetInfo.accept(clazz, method, codeAttribute, this, targetInfoVisitor);
+ }
+
+
+ /**
+ * Applies the given visitor to all type path elements.
+ */
+ public void typePathInfosAccept(Clazz clazz, TypePathInfoVisitor typePathVisitor)
+ {
+ for (int index = 0; index < typePath.length; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of TypePathInfo.
+ typePathVisitor.visitTypePathInfo(clazz, this, typePath[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to all type path elements.
+ */
+ public void typePathInfosAccept(Clazz clazz, Field field, TypePathInfoVisitor typePathVisitor)
+ {
+ for (int index = 0; index < typePath.length; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of TypePathInfo.
+ typePathVisitor.visitTypePathInfo(clazz, field, this, typePath[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to all type path elements.
+ */
+ public void typePathInfosAccept(Clazz clazz, Method method, TypePathInfoVisitor typePathVisitor)
+ {
+ for (int index = 0; index < typePath.length; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of TypePathInfo.
+ typePathVisitor.visitTypePathInfo(clazz, method, this, typePath[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to all type path elements.
+ */
+ public void typePathInfosAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypePathInfoVisitor typePathVisitor)
+ {
+ for (int index = 0; index < typePath.length; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of TypePathInfo.
+ typePathVisitor.visitTypePathInfo(clazz, method, codeAttribute, typeAnnotation, typePath[index]);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypeAnnotationsAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypeAnnotationsAttribute.java
new file mode 100644
index 0000000000..644d04548b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypeAnnotationsAttribute.java
@@ -0,0 +1,98 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+
+/**
+ * This Attribute represents a type annotations attribute.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class TypeAnnotationsAttribute extends AnnotationsAttribute
+{
+ /**
+ * Creates an uninitialized TypeAnnotationsAttribute.
+ */
+ protected TypeAnnotationsAttribute()
+ {
+ }
+
+
+ /**
+ * Creates an initialized TypeAnnotationsAttribute.
+ */
+ protected TypeAnnotationsAttribute(int u2attributeNameIndex,
+ int u2annotationsCount,
+ TypeAnnotation[] annotations)
+ {
+ super(u2attributeNameIndex, u2annotationsCount, annotations);
+ }
+
+
+ /**
+ * Applies the given visitor to all class annotations.
+ */
+ public void typeAnnotationsAccept(Clazz clazz, TypeAnnotationVisitor typeAnnotationVisitor)
+ {
+ TypeAnnotation[] annotations = (TypeAnnotation[])this.annotations;
+
+ for (int index = 0; index < u2annotationsCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of Annotation.
+ typeAnnotationVisitor.visitTypeAnnotation(clazz, annotations[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to all field annotations.
+ */
+ public void typeAnnotationsAccept(Clazz clazz, Field field, TypeAnnotationVisitor typeAnnotationVisitor)
+ {
+ TypeAnnotation[] annotations = (TypeAnnotation[])this.annotations;
+
+ for (int index = 0; index < u2annotationsCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of Annotation.
+ typeAnnotationVisitor.visitTypeAnnotation(clazz, field, annotations[index]);
+ }
+ }
+
+
+ /**
+ * Applies the given visitor to all method annotations.
+ */
+ public void typeAnnotationsAccept(Clazz clazz, Method method, TypeAnnotationVisitor typeAnnotationVisitor)
+ {
+ TypeAnnotation[] annotations = (TypeAnnotation[])this.annotations;
+
+ for (int index = 0; index < u2annotationsCount; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of Annotation.
+ typeAnnotationVisitor.visitTypeAnnotation(clazz, method, annotations[index]);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypePathInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypePathInfo.java
new file mode 100644
index 0000000000..1aa91f2666
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/TypePathInfo.java
@@ -0,0 +1,50 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation;
+
+/**
+ * Representation of a path element in a type annotation.
+ *
+ * @author Eric Lafortune
+ */
+public class TypePathInfo
+{
+ public int u1typePathKind;
+ public int u1typeArgumentIndex;
+
+
+ /**
+ * Creates an uninitialized TypePathInfo.
+ */
+ public TypePathInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized TypePathInfo.
+ */
+ public TypePathInfo(int u1typePathKind, int u1typeArgumentIndex)
+ {
+ this.u1typePathKind = u1typePathKind;
+ this.u1typeArgumentIndex = u1typeArgumentIndex;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/package.html
new file mode 100644
index 0000000000..6aacff3e2f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/package.html
@@ -0,0 +1,4 @@
+<body>
+This package contains classes to represent the annotation attributes inside
+class files.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/CatchTargetInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/CatchTargetInfo.java
new file mode 100644
index 0000000000..81c709d6bd
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/CatchTargetInfo.java
@@ -0,0 +1,82 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor;
+
+/**
+ * Representation of a 'catch' annotation target.
+ *
+ * @author Eric Lafortune
+ */
+public class CatchTargetInfo extends TargetInfo
+{
+ public int u2exceptionTableIndex;
+
+
+ /**
+ * Creates an uninitialized CatchTargetInfo.
+ */
+ public CatchTargetInfo()
+ {
+ }
+
+
+ /**
+ * Creates a partially initialized CatchTargetInfo.
+ */
+ public CatchTargetInfo(byte u1targetType)
+ {
+ super(u1targetType);
+ }
+
+
+ /**
+ * Creates an initialized CatchTargetInfo.
+ */
+ protected CatchTargetInfo(byte u1targetType,
+ int u2exceptionTableIndex)
+ {
+ super(u1targetType);
+
+ this.u2exceptionTableIndex = u2exceptionTableIndex;
+ }
+
+
+ // Implementations for TargetInfo.
+
+ /**
+ * Lets the visitor visit, with Method and CodeAttribute null.
+ */
+ public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitCatchTargetInfo(clazz, null, null, typeAnnotation, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitCatchTargetInfo(clazz, method, codeAttribute, typeAnnotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/EmptyTargetInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/EmptyTargetInfo.java
new file mode 100644
index 0000000000..6b6a9c9b98
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/EmptyTargetInfo.java
@@ -0,0 +1,72 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor;
+
+/**
+ * Representation of an empty annotation target.
+ *
+ * @author Eric Lafortune
+ */
+public class EmptyTargetInfo extends TargetInfo
+{
+ /**
+ * Creates an uninitialized EmptyTargetInfo.
+ */
+ public EmptyTargetInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized EmptyTargetInfo.
+ */
+ public EmptyTargetInfo(byte u1targetType)
+ {
+ super(u1targetType);
+ }
+
+
+ // Implementations for TargetInfo.
+
+ /**
+ * Lets the visitor visit, with Field null.
+ */
+ public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitEmptyTargetInfo(clazz, (Field)null, typeAnnotation, this);
+ }
+
+
+ public void accept(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitEmptyTargetInfo(clazz, field, typeAnnotation, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitEmptyTargetInfo(clazz, method, typeAnnotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/FormalParameterTargetInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/FormalParameterTargetInfo.java
new file mode 100644
index 0000000000..07906f5a2a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/FormalParameterTargetInfo.java
@@ -0,0 +1,81 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor;
+
+/**
+ * Representation of a formal parameter annotation target.
+ *
+ * @author Eric Lafortune
+ */
+public class FormalParameterTargetInfo extends TargetInfo
+{
+ public int u1formalParameterIndex;
+
+
+ /**
+ * Creates an uninitialized FormalParameterTargetInfo.
+ */
+ public FormalParameterTargetInfo()
+ {
+ }
+
+
+ /**
+ * Creates a partially initialized FormalParameterTargetInfo.
+ */
+ public FormalParameterTargetInfo(byte u1targetType)
+ {
+ super(u1targetType);
+ }
+
+
+ /**
+ * Creates an initialized FormalParameterTargetInfo.
+ */
+ public FormalParameterTargetInfo(byte u1targetType,
+ int u1formalParameterIndex)
+ {
+ super(u1targetType);
+
+ this.u1formalParameterIndex = u1formalParameterIndex;
+ }
+
+
+ // Implementations for TargetInfo.
+
+ /**
+ * Lets the visitor visit, with Method null.
+ */
+ public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitFormalParameterTargetInfo(clazz, null, typeAnnotation, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitFormalParameterTargetInfo(clazz, method, typeAnnotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetElement.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetElement.java
new file mode 100644
index 0000000000..85e3a689a6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetElement.java
@@ -0,0 +1,53 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+/**
+ * Representation of an local variable target table entry.
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTargetElement
+{
+ public int u2startPC;
+ public int u2length;
+ public int u2index;
+
+ /**
+ * Creates an uninitialized LocalVariableTargetElement.
+ */
+ public LocalVariableTargetElement()
+ {
+ }
+
+
+ /**
+ * Creates an initialized LocalVariableTargetElement.
+ */
+ public LocalVariableTargetElement(int u2startPC,
+ int u2length,
+ int u2index)
+ {
+ this.u2startPC = u2startPC;
+ this.u2length = u2length;
+ this.u2index = u2index;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetInfo.java
new file mode 100644
index 0000000000..7e532fcd75
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetInfo.java
@@ -0,0 +1,99 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.visitor.*;
+
+/**
+ * Representation of a local variable annotation target.
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTargetInfo extends TargetInfo
+{
+ public int u2tableLength;
+ public LocalVariableTargetElement[] table;
+
+
+ /**
+ * Creates an uninitialized LocalVariableTargetInfo.
+ */
+ public LocalVariableTargetInfo()
+ {
+ }
+
+
+ /**
+ * Creates a partially initialized LocalVariableTargetInfo.
+ */
+ public LocalVariableTargetInfo(byte u1targetType)
+ {
+ super(u1targetType);
+ }
+
+
+ /**
+ * Creates an initialized LocalVariableTargetInfo.
+ */
+ protected LocalVariableTargetInfo(byte u1targetType,
+ int u2tableLength,
+ LocalVariableTargetElement[] table)
+ {
+ super(u1targetType);
+
+ this.u2tableLength = u2tableLength;
+ this.table = table;
+ }
+
+
+ /**
+ * Applies the given visitor to all target elements.
+ */
+ public void targetElementsAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetElementVisitor localVariableTargetElementVisitor)
+ {
+ for (int index = 0; index < u2tableLength; index++)
+ {
+ // We don't need double dispatching here, since there is only one
+ // type of TypePathInfo.
+ localVariableTargetElementVisitor.visitLocalVariableTargetElement(clazz, method, codeAttribute, typeAnnotation, this, table[index]);
+ }
+ }
+
+
+ // Implementations for TargetInfo.
+
+ /**
+ * Lets the visitor visit, with Method and CodeAttribute null.
+ */
+ public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitLocalVariableTargetInfo(clazz, null, null, typeAnnotation, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitLocalVariableTargetInfo(clazz, method, codeAttribute, typeAnnotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/OffsetTargetInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/OffsetTargetInfo.java
new file mode 100644
index 0000000000..6eb7e9807e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/OffsetTargetInfo.java
@@ -0,0 +1,82 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor;
+
+/**
+ * Representation of an offset annotation target.
+ *
+ * @author Eric Lafortune
+ */
+public class OffsetTargetInfo extends TargetInfo
+{
+ public int u2offset;
+
+
+ /**
+ * Creates an uninitialized OffsetTargetInfo.
+ */
+ public OffsetTargetInfo()
+ {
+ }
+
+
+ /**
+ * Creates a partially initialized OffsetTargetInfo.
+ */
+ public OffsetTargetInfo(byte u1targetType)
+ {
+ super(u1targetType);
+ }
+
+
+ /**
+ * Creates an initialized OffsetTargetInfo.
+ */
+ protected OffsetTargetInfo(byte u1targetType,
+ int u2offset)
+ {
+ super(u1targetType);
+
+ this.u2offset = u2offset;
+ }
+
+
+ // Implementations for TargetInfo.
+
+ /**
+ * Lets the visitor visit, with Method and CodeAttribute null.
+ */
+ public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitOffsetTargetInfo(clazz, null, null, typeAnnotation, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitOffsetTargetInfo(clazz, method, codeAttribute, typeAnnotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/SuperTypeTargetInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/SuperTypeTargetInfo.java
new file mode 100644
index 0000000000..6bb82f0137
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/SuperTypeTargetInfo.java
@@ -0,0 +1,72 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor;
+
+/**
+ * Representation of a super type annotation target.
+ *
+ * @author Eric Lafortune
+ */
+public class SuperTypeTargetInfo extends TargetInfo
+{
+ public int u2superTypeIndex;
+
+
+ /**
+ * Creates an uninitialized SuperTypeTargetInfo.
+ */
+ public SuperTypeTargetInfo()
+ {
+ }
+
+
+ /**
+ * Creates a partially initialized SuperTypeTargetInfo.
+ */
+ public SuperTypeTargetInfo(byte u1targetType)
+ {
+ super(u1targetType);
+ }
+
+
+ /**
+ * Creates an initialized SuperTypeTargetInfo.
+ */
+ public SuperTypeTargetInfo(byte u1targetType,
+ int u2superTypeIndex)
+ {
+ super(u1targetType);
+
+ this.u2superTypeIndex = u2superTypeIndex;
+ }
+
+
+ // Implementations for TargetInfo.
+
+ public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitSuperTypeTargetInfo(clazz, typeAnnotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TargetInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TargetInfo.java
new file mode 100644
index 0000000000..138942fc20
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TargetInfo.java
@@ -0,0 +1,97 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor;
+
+/**
+ * Representation of an annotation target.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class TargetInfo
+{
+ public byte u1targetType;
+
+
+ /**
+ * Creates an uninitialized TargetInfo.
+ */
+ protected TargetInfo()
+ {
+ }
+
+
+ /**
+ * Creates an initialized TargetInfo.
+ */
+ protected TargetInfo(byte u1targetType)
+ {
+ this.u1targetType = u1targetType;
+ }
+
+
+ /**
+ * Returns the type of the target.
+ */
+ public byte getTargetType()
+ {
+ return u1targetType;
+ }
+
+
+ // Methods to be implemented by extensions.
+
+ /**
+ * Accepts the given visitor, in the context of a type annotation on a class.
+ */
+ public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ throw new UnsupportedOperationException("Unsupported type annotation [0x"+Integer.toHexString(u1targetType)+"] on a class");
+ }
+
+ /**
+ * Accepts the given visitor, in the context of a type annotation on a field.
+ */
+ public void accept(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ throw new UnsupportedOperationException("Unsupported type annotation [0x"+Integer.toHexString(u1targetType)+"] on a field");
+ }
+
+ /**
+ * Accepts the given visitor, in the context of a type annotation on a method.
+ */
+ public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ throw new UnsupportedOperationException("Unsupported type annotation [0x"+Integer.toHexString(u1targetType)+"] on a method");
+ }
+
+ /**
+ * Accepts the given visitor, in the context of a type annotation code.
+ */
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ throw new UnsupportedOperationException("Unsupported type annotation [0x"+Integer.toHexString(u1targetType)+"] on code");
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/ThrowsTargetInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/ThrowsTargetInfo.java
new file mode 100644
index 0000000000..c42a45b0d8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/ThrowsTargetInfo.java
@@ -0,0 +1,81 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor;
+
+/**
+ * Representation of a 'throws' annotation target.
+ *
+ * @author Eric Lafortune
+ */
+public class ThrowsTargetInfo extends TargetInfo
+{
+ public int u2throwsTypeIndex;
+
+
+ /**
+ * Creates an uninitialized ThrowsTargetInfo.
+ */
+ public ThrowsTargetInfo()
+ {
+ }
+
+
+ /**
+ * Creates a partially initialized ThrowsTargetInfo.
+ */
+ public ThrowsTargetInfo(byte u1targetType)
+ {
+ super(u1targetType);
+ }
+
+
+ /**
+ * Creates an initialized ThrowsTargetInfo.
+ */
+ public ThrowsTargetInfo(byte u1targetType,
+ int u2throwsTypeIndex)
+ {
+ super(u1targetType);
+
+ this.u2throwsTypeIndex = u2throwsTypeIndex;
+ }
+
+
+ // Implementations for TargetInfo.
+
+ /**
+ * Lets the visitor visit, with Method null.
+ */
+ public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitThrowsTargetInfo(clazz, null, typeAnnotation, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitThrowsTargetInfo(clazz, method, typeAnnotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeArgumentTargetInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeArgumentTargetInfo.java
new file mode 100644
index 0000000000..deb6eaabe8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeArgumentTargetInfo.java
@@ -0,0 +1,85 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor;
+
+/**
+ * Representation of an offset annotation target.
+ *
+ * @author Eric Lafortune
+ */
+public class TypeArgumentTargetInfo extends TargetInfo
+{
+ public int u2offset;
+ public int u1typeArgumentIndex;
+
+
+ /**
+ * Creates an uninitialized TypeArgumentTargetInfo.
+ */
+ public TypeArgumentTargetInfo()
+ {
+ }
+
+
+ /**
+ * Creates a partially initialized TypeArgumentTargetInfo.
+ */
+ public TypeArgumentTargetInfo(byte u1targetType)
+ {
+ super(u1targetType);
+ }
+
+
+ /**
+ * Creates an initialized TypeArgumentTargetInfo.
+ */
+ protected TypeArgumentTargetInfo(byte u1targetType,
+ int u2offset,
+ int u1typeArgumentIndex)
+ {
+ super(u1targetType);
+
+ this.u2offset = u2offset;
+ this.u1typeArgumentIndex = u1typeArgumentIndex;
+ }
+
+
+ // Implementations for TargetInfo.
+
+ /**
+ * Lets the visitor visit, with Method and CodeAttribute null.
+ */
+ public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitTypeArgumentTargetInfo(clazz, null, null, typeAnnotation, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitTypeArgumentTargetInfo(clazz, method, codeAttribute, typeAnnotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeParameterBoundTargetInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeParameterBoundTargetInfo.java
new file mode 100644
index 0000000000..6c628adeb0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeParameterBoundTargetInfo.java
@@ -0,0 +1,87 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor;
+
+/**
+ * Representation of a type parameter bound annotation target.
+ *
+ * @author Eric Lafortune
+ */
+public class TypeParameterBoundTargetInfo extends TargetInfo
+{
+ public int u1typeParameterIndex;
+ public int u1boundIndex;
+
+
+ /**
+ * Creates an uninitialized TypeParameterBoundTargetInfo.
+ */
+ public TypeParameterBoundTargetInfo()
+ {
+ }
+
+
+ /**
+ * Creates a partially initialized TypeParameterBoundTargetInfo.
+ */
+ public TypeParameterBoundTargetInfo(byte u1targetType)
+ {
+ super(u1targetType);
+ }
+
+
+ /**
+ * Creates an initialized TypeParameterBoundTargetInfo.
+ */
+ public TypeParameterBoundTargetInfo(byte u1targetType,
+ int u1typeParameterIndex,
+ int u1boundIndex)
+ {
+ super(u1targetType);
+
+ this.u1typeParameterIndex = u1typeParameterIndex;
+ this.u1boundIndex = u1boundIndex;
+ }
+
+
+ // Implementations for TargetInfo.
+
+ public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitTypeParameterBoundTargetInfo(clazz, typeAnnotation, this);
+ }
+
+
+ public void accept(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitTypeParameterBoundTargetInfo(clazz, field, typeAnnotation, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitTypeParameterBoundTargetInfo(clazz, method, typeAnnotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeParameterTargetInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeParameterTargetInfo.java
new file mode 100644
index 0000000000..06f2b57bcf
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/TypeParameterTargetInfo.java
@@ -0,0 +1,79 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor;
+
+/**
+ * Representation of a type parameter annotation target.
+ *
+ * @author Eric Lafortune
+ */
+public class TypeParameterTargetInfo extends TargetInfo
+{
+ public int u1typeParameterIndex;
+
+
+ /**
+ * Creates an uninitialized TypeParameterTargetInfo.
+ */
+ public TypeParameterTargetInfo()
+ {
+ }
+
+
+ /**
+ * Creates a partially initialized TypeParameterTargetInfo.
+ */
+ public TypeParameterTargetInfo(byte u1targetType)
+ {
+ super(u1targetType);
+ }
+
+
+ /**
+ * Creates an initialized TypeParameterTargetInfo.
+ */
+ public TypeParameterTargetInfo(byte u1targetType,
+ int u1typeParameterIndex)
+ {
+ super(u1targetType);
+
+ this.u1typeParameterIndex = u1typeParameterIndex;
+ }
+
+
+ // Implementations for TargetInfo.
+
+ public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitTypeParameterTargetInfo(clazz, typeAnnotation, this);
+ }
+
+
+ public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor)
+ {
+ targetInfoVisitor.visitTypeParameterTargetInfo(clazz, method, typeAnnotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/visitor/LocalVariableTargetElementVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/visitor/LocalVariableTargetElementVisitor.java
new file mode 100644
index 0000000000..659a0ff8b2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/visitor/LocalVariableTargetElementVisitor.java
@@ -0,0 +1,37 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.TypeAnnotation;
+import proguard.classfile.attribute.annotation.target.*;
+
+/**
+ * This interface specifies the methods for a visitor of LocalVariableTargetElement
+ * instances.
+ *
+ * @author Eric Lafortune
+ */
+public interface LocalVariableTargetElementVisitor
+{
+ public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/visitor/TargetInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/visitor/TargetInfoVisitor.java
new file mode 100644
index 0000000000..fef99f172e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/target/visitor/TargetInfoVisitor.java
@@ -0,0 +1,50 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.target.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.target.*;
+
+/**
+ * This interface specifies the methods for a visitor of <code>TargetInfo</code>
+ * objects.
+ *
+ * @author Eric Lafortune
+ */
+public interface TargetInfoVisitor
+{
+ public void visitTypeParameterTargetInfo( Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo);
+ public void visitTypeParameterTargetInfo( Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo);
+ public void visitSuperTypeTargetInfo( Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo);
+ public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo);
+ public void visitTypeParameterBoundTargetInfo(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo);
+ public void visitTypeParameterBoundTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo);
+ public void visitEmptyTargetInfo( Clazz clazz, Field field, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo);
+ public void visitEmptyTargetInfo( Clazz clazz, Method method, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo);
+ public void visitFormalParameterTargetInfo( Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo);
+ public void visitThrowsTargetInfo( Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo);
+ public void visitLocalVariableTargetInfo( Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo);
+ public void visitCatchTargetInfo( Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo);
+ public void visitOffsetTargetInfo( Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo);
+ public void visitTypeArgumentTargetInfo( Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java
new file mode 100644
index 0000000000..cead20c1d8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java
@@ -0,0 +1,161 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given AnnotationVisitor visit all Annotation
+ * objects of the attributes it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllAnnotationVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final AnnotationVisitor annotationVisitor;
+
+
+ /**
+ * Creates a new AllAnnotationVisitor.
+ * @param annotationVisitor the AnnotationVisitor to which visits will be
+ * delegated.
+ */
+ public AllAnnotationVisitor(AnnotationVisitor annotationVisitor)
+ {
+ this.annotationVisitor = annotationVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, annotationVisitor);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, field, annotationVisitor);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, method, annotationVisitor);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, annotationVisitor);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, field, annotationVisitor);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, method, annotationVisitor);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, annotationVisitor);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleTypeAnnotationsAttribute.annotationsAccept(clazz, annotationVisitor);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleTypeAnnotationsAttribute.annotationsAccept(clazz, field, annotationVisitor);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleTypeAnnotationsAttribute.annotationsAccept(clazz, method, annotationVisitor);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleTypeAnnotationsAttribute.annotationsAccept(clazz, method, codeAttribute, annotationVisitor);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleTypeAnnotationsAttribute.annotationsAccept(clazz, annotationVisitor);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleTypeAnnotationsAttribute.annotationsAccept(clazz, field, annotationVisitor);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleTypeAnnotationsAttribute.annotationsAccept(clazz, method, annotationVisitor);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleTypeAnnotationsAttribute.annotationsAccept(clazz, method, codeAttribute, annotationVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java
new file mode 100644
index 0000000000..3e9bf0f811
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java
@@ -0,0 +1,206 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor and AnnotationVisitor lets a given ElementValueVisitor
+ * visit all ElementValue objects of the attributes or annotations that it
+ * visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllElementValueVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor
+{
+ private final boolean deep;
+ private final ElementValueVisitor elementValueVisitor;
+
+
+ /**
+ * Creates a new AllElementValueVisitor.
+ * @param elementValueVisitor the AllElementValueVisitor to which visits
+ * will be delegated.
+ */
+ public AllElementValueVisitor(ElementValueVisitor elementValueVisitor)
+ {
+ this(false, elementValueVisitor);
+ }
+
+
+ /**
+ * Creates a new AllElementValueVisitor.
+ * @param deep specifies whether the element values
+ * further down the hierarchy should be
+ * visited too.
+ * @param elementValueVisitor the AllElementValueVisitor to which visits
+ * will be delegated.
+ */
+ public AllElementValueVisitor(boolean deep,
+ ElementValueVisitor elementValueVisitor)
+ {
+ this.deep = deep;
+ this.elementValueVisitor = elementValueVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, field, this);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, field, this);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Visit the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Visit the default element value.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Field field, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, int parameterIndex, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, Annotation annotation)
+ {
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ elementValueVisitor.visitConstantElementValue(clazz, annotation, constantElementValue);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ elementValueVisitor.visitEnumConstantElementValue(clazz, annotation, enumConstantElementValue);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ elementValueVisitor.visitClassElementValue(clazz, annotation, classElementValue);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ elementValueVisitor.visitAnnotationElementValue(clazz, annotation, annotationElementValue);
+
+ if (deep)
+ {
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ elementValueVisitor.visitArrayElementValue(clazz, annotation, arrayElementValue);
+
+ if (deep)
+ {
+ arrayElementValue.elementValuesAccept(clazz, annotation, elementValueVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java
new file mode 100644
index 0000000000..646b5ab6b2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.annotation.Annotation;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+
+/**
+ * This AnnotationVisitor delegates all visits to a given ClassVisitor.
+ * The latter visits the class of each visited annotation, although
+ * never twice in a row.
+ *
+ * @author Eric Lafortune
+ */
+public class AnnotatedClassVisitor
+extends SimplifiedVisitor
+implements AnnotationVisitor
+{
+ private final ClassVisitor classVisitor;
+
+ private Clazz lastVisitedClass;
+
+
+ public AnnotatedClassVisitor(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ if (!clazz.equals(lastVisitedClass))
+ {
+ clazz.accept(classVisitor);
+
+ lastVisitedClass = clazz;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java
new file mode 100644
index 0000000000..c21dcd6a5f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.Annotation;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+
+
+/**
+ * This AnnotationVisitor delegates all visits to a given MemberVisitor.
+ * The latter visits the class member of each visited class member annotation
+ * or method parameter annotation, although never twice in a row.
+ *
+ * @author Eric Lafortune
+ */
+public class AnnotationToMemberVisitor
+extends SimplifiedVisitor
+implements AnnotationVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+ private Member lastVisitedMember;
+
+
+ public AnnotationToMemberVisitor(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Member member, Annotation annotation)
+ {
+ if (!member.equals(lastVisitedMember))
+ {
+ member.accept(clazz, memberVisitor);
+
+ lastVisitedMember = member;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java
new file mode 100644
index 0000000000..0d5a6e6118
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java
@@ -0,0 +1,110 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.Annotation;
+import proguard.util.*;
+
+/**
+ * This <code>AnnotationVisitor</code> delegates its visits to another given
+ * <code>AnnotationVisitor</code>, but only when the visited annotation has
+ * a type that matches a given regular expression.
+ *
+ * @author Eric Lafortune
+ */
+public class AnnotationTypeFilter
+implements AnnotationVisitor
+{
+ private final StringMatcher regularExpressionMatcher;
+ private final AnnotationVisitor annotationVisitor;
+
+
+ /**
+ * Creates a new ClassNameFilter.
+ * @param regularExpression the regular expression against which annotation
+ * type names will be matched.
+ * @param annotationVisitor the <code>annotationVisitor</code> to which
+ * visits will be delegated.
+ */
+ public AnnotationTypeFilter(String regularExpression,
+ AnnotationVisitor annotationVisitor)
+ {
+ this.regularExpressionMatcher = new ListParser(new ClassNameParser()).parse(regularExpression);
+ this.annotationVisitor = annotationVisitor;
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ if (accepted(annotation.getType(clazz)))
+ {
+ annotationVisitor.visitAnnotation(clazz, annotation);
+ }
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Field field, Annotation annotation)
+ {
+ if (accepted(annotation.getType(clazz)))
+ {
+ annotationVisitor.visitAnnotation(clazz, field, annotation);
+ }
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, Annotation annotation)
+ {
+ if (accepted(annotation.getType(clazz)))
+ {
+ annotationVisitor.visitAnnotation(clazz, method, annotation);
+ }
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, int parameterIndex, Annotation annotation)
+ {
+ if (accepted(annotation.getType(clazz)))
+ {
+ annotationVisitor.visitAnnotation(clazz, method, parameterIndex, annotation);
+ }
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, Annotation annotation)
+ {
+ if (accepted(annotation.getType(clazz)))
+ {
+ annotationVisitor.visitAnnotation(clazz, method, codeAttribute, annotation);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean accepted(String name)
+ {
+ return regularExpressionMatcher.matches(name);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java
new file mode 100644
index 0000000000..b9c93e98bc
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java
@@ -0,0 +1,42 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.Annotation;
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>Annotation</code> objects. Note that there is only a single
+ * implementation of <code>Annotation</code>, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface AnnotationVisitor
+{
+ public void visitAnnotation(Clazz clazz, Annotation annotation);
+ public void visitAnnotation(Clazz clazz, Field field, Annotation annotation);
+ public void visitAnnotation(Clazz clazz, Method method, Annotation annotation);
+ public void visitAnnotation(Clazz clazz, Method method, int parameterIndex, Annotation annotation);
+ public void visitAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, Annotation annotation);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java
new file mode 100644
index 0000000000..076c0421fd
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java
@@ -0,0 +1,51 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.annotation.*;
+
+/**
+ * This interface specifies the methods for a visitor of <code>ElementValue</code>
+ * objects.
+ *
+ * @author Eric Lafortune
+ */
+public interface ElementValueVisitor
+{
+ public void visitConstantElementValue( Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue);
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue);
+ public void visitClassElementValue( Clazz clazz, Annotation annotation, ClassElementValue classElementValue);
+ public void visitAnnotationElementValue( Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue);
+ public void visitArrayElementValue( Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue);
+
+// public void visitConstantElementValue( Clazz clazz, Field field, Annotation annotation, ConstantElementValue constantElementValue);
+// public void visitEnumConstantElementValue(Clazz clazz, Field field, Annotation annotation, EnumConstantElementValue enumConstantElementValue);
+// public void visitClassElementValue( Clazz clazz, Field field, Annotation annotation, ClassElementValue classElementValue);
+// public void visitAnnotationElementValue( Clazz clazz, Field field, Annotation annotation, AnnotationElementValue annotationElementValue);
+// public void visitArrayElementValue( Clazz clazz, Field field, Annotation annotation, ArrayElementValue arrayElementValue);
+//
+// public void visitConstantElementValue( Clazz clazz, Method method, Annotation annotation, ConstantElementValue constantElementValue);
+// public void visitEnumConstantElementValue(Clazz clazz, Method method, Annotation annotation, EnumConstantElementValue enumConstantElementValue);
+// public void visitClassElementValue( Clazz clazz, Method method, Annotation annotation, ClassElementValue classElementValue);
+// public void visitAnnotationElementValue( Clazz clazz, Method method, Annotation annotation, AnnotationElementValue annotationElementValue);
+// public void visitArrayElementValue( Clazz clazz, Method method, Annotation annotation, ArrayElementValue arrayElementValue);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/TypeAnnotationVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/TypeAnnotationVisitor.java
new file mode 100644
index 0000000000..3a2f4fd8fa
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/TypeAnnotationVisitor.java
@@ -0,0 +1,41 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.*;
+
+/**
+ * This interface specifies the methods for a visitor of
+ * TypeAnnotation instances. Note that there is only a single
+ * implementation of TypeAnnotation, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface TypeAnnotationVisitor
+{
+ public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation);
+ public void visitTypeAnnotation(Clazz clazz, Field field, TypeAnnotation typeAnnotation);
+ public void visitTypeAnnotation(Clazz clazz, Method method, TypeAnnotation typeAnnotation);
+ public void visitTypeAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/TypePathInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/TypePathInfoVisitor.java
new file mode 100644
index 0000000000..34bfa081d0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/TypePathInfoVisitor.java
@@ -0,0 +1,41 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.annotation.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.*;
+
+/**
+ * This interface specifies the methods for a visitor of
+ * TypePathInfo instances. Note that there is only a single
+ * implementation of TypePathInfo, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface TypePathInfoVisitor
+{
+ public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo);
+ public void visitTypePathInfo(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo);
+ public void visitTypePathInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo);
+ public void visitTypePathInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/package.html
new file mode 100644
index 0000000000..10d0648501
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/annotation/visitor/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains visitors for annotation attributes and their components.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/package.html
new file mode 100644
index 0000000000..d17caaafdc
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains classes to represent the attributes inside class files.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/DoubleType.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/DoubleType.java
new file mode 100644
index 0000000000..ff124d7b1d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/DoubleType.java
@@ -0,0 +1,66 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.VerificationTypeVisitor;
+
+/**
+ * This VerificationType represents a Double type.
+ *
+ * @author Eric Lafortune
+ */
+public class DoubleType extends VerificationType
+{
+ // Implementations for VerificationType.
+
+ public int getTag()
+ {
+ return DOUBLE_TYPE;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitDoubleType(clazz, method, codeAttribute, instructionOffset, this);
+ }
+
+
+ public void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int stackIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitStackDoubleType(clazz, method, codeAttribute, instructionOffset, stackIndex, this);
+ }
+
+
+ public void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int variableIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitVariablesDoubleType(clazz, method, codeAttribute, instructionOffset, variableIndex, this);
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return "d";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/FloatType.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/FloatType.java
new file mode 100644
index 0000000000..3a8e8315c2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/FloatType.java
@@ -0,0 +1,66 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.VerificationTypeVisitor;
+
+/**
+ * This VerificationType represents a Float type.
+ *
+ * @author Eric Lafortune
+ */
+public class FloatType extends VerificationType
+{
+ // Implementations for VerificationType.
+
+ public int getTag()
+ {
+ return FLOAT_TYPE;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitFloatType(clazz, method, codeAttribute, instructionOffset, this);
+ }
+
+
+ public void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int stackIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitStackFloatType(clazz, method, codeAttribute, instructionOffset, stackIndex, this);
+ }
+
+
+ public void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int variableIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitVariablesFloatType(clazz, method, codeAttribute, instructionOffset, variableIndex, this);
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return "f";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/FullFrame.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/FullFrame.java
new file mode 100644
index 0000000000..8c405d2246
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/FullFrame.java
@@ -0,0 +1,202 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.*;
+
+/**
+ * This StackMapFrame represents a "full frame".
+ *
+ * @author Eric Lafortune
+ */
+public class FullFrame extends StackMapFrame
+{
+ public int variablesCount;
+ public VerificationType[] variables;
+ public int stackCount;
+ public VerificationType[] stack;
+
+
+ /**
+ * Creates an uninitialized FullFrame.
+ */
+ public FullFrame()
+ {
+ }
+
+
+ /**
+ * Creates a FullFrame with the given variables and stack.
+ */
+ public FullFrame(int offsetDelta,
+ VerificationType[] variables,
+ VerificationType[] stack)
+ {
+ this(offsetDelta,
+ variables.length,
+ variables,
+ stack.length,
+ stack);
+ }
+
+
+ /**
+ * Creates a FullFrame with the given variables and stack.
+ */
+ public FullFrame(int offsetDelta,
+ int variablesCount,
+ VerificationType[] variables,
+ int stackCount,
+ VerificationType[] stack)
+ {
+ this.u2offsetDelta = offsetDelta;
+ this.variablesCount = variablesCount;
+ this.variables = variables;
+ this.stackCount = stackCount;
+ this.stack = stack;
+ }
+
+
+ /**
+ * Applies the given verification type visitor to all variables.
+ */
+ public void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ for (int index = 0; index < variablesCount; index++)
+ {
+ variables[index].variablesAccept(clazz, method, codeAttribute, offset, index, verificationTypeVisitor);
+ }
+ }
+
+
+ /**
+ * Applies the given verification type visitor to all stack.
+ */
+ public void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ for (int index = 0; index < stackCount; index++)
+ {
+ stack[index].stackAccept(clazz, method, codeAttribute, offset, index, verificationTypeVisitor);
+ }
+ }
+
+
+ // Implementations for StackMapFrame.
+
+ public int getTag()
+ {
+ return FULL_FRAME;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrameVisitor stackMapFrameVisitor)
+ {
+ stackMapFrameVisitor.visitFullFrame(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (!super.equals(object))
+ {
+ return false;
+ }
+
+ FullFrame other = (FullFrame)object;
+
+ if (this.u2offsetDelta != other.u2offsetDelta ||
+ this.variablesCount != other.variablesCount ||
+ this.stackCount != other.stackCount)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < variablesCount; index++)
+ {
+ VerificationType thisType = this.variables[index];
+ VerificationType otherType = other.variables[index];
+
+ if (!thisType.equals(otherType))
+ {
+ return false;
+ }
+ }
+
+ for (int index = 0; index < stackCount; index++)
+ {
+ VerificationType thisType = this.stack[index];
+ VerificationType otherType = other.stack[index];
+
+ if (!thisType.equals(otherType))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ public int hashCode()
+ {
+ int hashCode = super.hashCode();
+
+ for (int index = 0; index < variablesCount; index++)
+ {
+ hashCode ^= variables[index].hashCode();
+ }
+
+ for (int index = 0; index < stackCount; index++)
+ {
+ hashCode ^= stack[index].hashCode();
+ }
+
+ return hashCode;
+ }
+
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer(super.toString()).append("Var: ");
+
+ for (int index = 0; index < variablesCount; index++)
+ {
+ buffer = buffer.append('[')
+ .append(variables[index].toString())
+ .append(']');
+ }
+
+ buffer.append(", Stack: ");
+
+ for (int index = 0; index < stackCount; index++)
+ {
+ buffer = buffer.append('[')
+ .append(stack[index].toString())
+ .append(']');
+ }
+
+ return buffer.toString();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/IntegerType.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/IntegerType.java
new file mode 100644
index 0000000000..5228b61b4e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/IntegerType.java
@@ -0,0 +1,66 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.VerificationTypeVisitor;
+
+/**
+ * This VerificationType represents a Integer type.
+ *
+ * @author Eric Lafortune
+ */
+public class IntegerType extends VerificationType
+{
+ // Implementations for VerificationType.
+
+ public int getTag()
+ {
+ return INTEGER_TYPE;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitIntegerType(clazz, method, codeAttribute, instructionOffset, this);
+ }
+
+
+ public void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int stackIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitStackIntegerType(clazz, method, codeAttribute, instructionOffset, stackIndex, this);
+ }
+
+
+ public void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int variableIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitVariablesIntegerType(clazz, method, codeAttribute, instructionOffset, variableIndex, this);
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return "i";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/LessZeroFrame.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/LessZeroFrame.java
new file mode 100644
index 0000000000..4308506380
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/LessZeroFrame.java
@@ -0,0 +1,103 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.StackMapFrameVisitor;
+
+/**
+ * This StackMapFrame represents an "chop frame".
+ *
+ * @author Eric Lafortune
+ */
+public class LessZeroFrame extends StackMapFrame
+{
+ public int choppedVariablesCount;
+
+
+ /**
+ * Creates an uninitialized LessZeroFrame.
+ */
+ public LessZeroFrame()
+ {
+ }
+
+
+ /**
+ * Creates a LessZeroFrame with the given tag.
+ */
+ public LessZeroFrame(int tag)
+ {
+ choppedVariablesCount = LESS_ZERO_FRAME + 3 - tag;
+ }
+
+
+ /**
+ * Creates a LessZeroFrame with the given number of chopped variables.
+ */
+ public LessZeroFrame(byte choppedVariablesCount)
+ {
+ this.choppedVariablesCount = (int)choppedVariablesCount;
+ }
+
+
+ // Implementations for StackMapFrame.
+
+ public int getTag()
+ {
+ return LESS_ZERO_FRAME + 3 - choppedVariablesCount;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrameVisitor stackMapFrameVisitor)
+ {
+ stackMapFrameVisitor.visitLessZeroFrame(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (!super.equals(object))
+ {
+ return false;
+ }
+
+ LessZeroFrame other = (LessZeroFrame)object;
+
+ return this.u2offsetDelta == other.u2offsetDelta &&
+ this.choppedVariablesCount != other.choppedVariablesCount;
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^ choppedVariablesCount;
+ }
+
+
+ public String toString()
+ {
+ return super.toString()+"Var: (chopped "+choppedVariablesCount+"), Stack: (empty)";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/LongType.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/LongType.java
new file mode 100644
index 0000000000..82b8af9075
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/LongType.java
@@ -0,0 +1,66 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.VerificationTypeVisitor;
+
+/**
+ * This VerificationType represents a Long type.
+ *
+ * @author Eric Lafortune
+ */
+public class LongType extends VerificationType
+{
+ // Implementations for VerificationType.
+
+ public int getTag()
+ {
+ return LONG_TYPE;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitLongType(clazz, method, codeAttribute, instructionOffset, this);
+ }
+
+
+ public void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int stackIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitStackLongType(clazz, method, codeAttribute, instructionOffset, stackIndex, this);
+ }
+
+
+ public void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int variableIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitVariablesLongType(clazz, method, codeAttribute, instructionOffset, variableIndex, this);
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return "l";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java
new file mode 100644
index 0000000000..a8858048e6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java
@@ -0,0 +1,161 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.*;
+
+/**
+ * This StackMapFrame represents an "append frame".
+ *
+ * @author Eric Lafortune
+ */
+public class MoreZeroFrame extends StackMapFrame
+{
+ public int additionalVariablesCount;
+ public VerificationType[] additionalVariables;
+
+
+ /**
+ * Creates an uninitialized MoreZeroFrame.
+ */
+ public MoreZeroFrame()
+ {
+ }
+
+
+ /**
+ * Creates a MoreZeroFrame with the given tag.
+ */
+ public MoreZeroFrame(int tag)
+ {
+ additionalVariablesCount = tag + 1 - MORE_ZERO_FRAME;
+ }
+
+
+ /**
+ * Creates a MoreZeroFrame with the given additional variables.
+ */
+ public MoreZeroFrame(VerificationType[] additionalVariables)
+ {
+ this(additionalVariables.length, additionalVariables);
+ }
+
+
+ /**
+ * Creates a MoreZeroFrame with the given additional variables.
+ */
+ public MoreZeroFrame(int additionalVariablesCount,
+ VerificationType[] additionalVariables)
+ {
+ this.additionalVariablesCount = additionalVariablesCount;
+ this.additionalVariables = additionalVariables;
+ }
+
+
+ /**
+ * Applies the given verification type visitor to all variables.
+ */
+ public void additionalVariablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ for (int index = 0; index < additionalVariablesCount; index++)
+ {
+ additionalVariables[index].accept(clazz, method, codeAttribute, offset, verificationTypeVisitor);
+ }
+ }
+
+
+ // Implementations for StackMapFrame.
+
+ public int getTag()
+ {
+ return MORE_ZERO_FRAME + additionalVariablesCount - 1;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrameVisitor stackMapFrameVisitor)
+ {
+ stackMapFrameVisitor.visitMoreZeroFrame(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (!super.equals(object))
+ {
+ return false;
+ }
+
+ MoreZeroFrame other = (MoreZeroFrame)object;
+
+ if (this.u2offsetDelta != other.u2offsetDelta ||
+ this.additionalVariablesCount != other.additionalVariablesCount)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < additionalVariablesCount; index++)
+ {
+ VerificationType thisType = this.additionalVariables[index];
+ VerificationType otherType = other.additionalVariables[index];
+
+ if (!thisType.equals(otherType))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ public int hashCode()
+ {
+ int hashCode = super.hashCode();
+
+ for (int index = 0; index < additionalVariablesCount; index++)
+ {
+ hashCode ^= additionalVariables[index].hashCode();
+ }
+
+ return hashCode;
+ }
+
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer(super.toString()).append("Var: ...");
+
+ for (int index = 0; index < additionalVariablesCount; index++)
+ {
+ buffer = buffer.append('[')
+ .append(additionalVariables[index].toString())
+ .append(']');
+ }
+
+ buffer.append(", Stack: (empty)");
+
+ return buffer.toString();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/NullType.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/NullType.java
new file mode 100644
index 0000000000..96003f0676
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/NullType.java
@@ -0,0 +1,66 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.VerificationTypeVisitor;
+
+/**
+ * This VerificationType represents a Null type.
+ *
+ * @author Eric Lafortune
+ */
+public class NullType extends VerificationType
+{
+ // Implementations for VerificationType.
+
+ public int getTag()
+ {
+ return NULL_TYPE;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitNullType(clazz, method, codeAttribute, instructionOffset, this);
+ }
+
+
+ public void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int stackIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitStackNullType(clazz, method, codeAttribute, instructionOffset, stackIndex, this);
+ }
+
+
+ public void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int variableIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitVariablesNullType(clazz, method, codeAttribute, instructionOffset, variableIndex, this);
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return "n";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/ObjectType.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/ObjectType.java
new file mode 100644
index 0000000000..5a4f1b775d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/ObjectType.java
@@ -0,0 +1,107 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.VerificationTypeVisitor;
+
+/**
+ * This VerificationType represents an Object type.
+ *
+ * @author Eric Lafortune
+ */
+public class ObjectType extends VerificationType
+{
+ public int u2classIndex;
+
+
+
+ /**
+ * Creates an uninitialized ObjectType.
+ */
+ public ObjectType()
+ {
+ }
+
+
+ /**
+ * Creates an ObjectType that points to the given class constant.
+ */
+ public ObjectType(int u2classIndex)
+ {
+ this.u2classIndex = u2classIndex;
+ }
+
+
+ // Implementations for VerificationType.
+
+ public int getTag()
+ {
+ return OBJECT_TYPE;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitObjectType(clazz, method, codeAttribute, instructionOffset, this);
+ }
+
+
+ public void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int stackIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitStackObjectType(clazz, method, codeAttribute, instructionOffset, stackIndex, this);
+ }
+
+
+ public void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int variableIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitVariablesObjectType(clazz, method, codeAttribute, instructionOffset, variableIndex, this);
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (!super.equals(object))
+ {
+ return false;
+ }
+
+ ObjectType other = (ObjectType)object;
+
+ return this.u2classIndex == other.u2classIndex;
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ u2classIndex;
+ }
+
+
+ public String toString()
+ {
+ return "a:" + u2classIndex;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/SameOneFrame.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/SameOneFrame.java
new file mode 100644
index 0000000000..8a16762709
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/SameOneFrame.java
@@ -0,0 +1,115 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.*;
+
+/**
+ * This StackMapFrame represents a "same locals 1 stack item frame" or a
+ * "same locals 1 stack item frame extended".
+ *
+ * @author Eric Lafortune
+ */
+public class SameOneFrame extends StackMapFrame
+{
+ public VerificationType stackItem;
+
+
+ /**
+ * Creates an uninitialized SameOneFrame.
+ */
+ public SameOneFrame()
+ {
+ }
+
+
+ /**
+ * Creates a SameOneFrame with the given tag.
+ */
+ public SameOneFrame(int tag)
+ {
+ u2offsetDelta = tag - SAME_ONE_FRAME;
+ }
+
+
+ /**
+ * Creates a SameOneFrame with the given stack verification type.
+ */
+ public SameOneFrame(VerificationType stackItem)
+ {
+ this.stackItem = stackItem;
+ }
+
+
+ /**
+ * Applies the given verification type visitor to the stack item.
+ */
+ public void stackItemAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ stackItem.accept(clazz, method, codeAttribute, offset, verificationTypeVisitor);
+ }
+
+
+ // Implementations for StackMapFrame.
+
+ public int getTag()
+ {
+ return u2offsetDelta < 64 ?
+ SAME_ONE_FRAME + u2offsetDelta :
+ SAME_ONE_FRAME_EXTENDED;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrameVisitor stackMapFrameVisitor)
+ {
+ stackMapFrameVisitor.visitSameOneFrame(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (!super.equals(object))
+ {
+ return false;
+ }
+
+ SameOneFrame other = (SameOneFrame)object;
+
+ return this.u2offsetDelta == other.u2offsetDelta &&
+ this.stackItem.equals(other.stackItem);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^ stackItem.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return super.toString()+"Var: ..., Stack: ["+stackItem.toString()+"]";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/SameZeroFrame.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/SameZeroFrame.java
new file mode 100644
index 0000000000..90200ba03d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/SameZeroFrame.java
@@ -0,0 +1,74 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.StackMapFrameVisitor;
+
+/**
+ * This StackMapFrame represents a "same frame" or a "same frame extended".
+ *
+ * @author Eric Lafortune
+ * @noinspection PointlessArithmeticExpression
+ */
+public class SameZeroFrame extends StackMapFrame
+{
+ /**
+ * Creates an uninitialized SameZeroFrame.
+ */
+ public SameZeroFrame()
+ {
+ }
+
+
+ /**
+ * Creates a SameZeroFrame with the given tag.
+ */
+ public SameZeroFrame(int tag)
+ {
+ u2offsetDelta = tag - SAME_ZERO_FRAME;
+ }
+
+
+ // Implementations for StackMapFrame.
+
+ public int getTag()
+ {
+ return u2offsetDelta < 64 ?
+ SAME_ZERO_FRAME + u2offsetDelta :
+ SAME_ZERO_FRAME_EXTENDED;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrameVisitor stackMapFrameVisitor)
+ {
+ stackMapFrameVisitor.visitSameZeroFrame(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return super.toString()+"Var: ..., Stack: (empty)";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapAttribute.java
new file mode 100644
index 0000000000..5ff0a08327
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapAttribute.java
@@ -0,0 +1,91 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.preverification.visitor.StackMapFrameVisitor;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents an exceptions attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class StackMapAttribute extends Attribute
+{
+ public int u2stackMapFramesCount;
+ public FullFrame[] stackMapFrames;
+
+
+ /**
+ * Creates an uninitialized ExceptionsAttribute.
+ */
+ public StackMapAttribute()
+ {
+ }
+
+
+ /**
+ * Creates a StackMapTableAttribute with the given stack map frames.
+ */
+ public StackMapAttribute(FullFrame[] stackMapFrames)
+ {
+ this(stackMapFrames.length, stackMapFrames);
+ }
+
+
+ /**
+ * Creates a StackMapTableAttribute with the given stack map frames.
+ */
+ public StackMapAttribute(int stackMapFramesCount,
+ FullFrame[] stackMapFrames)
+ {
+ this.u2stackMapFramesCount = stackMapFramesCount;
+ this.stackMapFrames = stackMapFrames;
+ }
+
+
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitStackMapAttribute(clazz, method, codeAttribute, this);
+ }
+
+
+ /**
+ * Applies the given stack map frame visitor to all stack map frames.
+ */
+ public void stackMapFramesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapFrameVisitor stackMapFrameVisitor)
+ {
+ for (int index = 0; index < u2stackMapFramesCount; index++)
+ {
+ FullFrame stackMapFrame = stackMapFrames[index];
+
+ // We don't need double dispatching here, since there is only one
+ // type of StackMapFrame.
+ stackMapFrameVisitor.visitFullFrame(clazz, method, codeAttribute, stackMapFrame.getOffsetDelta(), stackMapFrame);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapFrame.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapFrame.java
new file mode 100644
index 0000000000..474650cc2a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapFrame.java
@@ -0,0 +1,117 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.StackMapFrameVisitor;
+
+/**
+ * This abstract class represents a stack map frame. Specific types
+ * of entries are subclassed from it.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class StackMapFrame implements VisitorAccepter
+{
+ public static final int SAME_ZERO_FRAME = 0;
+ public static final int SAME_ONE_FRAME = 64;
+ public static final int SAME_ONE_FRAME_EXTENDED = 247;
+ public static final int LESS_ZERO_FRAME = 248;
+ public static final int SAME_ZERO_FRAME_EXTENDED = 251;
+ public static final int MORE_ZERO_FRAME = 252;
+ public static final int FULL_FRAME = 255;
+
+
+ public int u2offsetDelta;
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+
+ /**
+ * Returns the bytecode offset delta relative to the previous stack map
+ * frame.
+ */
+ public int getOffsetDelta()
+ {
+ return u2offsetDelta;
+ }
+
+
+ // Abstract methods to be implemented by extensions.
+
+ /**
+ * Returns the stack map frame tag that specifies the entry type.
+ */
+ public abstract int getTag();
+
+
+ /**
+ * Accepts the given visitor.
+ */
+ public abstract void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrameVisitor stackMapFrameVisitor);
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (object == null ||
+ this.getClass() != object.getClass())
+ {
+ return false;
+ }
+
+ StackMapFrame other = (StackMapFrame)object;
+
+ return this.u2offsetDelta == other.u2offsetDelta;
+ }
+
+
+ public int hashCode()
+ {
+ return getClass().hashCode() ^
+ u2offsetDelta;
+ }
+
+
+ public String toString()
+ {
+ return "[" + u2offsetDelta + "] ";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java
new file mode 100644
index 0000000000..b122221e7a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.preverification.visitor.StackMapFrameVisitor;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+
+/**
+ * This Attribute represents a stack map table attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class StackMapTableAttribute extends Attribute
+{
+ public int u2stackMapFramesCount;
+ public StackMapFrame[] stackMapFrames;
+
+
+ /**
+ * Creates an uninitialized StackMapTableAttribute.
+ */
+ public StackMapTableAttribute()
+ {
+ }
+
+
+ /**
+ * Creates a StackMapTableAttribute with the given stack map frames.
+ */
+ public StackMapTableAttribute(StackMapFrame[] stackMapFrames)
+ {
+ this(stackMapFrames.length, stackMapFrames);
+ }
+
+
+ /**
+ * Creates a StackMapTableAttribute with the given stack map frames.
+ */
+ public StackMapTableAttribute(int stackMapFramesCount,
+ StackMapFrame[] stackMapFrames)
+ {
+ this.u2stackMapFramesCount = stackMapFramesCount;
+ this.stackMapFrames = stackMapFrames;
+ }
+
+
+ // Implementations for Attribute.
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor)
+ {
+ attributeVisitor.visitStackMapTableAttribute(clazz, method, codeAttribute, this);
+ }
+
+
+ /**
+ * Applies the given stack map frame visitor to all stack map frames.
+ */
+ public void stackMapFramesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapFrameVisitor stackMapFrameVisitor)
+ {
+ int offset = 0;
+
+ for (int index = 0; index < u2stackMapFramesCount; index++)
+ {
+ StackMapFrame stackMapFrame = stackMapFrames[index];
+
+ // Note that the byte code offset is computed differently for the
+ // first stack map frame.
+ offset += stackMapFrame.getOffsetDelta() + (index == 0 ? 0 : 1);
+
+ stackMapFrame.accept(clazz, method, codeAttribute, offset, stackMapFrameVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/TopType.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/TopType.java
new file mode 100644
index 0000000000..065c9ebc64
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/TopType.java
@@ -0,0 +1,66 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.VerificationTypeVisitor;
+
+/**
+ * This VerificationType represents a Top type.
+ *
+ * @author Eric Lafortune
+ */
+public class TopType extends VerificationType
+{
+ // Implementations for VerificationType.
+
+ public int getTag()
+ {
+ return TOP_TYPE;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitTopType(clazz, method, codeAttribute, instructionOffset, this);
+ }
+
+
+ public void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int stackIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitStackTopType(clazz, method, codeAttribute, instructionOffset, stackIndex, this);
+ }
+
+
+ public void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int variableIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitVariablesTopType(clazz, method, codeAttribute, instructionOffset, variableIndex, this);
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return "T";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/UninitializedThisType.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/UninitializedThisType.java
new file mode 100644
index 0000000000..21d210be6b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/UninitializedThisType.java
@@ -0,0 +1,66 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.VerificationTypeVisitor;
+
+/**
+ * This VerificationType represents a UninitializedThis type.
+ *
+ * @author Eric Lafortune
+ */
+public class UninitializedThisType extends VerificationType
+{
+ // Implementations for VerificationType.
+
+ public int getTag()
+ {
+ return UNINITIALIZED_THIS_TYPE;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitUninitializedThisType(clazz, method, codeAttribute, instructionOffset, this);
+ }
+
+
+ public void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int stackIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitStackUninitializedThisType(clazz, method, codeAttribute, instructionOffset, stackIndex, this);
+ }
+
+
+ public void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int variableIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitVariablesUninitializedThisType(clazz, method, codeAttribute, instructionOffset, variableIndex, this);
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return "u:this";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/UninitializedType.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/UninitializedType.java
new file mode 100644
index 0000000000..ad44e05c7c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/UninitializedType.java
@@ -0,0 +1,106 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.VerificationTypeVisitor;
+
+/**
+ * This VerificationType represents a Uninitialized type.
+ *
+ * @author Eric Lafortune
+ */
+public class UninitializedType extends VerificationType
+{
+ public int u2newInstructionOffset;
+
+
+ /**
+ * Creates an uninitialized UninitializedType.
+ */
+ public UninitializedType()
+ {
+ }
+
+
+ /**
+ * Creates an UninitializedType pointing to the given 'new' instruction.
+ */
+ public UninitializedType(int u2newInstructionOffset)
+ {
+ this.u2newInstructionOffset = u2newInstructionOffset;
+ }
+
+
+ // Implementations for VerificationType.
+
+ public int getTag()
+ {
+ return UNINITIALIZED_TYPE;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitUninitializedType(clazz, method, codeAttribute, instructionOffset, this);
+ }
+
+
+ public void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int stackIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitStackUninitializedType(clazz, method, codeAttribute, instructionOffset, stackIndex, this);
+ }
+
+
+ public void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int variableIndex, VerificationTypeVisitor verificationTypeVisitor)
+ {
+ verificationTypeVisitor.visitVariablesUninitializedType(clazz, method, codeAttribute, instructionOffset, variableIndex, this);
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (!super.equals(object))
+ {
+ return false;
+ }
+
+ UninitializedType other = (UninitializedType)object;
+
+ return this.u2newInstructionOffset == other.u2newInstructionOffset;
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ u2newInstructionOffset;
+ }
+
+
+ public String toString()
+ {
+ return "u:" + u2newInstructionOffset;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/VerificationType.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/VerificationType.java
new file mode 100644
index 0000000000..29ff241fdb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/VerificationType.java
@@ -0,0 +1,103 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.visitor.VerificationTypeVisitor;
+
+/**
+ * This abstract class represents a verification type of a local variable or
+ * a stack element. Specific verification types are subclassed from it.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class VerificationType implements VisitorAccepter
+{
+ public static final int TOP_TYPE = 0;
+ public static final int INTEGER_TYPE = 1;
+ public static final int FLOAT_TYPE = 2;
+ public static final int DOUBLE_TYPE = 3;
+ public static final int LONG_TYPE = 4;
+ public static final int NULL_TYPE = 5;
+ public static final int UNINITIALIZED_THIS_TYPE = 6;
+ public static final int OBJECT_TYPE = 7;
+ public static final int UNINITIALIZED_TYPE = 8;
+
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ /**
+ * Returns the tag of the verification type.
+ */
+ public abstract int getTag();
+
+
+ /**
+ * Accepts the given visitor in the context of a method's code, either on
+ * a stack or as a variable.
+ */
+ public abstract void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, VerificationTypeVisitor verificationTypeVisitor);
+
+
+ /**
+ * Accepts the given visitor in the context of a stack in a method's code .
+ */
+ public abstract void stackAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int stackIndex, VerificationTypeVisitor verificationTypeVisitor);
+
+
+ /**
+ * Accepts the given visitor in the context of a variable in a method's code.
+ */
+ public abstract void variablesAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset, int variableIndex, VerificationTypeVisitor verificationTypeVisitor);
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return object != null &&
+ this.getClass() == object.getClass();
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java
new file mode 100644
index 0000000000..3fca3d3524
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java
@@ -0,0 +1,112 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification;
+
+/**
+ * This class provides methods to create and reuse IntegerType objects.
+ *
+ * @author Eric Lafortune
+ */
+public class VerificationTypeFactory
+{
+ // Shared copies of Type objects, to avoid creating a lot of objects.
+ static final IntegerType INTEGER_TYPE = new IntegerType();
+ static final LongType LONG_TYPE = new LongType();
+ static final FloatType FLOAT_TYPE = new FloatType();
+ static final DoubleType DOUBLE_TYPE = new DoubleType();
+ static final TopType TOP_TYPE = new TopType();
+ static final NullType NULL_TYPE = new NullType();
+ static final UninitializedThisType UNINITIALIZED_THIS_TYPE = new UninitializedThisType();
+
+
+ /**
+ * Creates a new IntegerType.
+ */
+ public static IntegerType createIntegerType()
+ {
+ return INTEGER_TYPE;
+ }
+
+ /**
+ * Creates a new LongType.
+ */
+ public static LongType createLongType()
+ {
+ return LONG_TYPE;
+ }
+
+ /**
+ * Creates a new FloatType.
+ */
+ public static FloatType createFloatType()
+ {
+ return FLOAT_TYPE;
+ }
+
+ /**
+ * Creates a new DoubleType.
+ */
+ public static DoubleType createDoubleType()
+ {
+ return DOUBLE_TYPE;
+ }
+
+ /**
+ * Creates a new TopType.
+ */
+ public static TopType createTopType()
+ {
+ return TOP_TYPE;
+ }
+
+ /**
+ * Creates a new NullType.
+ */
+ public static NullType createNullType()
+ {
+ return NULL_TYPE;
+ }
+
+ /**
+ * Creates a new UninitializedThisType.
+ */
+ public static UninitializedThisType createUninitializedThisType()
+ {
+ return UNINITIALIZED_THIS_TYPE;
+ }
+
+ /**
+ * Creates a new UninitializedType for an instance that was created at
+ * the given offset.
+ */
+ public static UninitializedType createUninitializedType(int newInstructionOffset)
+ {
+ return new UninitializedType(newInstructionOffset);
+ }
+
+ /**
+ * Creates a new ObjectType of the given type.
+ */
+ public static ObjectType createObjectType(int classIndex)
+ {
+ return new ObjectType(classIndex);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java
new file mode 100644
index 0000000000..910bd3965e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java
@@ -0,0 +1,40 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.*;
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>StackMapFrame</code> objects.
+ *
+ * @author Eric Lafortune
+ */
+public interface StackMapFrameVisitor
+{
+ public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame);
+ public void visitSameOneFrame( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame);
+ public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame);
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame);
+ public void visitFullFrame( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java
new file mode 100644
index 0000000000..3f087d5803
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.preverification.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.preverification.*;
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>VerificationType</code> objects. There a methods for stack entries
+ * and methods for variable entries.
+ *
+ * @author Eric Lafortune
+ */
+public interface VerificationTypeVisitor
+{
+ public void visitIntegerType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, IntegerType integerType);
+ public void visitFloatType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FloatType floatType);
+ public void visitLongType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LongType longType);
+ public void visitDoubleType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, DoubleType doubleType);
+ public void visitTopType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TopType topType);
+ public void visitObjectType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType);
+ public void visitNullType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, NullType nullType);
+ public void visitUninitializedType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType);
+ public void visitUninitializedThisType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedThisType uninitializedThisType);
+
+ public void visitStackIntegerType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, IntegerType integerType);
+ public void visitStackFloatType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, FloatType floatType);
+ public void visitStackLongType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, LongType longType);
+ public void visitStackDoubleType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, DoubleType doubleType);
+ public void visitStackTopType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, TopType topType);
+ public void visitStackObjectType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, ObjectType objectType);
+ public void visitStackNullType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, NullType nullType);
+ public void visitStackUninitializedType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, UninitializedType uninitializedType);
+ public void visitStackUninitializedThisType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, UninitializedThisType uninitializedThisType);
+
+ public void visitVariablesIntegerType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, IntegerType integerType);
+ public void visitVariablesFloatType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, FloatType floatType);
+ public void visitVariablesLongType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, LongType longType);
+ public void visitVariablesDoubleType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, DoubleType doubleType);
+ public void visitVariablesTopType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, TopType topType);
+ public void visitVariablesObjectType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, ObjectType objectType);
+ public void visitVariablesNullType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, NullType nullType);
+ public void visitVariablesUninitializedType( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, UninitializedType uninitializedType);
+ public void visitVariablesUninitializedThisType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, UninitializedThisType uninitializedThisType);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java
new file mode 100644
index 0000000000..62c53fb031
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java
@@ -0,0 +1,117 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor, MemberVisitor, and AttributeVisitor lets a given
+ * AttributeVisitor visit all Attribute objects of the program classes,
+ * program class members, or code attributes, respectively, that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllAttributeVisitor
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor
+{
+ private final boolean deep;
+ private final AttributeVisitor attributeVisitor;
+
+
+ /**
+ * Creates a new shallow AllAttributeVisitor.
+ * @param attributeVisitor the AttributeVisitor to which visits will be
+ * delegated.
+ */
+ public AllAttributeVisitor(AttributeVisitor attributeVisitor)
+ {
+ this(false, attributeVisitor);
+ }
+
+
+ /**
+ * Creates a new optionally deep AllAttributeVisitor.
+ * @param deep specifies whether the attributes contained
+ * further down the class structure should be
+ * visited too.
+ * @param attributeVisitor the AttributeVisitor to which visits will be
+ * delegated.
+ */
+ public AllAttributeVisitor(boolean deep,
+ AttributeVisitor attributeVisitor)
+ {
+ this.deep = deep;
+ this.attributeVisitor = attributeVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.attributesAccept(attributeVisitor);
+
+ // Visit the attributes further down the class structure, if required.
+ if (deep)
+ {
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+ programClass.attributesAccept(this);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ programMember.attributesAccept(programClass, attributeVisitor);
+
+ // Visit the attributes further down the member structure, if required.
+ if (deep)
+ {
+ programMember.attributesAccept(programClass, this);
+ }
+ }
+
+
+ public void visitLibraryMember(LibraryClass programClass, LibraryMember programMember) {}
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.attributesAccept(clazz, method, attributeVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java
new file mode 100644
index 0000000000..11e892f684
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given BootstrapMethodInfoVisitor visit all
+ * bootstrap method objects of the BootstrapMethodsAttribute objects it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllBootstrapMethodInfoVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor;
+
+
+ public AllBootstrapMethodInfoVisitor(BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor)
+ {
+ this.bootstrapMethodInfoVisitor = bootstrapMethodInfoVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, bootstrapMethodInfoVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java
new file mode 100644
index 0000000000..1e4a6d6bf3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given ExceptionInfoVisitor visit all exceptions
+ * objects of the CodeAttribute objects it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllExceptionInfoVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final ExceptionInfoVisitor exceptionInfoVisitor;
+
+
+ public AllExceptionInfoVisitor(ExceptionInfoVisitor exceptionInfoVisitor)
+ {
+ this.exceptionInfoVisitor = exceptionInfoVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.exceptionsAccept(clazz, method, exceptionInfoVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java
new file mode 100644
index 0000000000..2c2d5603d9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given InnerClassesInfoVisitor visit all
+ * InnerClassessInfo objects of the InnerClassesAttribute objects it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllInnerClassesInfoVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final InnerClassesInfoVisitor innerClassesInfoVisitor;
+
+
+ public AllInnerClassesInfoVisitor(InnerClassesInfoVisitor innerClassesInfoVisitor)
+ {
+ this.innerClassesInfoVisitor = innerClassesInfoVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ innerClassesAttribute.innerClassEntriesAccept(clazz, innerClassesInfoVisitor);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllLineNumberInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllLineNumberInfoVisitor.java
new file mode 100644
index 0000000000..a3a37ba455
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AllLineNumberInfoVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given LineNumberInfoVisitor visit all line numbers
+ * of the LineNumberTableAttribute objects it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllLineNumberInfoVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final LineNumberInfoVisitor lineNumberInfoVisitor;
+
+
+ public AllLineNumberInfoVisitor(LineNumberInfoVisitor lineNumberInfoVisitor)
+ {
+ this.lineNumberInfoVisitor = lineNumberInfoVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, lineNumberInfoVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
new file mode 100644
index 0000000000..340e4f223c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
@@ -0,0 +1,467 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.util.*;
+
+import java.util.List;
+
+/**
+ * This AttributeVisitor delegates its visits another AttributeVisitor, but
+ * only when the visited attribute has a name that that matches a given regular
+ * expression.
+ *
+ * @author Eric Lafortune
+ */
+public class AttributeNameFilter
+implements AttributeVisitor
+{
+ private final StringMatcher regularExpressionMatcher;
+ private final AttributeVisitor attributeVisitor;
+
+
+ /**
+ * Creates a new AttributeNameFilter.
+ * @param regularExpression the regular expression against which attribute
+ * names will be matched.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to which
+ * visits will be delegated.
+ */
+ public AttributeNameFilter(String regularExpression,
+ AttributeVisitor attributeVisitor)
+ {
+ this(new ListParser(new NameParser()).parse(regularExpression),
+ attributeVisitor);
+ }
+
+
+ /**
+ * Creates a new AttributeNameFilter.
+ * @param regularExpression the regular expression against which attribute
+ * names will be matched.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to which
+ * visits will be delegated.
+ */
+ public AttributeNameFilter(List regularExpression,
+ AttributeVisitor attributeVisitor)
+ {
+ this(new ListParser(new NameParser()).parse(regularExpression),
+ attributeVisitor);
+ }
+
+
+ /**
+ * Creates a new AttributeNameFilter.
+ * @param regularExpressionMatcher the string matcher against which
+ * attribute names will be matched.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to
+ * which visits will be delegated.
+ */
+ public AttributeNameFilter(StringMatcher regularExpressionMatcher,
+ AttributeVisitor attributeVisitor)
+ {
+ this.regularExpressionMatcher = regularExpressionMatcher;
+ this.attributeVisitor = attributeVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ if (accepted(clazz, unknownAttribute))
+ {
+ attributeVisitor.visitUnknownAttribute(clazz, unknownAttribute);
+ }
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (accepted(clazz, bootstrapMethodsAttribute))
+ {
+ attributeVisitor.visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute);
+ }
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ if (accepted(clazz, sourceFileAttribute))
+ {
+ attributeVisitor.visitSourceFileAttribute(clazz, sourceFileAttribute);
+ }
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ if (accepted(clazz, sourceDirAttribute))
+ {
+ attributeVisitor.visitSourceDirAttribute(clazz, sourceDirAttribute);
+ }
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ if (accepted(clazz, innerClassesAttribute))
+ {
+ attributeVisitor.visitInnerClassesAttribute(clazz, innerClassesAttribute);
+ }
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ if (accepted(clazz, enclosingMethodAttribute))
+ {
+ attributeVisitor.visitEnclosingMethodAttribute(clazz, enclosingMethodAttribute);
+ }
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ if (accepted(clazz, deprecatedAttribute))
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, deprecatedAttribute);
+ }
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute)
+ {
+ if (accepted(clazz, deprecatedAttribute))
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, field, deprecatedAttribute);
+ }
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute)
+ {
+ if (accepted(clazz, deprecatedAttribute))
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, method, deprecatedAttribute);
+ }
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ if (accepted(clazz, syntheticAttribute))
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, syntheticAttribute);
+ }
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute)
+ {
+ if (accepted(clazz, syntheticAttribute))
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, field, syntheticAttribute);
+ }
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute)
+ {
+ if (accepted(clazz, syntheticAttribute))
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, method, syntheticAttribute);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ if (accepted(clazz, signatureAttribute))
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, signatureAttribute);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute signatureAttribute)
+ {
+ if (accepted(clazz, signatureAttribute))
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, field, signatureAttribute);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute)
+ {
+ if (accepted(clazz, signatureAttribute))
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, method, signatureAttribute);
+ }
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ if (accepted(clazz, constantValueAttribute))
+ {
+ attributeVisitor.visitConstantValueAttribute(clazz, field, constantValueAttribute);
+ }
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute exceptionsAttribute)
+ {
+ if (accepted(clazz, exceptionsAttribute))
+ {
+ attributeVisitor.visitMethodParametersAttribute(clazz, method, exceptionsAttribute);
+ }
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ if (accepted(clazz, exceptionsAttribute))
+ {
+ attributeVisitor.visitExceptionsAttribute(clazz, method, exceptionsAttribute);
+ }
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (accepted(clazz, codeAttribute))
+ {
+ attributeVisitor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ if (accepted(clazz, stackMapAttribute))
+ {
+ attributeVisitor.visitStackMapAttribute(clazz, method, codeAttribute, stackMapAttribute);
+ }
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ if (accepted(clazz, stackMapTableAttribute))
+ {
+ attributeVisitor.visitStackMapTableAttribute(clazz, method, codeAttribute, stackMapTableAttribute);
+ }
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ if (accepted(clazz, lineNumberTableAttribute))
+ {
+ attributeVisitor.visitLineNumberTableAttribute(clazz, method, codeAttribute, lineNumberTableAttribute);
+ }
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ if (accepted(clazz, localVariableTableAttribute))
+ {
+ attributeVisitor.visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute);
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ if (accepted(clazz, localVariableTypeTableAttribute))
+ {
+ attributeVisitor.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeVisibleAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeVisibleAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, field, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeVisibleAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, method, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeInvisibleAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeInvisibleAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, field, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeInvisibleAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, method, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeVisibleParameterAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeVisibleParameterAnnotationsAttribute(clazz, method, runtimeVisibleParameterAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeInvisibleParameterAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeInvisibleParameterAnnotationsAttribute(clazz, method, runtimeInvisibleParameterAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeVisibleTypeAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeVisibleTypeAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeVisibleTypeAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeVisibleTypeAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeInvisibleTypeAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeInvisibleTypeAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeInvisibleTypeAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (accepted(clazz, runtimeInvisibleTypeAnnotationsAttribute))
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ if (accepted(clazz, annotationDefaultAttribute))
+ {
+ attributeVisitor.visitAnnotationDefaultAttribute(clazz, method, annotationDefaultAttribute);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean accepted(Clazz clazz, Attribute attribute)
+ {
+ return regularExpressionMatcher.matches(attribute.getAttributeName(clazz));
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AttributeVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
new file mode 100644
index 0000000000..668d13a7a6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
@@ -0,0 +1,101 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
+
+/**
+ * This interface specifies the methods for a visitor of <code>Attribute</code>
+ * objects.
+ *
+ * @author Eric Lafortune
+ */
+public interface AttributeVisitor
+{
+ // Attributes that are attached to classes.
+
+ public void visitUnknownAttribute( Clazz clazz, UnknownAttribute unknownAttribute);
+ public void visitBootstrapMethodsAttribute( Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute);
+ public void visitSourceFileAttribute( Clazz clazz, SourceFileAttribute sourceFileAttribute);
+ public void visitSourceDirAttribute( Clazz clazz, SourceDirAttribute sourceDirAttribute);
+ public void visitInnerClassesAttribute( Clazz clazz, InnerClassesAttribute innerClassesAttribute);
+ public void visitEnclosingMethodAttribute( Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute);
+
+ // Attributes that are attached to classes, fields, and methods.
+
+ public void visitDeprecatedAttribute( Clazz clazz, DeprecatedAttribute deprecatedAttribute);
+ public void visitDeprecatedAttribute( Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute);
+ public void visitDeprecatedAttribute( Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute);
+
+ public void visitSyntheticAttribute( Clazz clazz, SyntheticAttribute syntheticAttribute);
+ public void visitSyntheticAttribute( Clazz clazz, Field field, SyntheticAttribute syntheticAttribute);
+ public void visitSyntheticAttribute( Clazz clazz, Method method, SyntheticAttribute syntheticAttribute);
+
+ public void visitSignatureAttribute( Clazz clazz, SignatureAttribute signatureAttribute);
+ public void visitSignatureAttribute( Clazz clazz, Field field, SignatureAttribute signatureAttribute);
+ public void visitSignatureAttribute( Clazz clazz, Method method, SignatureAttribute signatureAttribute);
+
+ // Attributes that are attached to fields.
+
+ public void visitConstantValueAttribute( Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute);
+
+ // Attributes that are attached to methods.
+
+ public void visitMethodParametersAttribute( Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute);
+ public void visitExceptionsAttribute( Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute);
+ public void visitCodeAttribute( Clazz clazz, Method method, CodeAttribute codeAttribute);
+
+ // Attributes that are attached to code attributes.
+
+ public void visitStackMapAttribute( Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute);
+ public void visitStackMapTableAttribute( Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute);
+ public void visitLineNumberTableAttribute( Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute);
+ public void visitLocalVariableTableAttribute( Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute);
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute);
+
+ // Annotation attributes.
+
+ public void visitRuntimeVisibleAnnotationsAttribute( Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute);
+ public void visitRuntimeVisibleAnnotationsAttribute( Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute);
+ public void visitRuntimeVisibleAnnotationsAttribute( Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute);
+
+ public void visitRuntimeInvisibleAnnotationsAttribute( Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute);
+ public void visitRuntimeInvisibleAnnotationsAttribute( Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute);
+ public void visitRuntimeInvisibleAnnotationsAttribute( Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute);
+
+ public void visitRuntimeVisibleParameterAnnotationsAttribute( Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute);
+ public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute);
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute( Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute);
+ public void visitRuntimeVisibleTypeAnnotationsAttribute( Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute);
+ public void visitRuntimeVisibleTypeAnnotationsAttribute( Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute);
+ public void visitRuntimeVisibleTypeAnnotationsAttribute( Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute);
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute( Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute);
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute( Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute);
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute( Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute);
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute( Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute);
+
+ public void visitAnnotationDefaultAttribute( Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java
new file mode 100755
index 0000000000..f796837765
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java
@@ -0,0 +1,38 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.BootstrapMethodInfo;
+
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>BootstrapMethodInfo</code> objects. Note that there is only a single
+ * implementation of <code>BootstrapMethodInfo</code>, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface BootstrapMethodInfoVisitor
+{
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
new file mode 100644
index 0000000000..e15ab7cb10
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
@@ -0,0 +1,37 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>ExceptionInfo</code> objects. Note that there is only a single
+ * implementation of <code>ExceptionInfo</code>, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface ExceptionInfoVisitor
+{
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java
new file mode 100644
index 0000000000..d4e498493a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java
@@ -0,0 +1,38 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.InnerClassesInfo;
+
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>InnerClassesInfo</code> objects. Note that there is only a single
+ * implementation of <code>InnerClassesInfo</code>, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface InnerClassesInfoVisitor
+{
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java
new file mode 100644
index 0000000000..c58d11304a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java
@@ -0,0 +1,38 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>LineNumberInfo</code> objects. Note that there is only a single
+ * implementation of <code>LineNumberInfo</code>, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface LineNumberInfoVisitor
+{
+ public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LineNumberRangeFinder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LineNumberRangeFinder.java
new file mode 100644
index 0000000000..4cbbff0d7f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LineNumberRangeFinder.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+
+/**
+ * This LineNumberInfoVisitor remembers the lowest and the highest line
+ * numbers that it finds in all the line numbers that it visits. It
+ * ignores the sources of the line numbers.
+ */
+public class LineNumberRangeFinder
+implements LineNumberInfoVisitor
+{
+ private int lowestLineNumber = Integer.MAX_VALUE;
+ private int highestLineNumber = 0;
+ private boolean hasSource;
+
+
+ /**
+ * Returns the lowest line number that has been visited so far.
+ */
+ public int getLowestLineNumber()
+ {
+ return lowestLineNumber;
+ }
+
+
+ /**
+ * Returns the highest line number that has been visited so far.
+ */
+ public int getHighestLineNumber()
+ {
+ return highestLineNumber;
+ }
+
+
+ /**
+ * Returns whether any of the visited line numbers has a non-null source.
+ */
+ public boolean hasSource()
+ {
+ return hasSource;
+ }
+
+
+ // Implementations for LineNumberInfoVisitor.
+
+ public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
+ {
+ int lineNumber = lineNumberInfo.u2lineNumber;
+
+ // Remember the lowest line number.
+ if (lowestLineNumber > lineNumber)
+ {
+ lowestLineNumber = lineNumber;
+ }
+
+ // Remember the highest line number.
+ if (highestLineNumber < lineNumber)
+ {
+ highestLineNumber = lineNumber;
+ }
+
+ if (lineNumberInfo.getSource() != null)
+ {
+ hasSource = true;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java
new file mode 100644
index 0000000000..523c1922f4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java
@@ -0,0 +1,38 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>LocalVariableInfo</code> objects. Note that there is only a single
+ * implementation of <code>LocalVariableInfo</code>, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface LocalVariableInfoVisitor
+{
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java
new file mode 100644
index 0000000000..870d340788
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java
@@ -0,0 +1,38 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>LocalVariableTypeInfo</code> objects. Note that there is only a single
+ * implementation of <code>LocalVariableTypeInfo</code>, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface LocalVariableTypeInfoVisitor
+{
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java
new file mode 100644
index 0000000000..92698ef9ce
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java
@@ -0,0 +1,446 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
+
+/**
+ * This AttributeVisitor delegates all visits to each AttributeVisitor
+ * in a given list.
+ *
+ * @author Eric Lafortune
+ */
+public class MultiAttributeVisitor implements AttributeVisitor
+{
+ private AttributeVisitor[] attributeVisitors;
+
+
+ public MultiAttributeVisitor()
+ {
+ }
+
+
+ public MultiAttributeVisitor(AttributeVisitor[] attributeVisitors)
+ {
+ this.attributeVisitors = attributeVisitors;
+ }
+
+
+ public void addAttributeVisitor(AttributeVisitor attributeVisitor)
+ {
+ incrementArraySize();
+
+ attributeVisitors[attributeVisitors.length - 1] = attributeVisitor;
+ }
+
+
+ private void incrementArraySize()
+ {
+ if (attributeVisitors == null)
+ {
+ attributeVisitors = new AttributeVisitor[1];
+ }
+ else
+ {
+ AttributeVisitor[] newAttributeVisitors =
+ new AttributeVisitor[attributeVisitors.length + 1];
+ System.arraycopy(attributeVisitors, 0,
+ newAttributeVisitors, 0,
+ attributeVisitors.length);
+ attributeVisitors = newAttributeVisitors;
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitUnknownAttribute(clazz, unknownAttribute);
+ }
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute);
+ }
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitSourceFileAttribute(clazz, sourceFileAttribute);
+ }
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitSourceDirAttribute(clazz, sourceDirAttribute);
+ }
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitInnerClassesAttribute(clazz, innerClassesAttribute);
+ }
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitEnclosingMethodAttribute(clazz, enclosingMethodAttribute);
+ }
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitDeprecatedAttribute(clazz, deprecatedAttribute);
+ }
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitSyntheticAttribute(clazz, syntheticAttribute);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute syntheticAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitSignatureAttribute(clazz, syntheticAttribute);
+ }
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitDeprecatedAttribute(clazz, field, deprecatedAttribute);
+ }
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitSyntheticAttribute(clazz, field, syntheticAttribute);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute syntheticAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitSignatureAttribute(clazz, field, syntheticAttribute);
+ }
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitDeprecatedAttribute(clazz, method, deprecatedAttribute);
+ }
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitSyntheticAttribute(clazz, method, syntheticAttribute);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute syntheticAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitSignatureAttribute(clazz, method, syntheticAttribute);
+ }
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitConstantValueAttribute(clazz, field, constantValueAttribute);
+ }
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitMethodParametersAttribute(clazz, method, methodParametersAttribute);
+ }
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitExceptionsAttribute(clazz, method, exceptionsAttribute);
+ }
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitStackMapAttribute(clazz, method, codeAttribute, stackMapAttribute);
+ }
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitStackMapTableAttribute(clazz, method, codeAttribute, stackMapTableAttribute);
+ }
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitLineNumberTableAttribute(clazz, method, codeAttribute, lineNumberTableAttribute);
+ }
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute);
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeVisibleAnnotationsAttribute(clazz, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeInvisibleAnnotationsAttribute(clazz, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeVisibleAnnotationsAttribute(clazz, field, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeInvisibleAnnotationsAttribute(clazz, field, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeVisibleAnnotationsAttribute(clazz, method, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeInvisibleAnnotationsAttribute(clazz, method, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeVisibleParameterAnnotationsAttribute(clazz, method, runtimeVisibleParameterAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeInvisibleParameterAnnotationsAttribute(clazz, method, runtimeInvisibleParameterAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ for (int index = 0; index < attributeVisitors.length; index++)
+ {
+ attributeVisitors[index].visitAnnotationDefaultAttribute(clazz, method, annotationDefaultAttribute);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java
new file mode 100644
index 0000000000..52bbae16d7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java
@@ -0,0 +1,373 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
+
+/**
+ * This AttributeVisitor delegates its visits another AttributeVisitor, but
+ * only when the visited attribute is not empty. For instance, a local variable
+ * table without variables is empty.
+ *
+ * @author Eric Lafortune
+ */
+public class NonEmptyAttributeFilter
+implements AttributeVisitor
+{
+ private final AttributeVisitor attributeVisitor;
+
+
+ /**
+ * Creates a new NonEmptyAttributeFilter.
+ * @param attributeVisitor the <code>AttributeVisitor</code> to which
+ * visits will be delegated.
+ */
+ public NonEmptyAttributeFilter(AttributeVisitor attributeVisitor)
+ {
+ this.attributeVisitor = attributeVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ attributeVisitor.visitUnknownAttribute(clazz, unknownAttribute);
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (bootstrapMethodsAttribute.u2bootstrapMethodsCount > 0)
+ {
+ attributeVisitor.visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute);
+ }
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ attributeVisitor.visitSourceFileAttribute(clazz, sourceFileAttribute);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ attributeVisitor.visitSourceDirAttribute(clazz, sourceDirAttribute);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ if (innerClassesAttribute.u2classesCount > 0)
+ {
+ attributeVisitor.visitInnerClassesAttribute(clazz, innerClassesAttribute);
+ }
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ attributeVisitor.visitEnclosingMethodAttribute(clazz, enclosingMethodAttribute);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, deprecatedAttribute);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute)
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, field, deprecatedAttribute);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute)
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, method, deprecatedAttribute);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, syntheticAttribute);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute)
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, field, syntheticAttribute);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute)
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, method, syntheticAttribute);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, signatureAttribute);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute signatureAttribute)
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, field, signatureAttribute);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute)
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, method, signatureAttribute);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ attributeVisitor.visitConstantValueAttribute(clazz, field, constantValueAttribute);
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute exceptionsAttribute)
+ {
+ if (exceptionsAttribute.u1parametersCount > 0)
+ {
+ attributeVisitor.visitMethodParametersAttribute(clazz, method, exceptionsAttribute);
+ }
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ if (exceptionsAttribute.u2exceptionIndexTableLength > 0)
+ {
+ attributeVisitor.visitExceptionsAttribute(clazz, method, exceptionsAttribute);
+ }
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ attributeVisitor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ if (stackMapAttribute.u2stackMapFramesCount > 0)
+ {
+ attributeVisitor.visitStackMapAttribute(clazz, method, codeAttribute, stackMapAttribute);
+ }
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ if (stackMapTableAttribute.u2stackMapFramesCount > 0)
+ {
+ attributeVisitor.visitStackMapTableAttribute(clazz, method, codeAttribute, stackMapTableAttribute);
+ }
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ if (lineNumberTableAttribute.u2lineNumberTableLength > 0)
+ {
+ attributeVisitor.visitLineNumberTableAttribute(clazz, method, codeAttribute, lineNumberTableAttribute);
+ }
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ if (localVariableTableAttribute.u2localVariableTableLength > 0)
+ {
+ attributeVisitor.visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute);
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ if (localVariableTypeTableAttribute.u2localVariableTypeTableLength > 0)
+ {
+ attributeVisitor.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, field, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, method, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, field, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, method, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
+ {
+ if (runtimeVisibleParameterAnnotationsAttribute.u1parametersCount > 0)
+ {
+ attributeVisitor.visitRuntimeVisibleParameterAnnotationsAttribute(clazz, method, runtimeVisibleParameterAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
+ {
+ if (runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount > 0)
+ {
+ attributeVisitor.visitRuntimeInvisibleParameterAnnotationsAttribute(clazz, method, runtimeInvisibleParameterAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (runtimeVisibleTypeAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (runtimeVisibleTypeAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (runtimeVisibleTypeAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (runtimeVisibleTypeAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (runtimeInvisibleTypeAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (runtimeInvisibleTypeAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (runtimeInvisibleTypeAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (runtimeInvisibleTypeAnnotationsAttribute.u2annotationsCount > 0)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ attributeVisitor.visitAnnotationDefaultAttribute(clazz, method, annotationDefaultAttribute);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/ParameterInfoVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/ParameterInfoVisitor.java
new file mode 100644
index 0000000000..59a743027d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/ParameterInfoVisitor.java
@@ -0,0 +1,37 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.ParameterInfo;
+
+/**
+ * This interface specifies the method for a visitor of
+ * <code>ParameterInfo</code> objects. Note that there is only a single
+ * implementation of <code>ParameterInfo</code>, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface ParameterInfoVisitor
+{
+ public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
new file mode 100644
index 0000000000..32f29bfdd7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
@@ -0,0 +1,443 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.obfuscate.AttributeShrinker;
+
+/**
+ * This AttributeVisitor delegates its visits to one of two other
+ * AttributeVisitor instances, depending on whether the visited attribute
+ * is strictly required or not.
+ *
+ * Stack map attributes and stack map table attributes are treated as optional.
+ *
+ * @see AttributeShrinker
+ *
+ * @author Eric Lafortune
+ */
+public class RequiredAttributeFilter
+implements AttributeVisitor
+{
+ private final AttributeVisitor requiredAttributeVisitor;
+ private final AttributeVisitor optionalAttributeVisitor;
+
+
+ /**
+ * Creates a new RequiredAttributeFilter for visiting required attributes.
+ * @param requiredAttributeVisitor the visitor that will visit required
+ * attributes.
+ */
+ public RequiredAttributeFilter(AttributeVisitor requiredAttributeVisitor)
+ {
+ this(requiredAttributeVisitor, null);
+ }
+
+
+ /**
+ * Creates a new RequiredAttributeFilter for visiting required and
+ * optional attributes.
+ * @param requiredAttributeVisitor the visitor that will visit required
+ * attributes.
+ * @param optionalAttributeVisitor the visitor that will visit optional
+ * attributes.
+ */
+ public RequiredAttributeFilter(AttributeVisitor requiredAttributeVisitor,
+ AttributeVisitor optionalAttributeVisitor)
+ {
+ this.requiredAttributeVisitor = requiredAttributeVisitor;
+ this.optionalAttributeVisitor = optionalAttributeVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitUnknownAttribute(clazz, unknownAttribute);
+ }
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (requiredAttributeVisitor != null)
+ {
+ requiredAttributeVisitor.visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute);
+ }
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitSourceFileAttribute(clazz, sourceFileAttribute);
+ }
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitSourceDirAttribute(clazz, sourceDirAttribute);
+ }
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitInnerClassesAttribute(clazz, innerClassesAttribute);
+ }
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitEnclosingMethodAttribute(clazz, enclosingMethodAttribute);
+ }
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitDeprecatedAttribute(clazz, deprecatedAttribute);
+ }
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitDeprecatedAttribute(clazz, field, deprecatedAttribute);
+ }
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitDeprecatedAttribute(clazz, method, deprecatedAttribute);
+ }
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitSyntheticAttribute(clazz, syntheticAttribute);
+ }
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitSyntheticAttribute(clazz, field, syntheticAttribute);
+ }
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitSyntheticAttribute(clazz, method, syntheticAttribute);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitSignatureAttribute(clazz, signatureAttribute);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute signatureAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitSignatureAttribute(clazz, field, signatureAttribute);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitSignatureAttribute(clazz, method, signatureAttribute);
+ }
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ if (requiredAttributeVisitor != null)
+ {
+ requiredAttributeVisitor.visitConstantValueAttribute(clazz, field, constantValueAttribute);
+ }
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute exceptionsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitMethodParametersAttribute(clazz, method, exceptionsAttribute);
+ }
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitExceptionsAttribute(clazz, method, exceptionsAttribute);
+ }
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (requiredAttributeVisitor != null)
+ {
+ requiredAttributeVisitor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitStackMapAttribute(clazz, method, codeAttribute, stackMapAttribute);
+ }
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitStackMapTableAttribute(clazz, method, codeAttribute, stackMapTableAttribute);
+ }
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitLineNumberTableAttribute(clazz, method, codeAttribute, lineNumberTableAttribute);
+ }
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute);
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, field, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, method, runtimeVisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, field, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, method, runtimeInvisibleAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeVisibleParameterAnnotationsAttribute(clazz, method, runtimeVisibleParameterAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeInvisibleParameterAnnotationsAttribute(clazz, method, runtimeInvisibleParameterAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeVisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ if (optionalAttributeVisitor != null)
+ {
+ optionalAttributeVisitor.visitAnnotationDefaultAttribute(clazz, method, annotationDefaultAttribute);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/StackSizeComputer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
new file mode 100644
index 0000000000..009666c695
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
@@ -0,0 +1,389 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.attribute.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassPrinter;
+import proguard.util.ArrayUtil;
+
+/**
+ * This AttributeVisitor computes the stack sizes at all instruction offsets
+ * of the code attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class StackSizeComputer
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ExceptionInfoVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = true;
+ //*/
+
+
+ private boolean[] evaluated = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int[] stackSizesBefore = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int[] stackSizesAfter = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+
+ private boolean exitInstructionBlock;
+
+ private int stackSize;
+ private int maxStackSize;
+
+
+ /**
+ * Returns whether the instruction at the given offset is reachable in the
+ * most recently visited code attribute.
+ */
+ public boolean isReachable(int instructionOffset)
+ {
+ return evaluated[instructionOffset];
+ }
+
+
+ /**
+ * Returns the stack size before the given instruction offset of the most
+ * recently visited code attribute.
+ */
+ public int getStackSizeBefore(int instructionOffset)
+ {
+ if (!evaluated[instructionOffset])
+ {
+ throw new IllegalArgumentException("Unknown stack size before unreachable instruction offset ["+instructionOffset+"]");
+ }
+
+ return stackSizesBefore[instructionOffset];
+ }
+
+
+ /**
+ * Returns the stack size after the given instruction offset of the most
+ * recently visited code attribute.
+ */
+ public int getStackSizeAfter(int instructionOffset)
+ {
+ if (!evaluated[instructionOffset])
+ {
+ throw new IllegalArgumentException("Unknown stack size after unreachable instruction offset ["+instructionOffset+"]");
+ }
+
+ return stackSizesAfter[instructionOffset];
+ }
+
+
+ /**
+ * Returns the maximum stack size of the most recently visited code attribute.
+ */
+ public int getMaxStackSize()
+ {
+ return maxStackSize;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ // TODO: Remove this when the code has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while computing stack sizes:");
+ System.err.println(" Class = ["+clazz.getName()+"]");
+ System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+
+ if (DEBUG)
+ {
+ method.accept(clazz, new ClassPrinter());
+ }
+
+ throw ex;
+ }
+ }
+
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (DEBUG)
+ {
+ System.out.println("StackSizeComputer: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ }
+
+ int codeLength = codeAttribute.u4codeLength;
+
+ // Make sure the global arrays are sufficiently large.
+ evaluated = ArrayUtil.ensureArraySize(evaluated, codeLength, false);
+ stackSizesBefore = ArrayUtil.ensureArraySize(stackSizesBefore, codeLength, 0);
+ stackSizesAfter = ArrayUtil.ensureArraySize(stackSizesAfter, codeLength, 0);
+
+ // The initial stack is always empty.
+ stackSize = 0;
+ maxStackSize = 0;
+
+ // Evaluate the instruction block starting at the entry point of the method.
+ evaluateInstructionBlock(clazz, method, codeAttribute, 0);
+
+ // Evaluate the exception handlers.
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ byte opcode = simpleInstruction.opcode;
+
+ // Some simple instructions exit from the current instruction block.
+ exitInstructionBlock =
+ opcode == InstructionConstants.OP_IRETURN ||
+ opcode == InstructionConstants.OP_LRETURN ||
+ opcode == InstructionConstants.OP_FRETURN ||
+ opcode == InstructionConstants.OP_DRETURN ||
+ opcode == InstructionConstants.OP_ARETURN ||
+ opcode == InstructionConstants.OP_RETURN ||
+ opcode == InstructionConstants.OP_ATHROW;
+ }
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ // Constant pool instructions never end the current instruction block.
+ exitInstructionBlock = false;
+ }
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ byte opcode = variableInstruction.opcode;
+
+ // The ret instruction end the current instruction block.
+ exitInstructionBlock =
+ opcode == InstructionConstants.OP_RET;
+ }
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ byte opcode = branchInstruction.opcode;
+
+ // Evaluate the target instruction blocks.
+ evaluateInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ offset +
+ branchInstruction.branchOffset);
+
+ // Evaluate the instructions after a subroutine branch.
+ if (opcode == InstructionConstants.OP_JSR ||
+ opcode == InstructionConstants.OP_JSR_W)
+ {
+ // We assume subroutine calls (jsr and jsr_w instructions) don't
+ // change the stack, other than popping the return value.
+ stackSize -= 1;
+
+ evaluateInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ offset + branchInstruction.length(offset));
+ }
+
+ // Some branch instructions always end the current instruction block.
+ exitInstructionBlock =
+ opcode == InstructionConstants.OP_GOTO ||
+ opcode == InstructionConstants.OP_GOTO_W ||
+ opcode == InstructionConstants.OP_JSR ||
+ opcode == InstructionConstants.OP_JSR_W;
+ }
+
+
+ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ {
+ // Evaluate the target instruction blocks.
+
+ // Loop over all jump offsets.
+ int[] jumpOffsets = switchInstruction.jumpOffsets;
+
+ for (int index = 0; index < jumpOffsets.length; index++)
+ {
+ // Evaluate the jump instruction block.
+ evaluateInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ offset + jumpOffsets[index]);
+ }
+
+ // Also evaluate the default instruction block.
+ evaluateInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ offset + switchInstruction.defaultOffset);
+
+ // The switch instruction always ends the current instruction block.
+ exitInstructionBlock = true;
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ if (DEBUG)
+ {
+ System.out.println("Exception:");
+ }
+
+ // The stack size when entering the exception handler is always 1.
+ stackSize = 1;
+
+ // Evaluate the instruction block starting at the entry point of the
+ // exception handler.
+ evaluateInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ exceptionInfo.u2handlerPC);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Evaluates a block of instructions that hasn't been handled before,
+ * starting at the given offset and ending at a branch instruction, a return
+ * instruction, or a throw instruction. Branch instructions are handled
+ * recursively.
+ */
+ private void evaluateInstructionBlock(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int instructionOffset)
+ {
+ if (DEBUG)
+ {
+ if (evaluated[instructionOffset])
+ {
+ System.out.println("-- (instruction block at "+instructionOffset+" already evaluated)");
+ }
+ else
+ {
+ System.out.println("-- instruction block:");
+ }
+ }
+
+ // Remember the initial stack size.
+ int initialStackSize = stackSize;
+
+ // Remember the maximum stack size.
+ if (maxStackSize < stackSize)
+ {
+ maxStackSize = stackSize;
+ }
+
+ // Evaluate any instructions that haven't been evaluated before.
+ while (!evaluated[instructionOffset])
+ {
+ // Mark the instruction as evaluated.
+ evaluated[instructionOffset] = true;
+ stackSizesBefore[instructionOffset] = stackSize;
+
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ instructionOffset);
+
+ if (DEBUG)
+ {
+ int stackPushCount = instruction.stackPushCount(clazz);
+ int stackPopCount = instruction.stackPopCount(clazz);
+ System.out.println("["+instructionOffset+"]: "+
+ stackSize+" - "+
+ stackPopCount+" + "+
+ stackPushCount+" = "+
+ (stackSize+stackPushCount-stackPopCount)+": "+
+ instruction.toString(instructionOffset));
+ }
+
+ // Compute the instruction's effect on the stack size.
+ stackSize -= instruction.stackPopCount(clazz);
+
+ if (stackSize < 0)
+ {
+ throw new IllegalArgumentException("Stack size becomes negative after instruction "+
+ instruction.toString(instructionOffset)+" in ["+
+ clazz.getName()+"."+
+ method.getName(clazz)+
+ method.getDescriptor(clazz)+"]");
+ }
+
+ stackSize += instruction.stackPushCount(clazz);
+ stackSizesAfter[instructionOffset] = stackSize;
+
+ // Remember the maximum stack size.
+ if (maxStackSize < stackSize)
+ {
+ maxStackSize = stackSize;
+ }
+
+ // Remember the next instruction offset.
+ int nextInstructionOffset = instructionOffset +
+ instruction.length(instructionOffset);
+
+ // Visit the instruction, in order to handle branches.
+ instruction.accept(clazz, method, codeAttribute, instructionOffset, this);
+
+ // Stop evaluating after a branch.
+ if (exitInstructionBlock)
+ {
+ break;
+ }
+
+ // Continue with the next instruction.
+ instructionOffset = nextInstructionOffset;
+
+ if (DEBUG)
+ {
+ if (evaluated[instructionOffset])
+ {
+ System.out.println("-- (instruction at "+instructionOffset+" already evaluated)");
+ }
+ }
+ }
+
+ // Restore the stack size for possible subsequent instruction blocks.
+ this.stackSize = initialStackSize;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/package.html
new file mode 100644
index 0000000000..056244af62
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/attribute/visitor/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains visitors for attributes and their components.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/ClassConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/ClassConstant.java
new file mode 100644
index 0000000000..b4993743d2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/ClassConstant.java
@@ -0,0 +1,105 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This Constant represents a class constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassConstant extends Constant
+{
+ public int u2nameIndex;
+
+ /**
+ * An extra field pointing to the referenced Clazz object.
+ * This field is filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}</code>.
+ */
+ public Clazz referencedClass;
+
+ /**
+ * An extra field pointing to the java.lang.Class Clazz object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>..
+ */
+ public Clazz javaLangClassClass;
+
+
+ /**
+ * Creates an uninitialized ClassConstant.
+ */
+ public ClassConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new ClassConstant with the given name index.
+ * @param u2nameIndex the index of the name in the constant pool.
+ * @param referencedClass the referenced class.
+ */
+ public ClassConstant(int u2nameIndex,
+ Clazz referencedClass)
+ {
+ this.u2nameIndex = u2nameIndex;
+ this.referencedClass = referencedClass;
+ }
+
+
+ /**
+ * Returns the name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getString(u2nameIndex);
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_Class;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitClassConstant(clazz, this);
+ }
+
+
+ /**
+ * Lets the referenced class accept the given visitor.
+ */
+ public void referencedClassAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/Constant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/Constant.java
new file mode 100644
index 0000000000..86acf9d368
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/Constant.java
@@ -0,0 +1,68 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This abstract class represents an entry in the ConstantPool. Specific types
+ * of entries are subclassed from it.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class Constant implements VisitorAccepter
+{
+ //public int u1tag;
+ //public byte info[];
+
+ /**
+ * An extra field in which visitors can store information.
+ */
+ public Object visitorInfo;
+
+
+ // Abstract methods to be implemented by extensions.
+
+ /**
+ * Returns the constant pool info tag that specifies the entry type.
+ */
+ public abstract int getTag();
+
+
+ /**
+ * Accepts the given visitor.
+ */
+ public abstract void accept(Clazz clazz, ConstantVisitor constantVisitor);
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return visitorInfo;
+ }
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ this.visitorInfo = visitorInfo;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/DoubleConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/DoubleConstant.java
new file mode 100644
index 0000000000..a9eca1eef7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/DoubleConstant.java
@@ -0,0 +1,82 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a double constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class DoubleConstant extends Constant
+{
+ public double f8value;
+
+
+ /**
+ * Creates an uninitialized DoubleConstant.
+ */
+ public DoubleConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new DoubleConstant with the given double value.
+ */
+ public DoubleConstant(double value)
+ {
+ f8value = value;
+ }
+
+
+ /**
+ * Returns the double value of this DoubleConstant.
+ */
+ public double getValue()
+ {
+ return f8value;
+ }
+
+
+ /**
+ * Sets the double value of this DoubleConstant.
+ */
+ public void setValue(double value)
+ {
+ f8value = value;
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_Double;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitDoubleConstant(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/FieldrefConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/FieldrefConstant.java
new file mode 100644
index 0000000000..6cc30a3839
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/FieldrefConstant.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a field reference constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class FieldrefConstant extends RefConstant
+{
+ /**
+ * Creates an uninitialized FieldrefConstant.
+ */
+ public FieldrefConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new FieldrefConstant with the given name and type indices.
+ * @param u2classIndex the index of the class in the constant pool.
+ * @param u2nameAndTypeIndex the index of the name and type entry in the constant pool.
+ * @param referencedClass the referenced class.
+ * @param referencedMember the referenced member info.
+ */
+ public FieldrefConstant(int u2classIndex,
+ int u2nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ this.u2classIndex = u2classIndex;
+ this.u2nameAndTypeIndex = u2nameAndTypeIndex;
+ this.referencedClass = referencedClass;
+ this.referencedMember = referencedMember;
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_Fieldref;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitFieldrefConstant(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/FloatConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/FloatConstant.java
new file mode 100644
index 0000000000..8dbe933ea3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/FloatConstant.java
@@ -0,0 +1,82 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a float constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class FloatConstant extends Constant
+{
+ public float f4value;
+
+
+ /**
+ * Creates an uninitialized FloatConstant.
+ */
+ public FloatConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new FloatConstant with the given float value.
+ */
+ public FloatConstant(float value)
+ {
+ f4value = value;
+ }
+
+
+ /**
+ * Returns the float value of this FloatConstant.
+ */
+ public float getValue()
+ {
+ return f4value;
+ }
+
+
+ /**
+ * Sets the float value of this FloatConstant.
+ */
+ public void setValue(float value)
+ {
+ f4value = value;
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_Float;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitFloatConstant(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/IntegerConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/IntegerConstant.java
new file mode 100644
index 0000000000..9c09149c66
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/IntegerConstant.java
@@ -0,0 +1,82 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a integer constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class IntegerConstant extends Constant
+{
+ public int u4value;
+
+
+ /**
+ * Creates an uninitialized IntegerConstant.
+ */
+ public IntegerConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new IntegerConstant with the given integer value.
+ */
+ public IntegerConstant(int value)
+ {
+ u4value = value;
+ }
+
+
+ /**
+ * Returns the integer value of this IntegerConstant.
+ */
+ public int getValue()
+ {
+ return u4value;
+ }
+
+
+ /**
+ * Sets the integer value of this IntegerConstant.
+ */
+ public void setValue(int value)
+ {
+ u4value = value;
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_Integer;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitIntegerConstant(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/InterfaceMethodrefConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/InterfaceMethodrefConstant.java
new file mode 100644
index 0000000000..0436ffeb7e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/InterfaceMethodrefConstant.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a interface method reference constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class InterfaceMethodrefConstant extends RefConstant
+{
+ /**
+ * Creates an uninitialized InterfaceMethodrefConstant.
+ */
+ public InterfaceMethodrefConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new InterfaceMethodrefConstant with the given name and type indices.
+ * @param u2classIndex the index of the class in the constant pool.
+ * @param u2nameAndTypeIndex the index of the name and type entry in the constant pool.
+ * @param referencedClass the referenced class.
+ * @param referencedMember the referenced member info.
+ */
+ public InterfaceMethodrefConstant(int u2classIndex,
+ int u2nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ this.u2classIndex = u2classIndex;
+ this.u2nameAndTypeIndex = u2nameAndTypeIndex;
+ this.referencedClass = referencedClass;
+ this.referencedMember = referencedMember;
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_InterfaceMethodref;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitInterfaceMethodrefConstant(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/InvokeDynamicConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/InvokeDynamicConstant.java
new file mode 100755
index 0000000000..26c46d3a8b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/InvokeDynamicConstant.java
@@ -0,0 +1,148 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This Constant represents an invoke dynamic constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class InvokeDynamicConstant extends Constant
+{
+ public int u2bootstrapMethodAttributeIndex;
+ public int u2nameAndTypeIndex;
+
+ /**
+ * An extra field pointing to the Clazz objects referenced in the
+ * descriptor string. This field is filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}</code>.
+ * References to primitive types are ignored.
+ */
+ public Clazz[] referencedClasses;
+
+
+ /**
+ * Creates an uninitialized InvokeDynamicConstant.
+ */
+ public InvokeDynamicConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new InvokeDynamicConstant with the given bootstrap method
+ * and name-and-type indices.
+ * @param u2bootstrapMethodAttributeIndex the index of the bootstrap method
+ * entry in the bootstrap methods
+ * attribute.
+ * @param u2nameAndTypeIndex the index of the name and type
+ * entry in the constant pool.
+ * @param referencedClasses the classes referenced by the
+ * type.
+ */
+ public InvokeDynamicConstant(int u2bootstrapMethodAttributeIndex,
+ int u2nameAndTypeIndex,
+ Clazz[] referencedClasses)
+ {
+ this.u2bootstrapMethodAttributeIndex = u2bootstrapMethodAttributeIndex;
+ this.u2nameAndTypeIndex = u2nameAndTypeIndex;
+ this.referencedClasses = referencedClasses;
+ }
+
+
+ /**
+ * Returns the index of the bootstrap method in the bootstrap methods
+ * attribute of the class.
+ */
+ public int getBootstrapMethodAttributeIndex()
+ {
+ return u2bootstrapMethodAttributeIndex;
+ }
+
+ /**
+ * Returns the name-and-type index.
+ */
+ public int getNameAndTypeIndex()
+ {
+ return u2nameAndTypeIndex;
+ }
+
+ /**
+ * Returns the method name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getName(u2nameAndTypeIndex);
+ }
+
+ /**
+ * Returns the method type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getType(u2nameAndTypeIndex);
+ }
+
+
+ /**
+ * Lets the Clazz objects referenced in the descriptor string
+ * accept the given visitor.
+ */
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ if (referencedClasses[index] != null)
+ {
+ referencedClasses[index].accept(classVisitor);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Lets the bootstrap method handle constant accept the given visitor.
+ */
+ public void bootstrapMethodHandleAccept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ new BootstrapMethodHandleTraveler(constantVisitor).visitInvokeDynamicConstant(clazz, this);
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_InvokeDynamic;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitInvokeDynamicConstant(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/LongConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/LongConstant.java
new file mode 100644
index 0000000000..977d013ef6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/LongConstant.java
@@ -0,0 +1,82 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a long constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class LongConstant extends Constant
+{
+ public long u8value;
+
+
+ /**
+ * Creates an uninitialized LongConstant.
+ */
+ public LongConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new LongConstant with the given long value.
+ */
+ public LongConstant(long value)
+ {
+ u8value = value;
+ }
+
+
+ /**
+ * Returns the long value of this LongConstant.
+ */
+ public long getValue()
+ {
+ return u8value;
+ }
+
+
+ /**
+ * Sets the long value of this LongConstant.
+ */
+ public void setValue(long value)
+ {
+ u8value = value;
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_Long;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitLongConstant(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodHandleConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodHandleConstant.java
new file mode 100755
index 0000000000..950136a321
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodHandleConstant.java
@@ -0,0 +1,132 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a method handle constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodHandleConstant extends Constant
+{
+ public int u1referenceKind;
+ public int u2referenceIndex;
+
+
+ /**
+ * An extra field pointing to the java.lang.invoke.MethodHandle Clazz object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ */
+ public Clazz javaLangInvokeMethodHandleClass;
+
+
+ /**
+ * Creates an uninitialized MethodHandleConstant.
+ */
+ public MethodHandleConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new MethodHandleConstant with the given type and method ref
+ * index.
+ * @param u1referenceKind the reference kind.
+ * @param u2referenceIndex the index of the field ref constant, interface
+ * method ref constant, or method ref constant in
+ * the constant pool.
+ */
+ public MethodHandleConstant(int u1referenceKind, int u2referenceIndex)
+ {
+ this.u1referenceKind = u1referenceKind;
+ this.u2referenceIndex = u2referenceIndex;
+ }
+
+
+ /**
+ * Returns the kind of reference to which this constant is pointing.
+ * @return One of
+ * {@link ClassConstants#REF_getField },
+ * {@link ClassConstants#REF_getStatic },
+ * {@link ClassConstants#REF_putField },
+ * {@link ClassConstants#REF_putStatic },
+ * {@link ClassConstants#REF_invokeVirtual },
+ * {@link ClassConstants#REF_invokeStatic },
+ * {@link ClassConstants#REF_invokeSpecial },
+ * {@link ClassConstants#REF_newInvokeSpecial}, or
+ * {@link ClassConstants#REF_invokeInterface }.
+ */
+ public int getReferenceKind()
+ {
+ return u1referenceKind;
+ }
+
+ /**
+ * Returns the field ref, interface method ref, or method ref index.
+ */
+ public int getReferenceIndex()
+ {
+ return u2referenceIndex;
+ }
+
+
+ /**
+ * Returns the class name.
+ */
+ public String getClassName(Clazz clazz)
+ {
+ return clazz.getRefClassName(u2referenceIndex);
+ }
+
+ /**
+ * Returns the method/field name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getRefName(u2referenceIndex);
+ }
+
+ /**
+ * Returns the type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getRefType(u2referenceIndex);
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_MethodHandle;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitMethodHandleConstant(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodTypeConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodTypeConstant.java
new file mode 100644
index 0000000000..eba5d1166c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodTypeConstant.java
@@ -0,0 +1,125 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This Constant represents a method handle constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodTypeConstant extends Constant
+{
+ public int u2descriptorIndex;
+
+
+ /**
+ * An extra field pointing to the java.lang.invoke.MethodType Clazz object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>..
+ */
+ public Clazz javaLangInvokeMethodTypeClass;
+
+
+ /**
+ * An extra field pointing to the Clazz objects referenced in the
+ * descriptor string. This field is filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer ClassReferenceInitializer}</code>.
+ * References to primitive types are ignored.
+ */
+ public Clazz[] referencedClasses;
+
+
+ /**
+ * Creates an uninitialized MethodTypeConstant.
+ */
+ public MethodTypeConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new MethodTypeConstant with the given descriptor index.
+ * @param u2descriptorIndex the index of the descriptor in the constant
+ * pool.
+ * @param referencedClasses the classes referenced by the descriptor.
+ */
+ public MethodTypeConstant(int u2descriptorIndex,
+ Clazz[] referencedClasses)
+ {
+ this.u2descriptorIndex = u2descriptorIndex;
+ this.referencedClasses = referencedClasses;
+ }
+
+
+ /**
+ * Returns the descriptor index.
+ */
+ public int getDescriptorIndex()
+ {
+ return u2descriptorIndex;
+ }
+
+
+ /**
+ * Returns the type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getString(u2descriptorIndex);
+ }
+
+
+ /**
+ * Lets the Clazz objects referenced in the descriptor string
+ * accept the given visitor.
+ */
+ public void referencedClassesAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClasses != null)
+ {
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ if (referencedClasses[index] != null)
+ {
+ referencedClasses[index].accept(classVisitor);
+ }
+ }
+ }
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_MethodType;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitMethodTypeConstant(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodrefConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodrefConstant.java
new file mode 100644
index 0000000000..a3a0b7ca3e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/MethodrefConstant.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a method reference constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodrefConstant extends RefConstant
+{
+ /**
+ * Creates an uninitialized MethodrefConstant.
+ */
+ public MethodrefConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new MethodrefConstant with the given name and type indices.
+ * @param u2classIndex the index of the class in the constant pool.
+ * @param u2nameAndTypeIndex the index of the name and type entry in the constant pool.
+ * @param referencedClass the referenced class.
+ * @param referencedMember the referenced member info.
+ */
+ public MethodrefConstant(int u2classIndex,
+ int u2nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ this.u2classIndex = u2classIndex;
+ this.u2nameAndTypeIndex = u2nameAndTypeIndex;
+ this.referencedClass = referencedClass;
+ this.referencedMember = referencedMember;
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_Methodref;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitMethodrefConstant(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/NameAndTypeConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/NameAndTypeConstant.java
new file mode 100644
index 0000000000..f52c3ebcd2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/NameAndTypeConstant.java
@@ -0,0 +1,119 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This Constant represents a name and type constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class NameAndTypeConstant extends Constant
+{
+ public int u2nameIndex;
+ public int u2descriptorIndex;
+
+
+ /**
+ * Creates an uninitialized NameAndTypeConstant.
+ */
+ public NameAndTypeConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new NameAndTypeConstant with the given name and type indices.
+ * @param u2nameIndex the index of the name in the constant pool.
+ * @param u2descriptorIndex the index of the descriptor in the constant
+ * pool.
+ */
+ public NameAndTypeConstant(int u2nameIndex,
+ int u2descriptorIndex)
+ {
+ this.u2nameIndex = u2nameIndex;
+ this.u2descriptorIndex = u2descriptorIndex;
+ }
+
+
+ /**
+ * Returns the name index.
+ */
+ protected int getNameIndex()
+ {
+ return u2nameIndex;
+ }
+
+ /**
+ * Sets the name index.
+ */
+ protected void setNameIndex(int index)
+ {
+ u2nameIndex = index;
+ }
+
+ /**
+ * Returns the descriptor index.
+ */
+ protected int getDescriptorIndex()
+ {
+ return u2descriptorIndex;
+ }
+
+ /**
+ * Sets the descriptor index.
+ */
+ protected void setDescriptorIndex(int index)
+ {
+ u2descriptorIndex = index;
+ }
+
+ /**
+ * Returns the name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getString(u2nameIndex);
+ }
+
+ /**
+ * Returns the type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getString(u2descriptorIndex);
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_NameAndType;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitNameAndTypeConstant(clazz, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/RefConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/RefConstant.java
new file mode 100644
index 0000000000..11c59348e9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/RefConstant.java
@@ -0,0 +1,130 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This Constant represents a ref constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class RefConstant extends Constant
+{
+ public int u2classIndex;
+ public int u2nameAndTypeIndex;
+
+ /**
+ * An extra field pointing to the referenced Clazz object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ */
+ public Clazz referencedClass;
+
+ /**
+ * An extra field optionally pointing to the referenced Member object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>.
+ */
+ public Member referencedMember;
+
+
+ protected RefConstant()
+ {
+ }
+
+
+ /**
+ * Returns the class index.
+ */
+ public int getClassIndex()
+ {
+ return u2classIndex;
+ }
+
+ /**
+ * Returns the name-and-type index.
+ */
+ public int getNameAndTypeIndex()
+ {
+ return u2nameAndTypeIndex;
+ }
+
+ /**
+ * Sets the name-and-type index.
+ */
+ public void setNameAndTypeIndex(int index)
+ {
+ u2nameAndTypeIndex = index;
+ }
+
+ /**
+ * Returns the class name.
+ */
+ public String getClassName(Clazz clazz)
+ {
+ return clazz.getClassName(u2classIndex);
+ }
+
+ /**
+ * Returns the method/field name.
+ */
+ public String getName(Clazz clazz)
+ {
+ return clazz.getName(u2nameAndTypeIndex);
+ }
+
+ /**
+ * Returns the type.
+ */
+ public String getType(Clazz clazz)
+ {
+ return clazz.getType(u2nameAndTypeIndex);
+ }
+
+
+ /**
+ * Lets the referenced class accept the given visitor.
+ */
+ public void referencedClassAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+
+
+ /**
+ * Lets the referenced class member accept the given visitor.
+ */
+ public void referencedMemberAccept(MemberVisitor memberVisitor)
+ {
+ if (referencedMember != null)
+ {
+ referencedMember.accept(referencedClass,
+ memberVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/StringConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/StringConstant.java
new file mode 100644
index 0000000000..42509a1cd7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/StringConstant.java
@@ -0,0 +1,135 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This Constant represents a string constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class StringConstant extends Constant
+{
+ public int u2stringIndex;
+
+ /**
+ * An extra field pointing to the referenced Clazz object, if this
+ * string is being used in Class.forName(), .class, or
+ * Class.getDeclaredField/Method constructs.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.DynamicClassReferenceInitializer
+ * DynamicClassReferenceInitializer}</code> or by the <code>{@link
+ * proguard.classfile.util.DynamicMemberReferenceInitializer
+ * DynamicMemberReferenceInitializer}</code>.
+ */
+ public Clazz referencedClass;
+
+ /**
+ * An extra field pointing to the referenced Member object, if this
+ * string is being used in Class.getDeclaredField/Method constructs.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.DynamicMemberReferenceInitializer
+ * DynamicMemberReferenceInitializer}</code>.
+ */
+ public Member referencedMember;
+
+ /**
+ * An extra field pointing to the java.lang.String Clazz object.
+ * This field is typically filled out by the <code>{@link
+ * proguard.classfile.util.ClassReferenceInitializer
+ * ClassReferenceInitializer}</code>..
+ */
+ public Clazz javaLangStringClass;
+
+
+ /**
+ * Creates an uninitialized StringConstant.
+ */
+ public StringConstant()
+ {
+ }
+
+
+ /**
+ * Creates a new StringConstant with the given string index.
+ * @param u2stringIndex the index of the string in the constant pool.
+ * @param referencedClass the referenced class, if any.
+ * @param referenceMember the referenced class member, if any.
+ */
+ public StringConstant(int u2stringIndex,
+ Clazz referencedClass,
+ Member referenceMember)
+ {
+ this.u2stringIndex = u2stringIndex;
+ this.referencedClass = referencedClass;
+ this.referencedMember = referenceMember;
+ }
+
+
+ /**
+ * Returns the string value.
+ */
+ public String getString(Clazz clazz)
+ {
+ return clazz.getString(u2stringIndex);
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_String;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitStringConstant(clazz, this);
+ }
+
+
+ /**
+ * Lets the referenced class accept the given visitor.
+ */
+ public void referencedClassAccept(ClassVisitor classVisitor)
+ {
+ if (referencedClass != null &&
+ referencedMember == null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+
+
+ /**
+ * Lets the referenced member accept the given visitor.
+ */
+ public void referencedMemberAccept(MemberVisitor memberVisitor)
+ {
+ if (referencedMember != null)
+ {
+ referencedMember.accept(referencedClass, memberVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/Utf8Constant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/Utf8Constant.java
new file mode 100644
index 0000000000..8ef9d5ecbf
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/Utf8Constant.java
@@ -0,0 +1,285 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * This Constant represents a UTF-8 constant in the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class Utf8Constant extends Constant
+{
+ private static final char TWO_BYTE_LIMIT = 0x80;
+ private static final int TWO_BYTE_CONSTANT1 = 0xc0;
+ private static final int TWO_BYTE_CONSTANT2 = 0x80;
+ private static final int TWO_BYTE_SHIFT1 = 6;
+ private static final int TWO_BYTE_MASK1 = 0x1f;
+ private static final int TWO_BYTE_MASK2 = 0x3f;
+
+ private static final char THREE_BYTE_LIMIT = 0x800;
+ private static final int THREE_BYTE_CONSTANT1 = 0xe0;
+ private static final int THREE_BYTE_CONSTANT2 = 0x80;
+ private static final int THREE_BYTE_CONSTANT3 = 0x80;
+ private static final int THREE_BYTE_SHIFT1 = 12;
+ private static final int THREE_BYTE_SHIFT2 = 6;
+ private static final int THREE_BYTE_MASK1 = 0x0f;
+ private static final int THREE_BYTE_MASK2 = 0x3f;
+ private static final int THREE_BYTE_MASK3 = 0x3f;
+
+
+ // There are a lot of Utf8Constant objects, so we're optimising their storage.
+ // Initially, we're storing the UTF-8 bytes in a byte array.
+ // When the corresponding String is requested, we ditch the array and just
+ // store the String.
+
+ //private int u2length;
+ private byte[] bytes;
+
+ private String string;
+
+
+ /**
+ * Creates an uninitialized Utf8Constant.
+ *
+ */
+ public Utf8Constant()
+ {
+ }
+
+
+ /**
+ * Creates a Utf8Constant containing the given string.
+ */
+ public Utf8Constant(String string)
+ {
+ this.bytes = null;
+ this.string = string;
+ }
+
+
+ /**
+ * Initializes the UTF-8 data with an array of bytes.
+ */
+ public void setBytes(byte[] bytes)
+ {
+ this.bytes = bytes;
+ this.string = null;
+ }
+
+
+ /**
+ * Returns the UTF-8 data as an array of bytes.
+ */
+ public byte[] getBytes()
+ {
+ try
+ {
+ switchToByteArrayRepresentation();
+ }
+ catch (UnsupportedEncodingException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+
+ return bytes;
+ }
+
+
+ /**
+ * Initializes the UTF-8 data with a String.
+ */
+ public void setString(String utf8String)
+ {
+ this.bytes = null;
+ this.string = utf8String;
+ }
+
+
+ /**
+ * Returns the UTF-8 data as a String.
+ */
+ public String getString()
+ {
+ try
+ {
+ switchToStringRepresentation();
+ }
+ catch (UnsupportedEncodingException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+
+ return string;
+ }
+
+
+ // Implementations for Constant.
+
+ public int getTag()
+ {
+ return ClassConstants.CONSTANT_Utf8;
+ }
+
+ public void accept(Clazz clazz, ConstantVisitor constantVisitor)
+ {
+ constantVisitor.visitUtf8Constant(clazz, this);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Switches to a byte array representation of the UTF-8 data.
+ */
+ private void switchToByteArrayRepresentation() throws UnsupportedEncodingException
+ {
+ if (bytes == null)
+ {
+ bytes = getByteArrayRepresentation(string);
+ string = null;
+ }
+ }
+
+
+ /**
+ * Switches to a String representation of the UTF-8 data.
+ */
+ private void switchToStringRepresentation() throws UnsupportedEncodingException
+ {
+ if (string == null)
+ {
+ string = getStringRepresentation(bytes);
+ bytes = null;
+ }
+ }
+
+
+ /**
+ * Returns the modified UTF-8 byte array representation of the given string.
+ */
+ private byte[] getByteArrayRepresentation(String string) throws UnsupportedEncodingException
+ {
+ // We're computing the byte array ourselves, because the implementation
+ // of String.getBytes("UTF-8") has a bug, at least up to JRE 1.4.2.
+ // Also note the special treatment of the 0 character.
+
+ // Compute the byte array length.
+ int byteLength = 0;
+ int stringLength = string.length();
+ for (int stringIndex = 0; stringIndex < stringLength; stringIndex++)
+ {
+ char c = string.charAt(stringIndex);
+
+ // The character is represented by one, two, or three bytes.
+ byteLength += c == 0 ? 2 :
+ c < TWO_BYTE_LIMIT ? 1 :
+ c < THREE_BYTE_LIMIT ? 2 :
+ 3;
+ }
+
+ // Allocate the byte array with the computed length.
+ byte[] bytes = new byte[byteLength];
+
+ // Fill out the array.
+ int byteIndex = 0;
+ for (int stringIndex = 0; stringIndex < stringLength; stringIndex++)
+ {
+ char c = string.charAt(stringIndex);
+ if (c == 0)
+ {
+ // The 0 character gets a two-byte representation in classes.
+ bytes[byteIndex++] = (byte)TWO_BYTE_CONSTANT1;
+ bytes[byteIndex++] = (byte)TWO_BYTE_CONSTANT2;
+ }
+ else if (c < TWO_BYTE_LIMIT)
+ {
+ // The character is represented by a single byte.
+ bytes[byteIndex++] = (byte)c;
+ }
+ else if (c < THREE_BYTE_LIMIT)
+ {
+ // The character is represented by two bytes.
+ bytes[byteIndex++] = (byte)(TWO_BYTE_CONSTANT1 | ((c >>> TWO_BYTE_SHIFT1) & TWO_BYTE_MASK1));
+ bytes[byteIndex++] = (byte)(TWO_BYTE_CONSTANT2 | ( c & TWO_BYTE_MASK2));
+ }
+ else
+ {
+ // The character is represented by three bytes.
+ bytes[byteIndex++] = (byte)(THREE_BYTE_CONSTANT1 | ((c >>> THREE_BYTE_SHIFT1) & THREE_BYTE_MASK1));
+ bytes[byteIndex++] = (byte)(THREE_BYTE_CONSTANT2 | ((c >>> THREE_BYTE_SHIFT2) & THREE_BYTE_MASK2));
+ bytes[byteIndex++] = (byte)(THREE_BYTE_CONSTANT3 | ( c & THREE_BYTE_MASK3));
+ }
+ }
+
+ return bytes;
+ }
+
+
+ /**
+ * Returns the String representation of the given modified UTF-8 byte array.
+ */
+ private String getStringRepresentation(byte[] bytes) throws UnsupportedEncodingException
+ {
+ // We're computing the string ourselves, because the implementation
+ // of "new String(bytes)" doesn't honor the special treatment of
+ // the 0 character in JRE 1.6_u11.
+
+ // Allocate the byte array with the computed length.
+ char[] chars = new char[bytes.length];
+
+ // Fill out the array.
+ int charIndex = 0;
+ int byteIndex = 0;
+ while (byteIndex < bytes.length)
+ {
+
+ int b = bytes[byteIndex++] & 0xff;
+
+ // Depending on the flag bits in the first byte, the character
+ // is represented by a single byte, by two bytes, or by three
+ // bytes. We're not checking the redundant flag bits in the
+ // second byte and the third byte.
+ try
+ {
+ chars[charIndex++] =
+ (char)(b < TWO_BYTE_CONSTANT1 ? b :
+
+ b < THREE_BYTE_CONSTANT1 ? ((b & TWO_BYTE_MASK1) << TWO_BYTE_SHIFT1) |
+ ((bytes[byteIndex++] & TWO_BYTE_MASK2) ) :
+
+ ((b & THREE_BYTE_MASK1) << THREE_BYTE_SHIFT1) |
+ ((bytes[byteIndex++] & THREE_BYTE_MASK2) << THREE_BYTE_SHIFT2) |
+ ((bytes[byteIndex++] & THREE_BYTE_MASK3) ));
+ }
+ catch (ArrayIndexOutOfBoundsException e)
+ {
+ throw new UnsupportedEncodingException("Missing UTF-8 bytes after initial byte [0x"+Integer.toHexString(b)+"] in string ["+new String(chars, 0, charIndex)+"]");
+ }
+ }
+
+ return new String(chars, 0, charIndex);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/AllConstantVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
new file mode 100644
index 0000000000..90d4124aa0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
@@ -0,0 +1,53 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+
+/**
+ * This ClassVisitor lets a given ConstantVisitor visit all constant pool
+ * entries of the program classes it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllConstantVisitor implements ClassVisitor
+{
+ private final ConstantVisitor constantVisitor;
+
+
+ public AllConstantVisitor(ConstantVisitor constantVisitor)
+ {
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.constantPoolEntriesAccept(constantVisitor);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/BootstrapMethodArgumentVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/BootstrapMethodArgumentVisitor.java
new file mode 100644
index 0000000000..8bbb34c549
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/BootstrapMethodArgumentVisitor.java
@@ -0,0 +1,56 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.BootstrapMethodInfo;
+import proguard.classfile.attribute.visitor.BootstrapMethodInfoVisitor;
+
+/**
+ * This BootstrapMethodInfoVisitor lets a given ConstantVisitor visit all
+ * constant pool entries of the bootstrap methods it visits.
+ *
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodArgumentVisitor
+implements BootstrapMethodInfoVisitor
+{
+ private ConstantVisitor constantVisitor;
+
+ /**
+ * Creates a new BootstrapMethodArgumentVisitor that will delegate to the
+ * given constant visitor.
+ */
+ public BootstrapMethodArgumentVisitor(ConstantVisitor constantVisitor)
+ {
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ // Check bootstrap method.
+ bootstrapMethodInfo.methodArgumentsAccept(clazz, constantVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java
new file mode 100644
index 0000000000..032dafb972
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java
@@ -0,0 +1,96 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This ConstantVisitor and BootstrapMethodInfoVisitor travels from any invoke
+ * dynamic constants or bootstrap method info entries that it visits to their
+ * bootstrap method handle constants, and applies a given constant visitor.
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodHandleTraveler
+extends SimplifiedVisitor
+implements ConstantVisitor,
+ AttributeVisitor,
+ BootstrapMethodInfoVisitor
+{
+ private ConstantVisitor bootstrapMethodHandleVisitor;
+
+ // Field serving as a method argument.
+ int bootstrapMethodAttributeIndex;
+
+
+ /**
+ * Creates a new BootstrapMethodHandleVisitor that will delegate to the
+ * given constant visitor.
+ */
+ public BootstrapMethodHandleTraveler(ConstantVisitor bootstrapMethodHandleVisitor)
+ {
+ this.bootstrapMethodHandleVisitor = bootstrapMethodHandleVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Pass the method index.
+ bootstrapMethodAttributeIndex =
+ invokeDynamicConstant.u2bootstrapMethodAttributeIndex;
+
+ // Delegate to the bootstrap method.
+ clazz.attributesAccept(this);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Check bootstrap methods.
+ bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz,
+ bootstrapMethodAttributeIndex,
+ this);
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ // Check bootstrap method.
+ clazz.constantPoolEntryAccept(bootstrapMethodInfo.u2methodHandleIndex,
+ bootstrapMethodHandleVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ConstantTagFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ConstantTagFilter.java
new file mode 100644
index 0000000000..43a95f9f36
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ConstantTagFilter.java
@@ -0,0 +1,86 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.constant.Constant;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This <code>ConstantVisitor</code> delegates its visits to one or more
+ * specified types of constants.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantTagFilter
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final int constantTagMask;
+ private final ConstantVisitor constantVisitor;
+
+
+ /**
+ * Creates a new ConstantTagFilter.
+ * @param constantTag the type of constants for which visits will be
+ * delegated.
+ * @param constantVisitor the <code>ConstantVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ConstantTagFilter(int constantTag,
+ ConstantVisitor constantVisitor)
+ {
+ this.constantTagMask = 1 << constantTag;
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ /**
+ * Creates a new ConstantTagFilter.
+ * @param constantTags the types of constants for which visits will be
+ * delegated.
+ * @param constantVisitor the <code>ConstantVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ConstantTagFilter(int[] constantTags,
+ ConstantVisitor constantVisitor)
+ {
+ int constantTagMask = 0;
+ for (int index = 0; index < constantTags.length; index++)
+ {
+ constantTagMask |= 1 << constantTags[index];
+ }
+
+ this.constantTagMask = constantTagMask;
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ if (((1 << constant.getTag()) & constantTagMask) != 0)
+ {
+ constant.accept(clazz, constantVisitor);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ConstantVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ConstantVisitor.java
new file mode 100644
index 0000000000..2e74e3bec2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ConstantVisitor.java
@@ -0,0 +1,49 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.constant.*;
+
+
+/**
+ * This interface specifies the methods for a visitor of <code>Constant</code>
+ * objects.
+ *
+ * @author Eric Lafortune
+ */
+public interface ConstantVisitor
+{
+ public void visitIntegerConstant( Clazz clazz, IntegerConstant integerConstant);
+ public void visitLongConstant( Clazz clazz, LongConstant longConstant);
+ public void visitFloatConstant( Clazz clazz, FloatConstant floatConstant);
+ public void visitDoubleConstant( Clazz clazz, DoubleConstant doubleConstant);
+ public void visitStringConstant( Clazz clazz, StringConstant stringConstant);
+ public void visitUtf8Constant( Clazz clazz, Utf8Constant utf8Constant);
+ public void visitInvokeDynamicConstant( Clazz clazz, InvokeDynamicConstant invokeDynamicConstant);
+ public void visitMethodHandleConstant( Clazz clazz, MethodHandleConstant methodHandleConstant);
+ public void visitFieldrefConstant( Clazz clazz, FieldrefConstant fieldrefConstant);
+ public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant);
+ public void visitMethodrefConstant( Clazz clazz, MethodrefConstant methodrefConstant);
+ public void visitClassConstant( Clazz clazz, ClassConstant classConstant);
+ public void visitMethodTypeConstant( Clazz clazz, MethodTypeConstant methodTypeConstant);
+ public void visitNameAndTypeConstant( Clazz clazz, NameAndTypeConstant nameAndTypeConstant);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
new file mode 100644
index 0000000000..b49c478163
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
@@ -0,0 +1,64 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This <code>ConstantVisitor</code> delegates its visits to class constants
+ * to another given <code>ConstantVisitor</code>, except for one given class.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptClassConstantFilter
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final String exceptClassName;
+ private final ConstantVisitor constantVisitor;
+
+
+ /**
+ * Creates a new ExceptClassConstantFilter.
+ * @param exceptClassName the name of the class that will not be visited.
+ * @param constantVisitor the <code>ConstantVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ExceptClassConstantFilter(String exceptClassName,
+ ConstantVisitor constantVisitor)
+ {
+ this.exceptClassName = exceptClassName;
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ if (!classConstant.getName(clazz).equals(exceptClassName))
+ {
+ constantVisitor.visitClassConstant(clazz, classConstant);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/MethodrefTraveler.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/MethodrefTraveler.java
new file mode 100644
index 0000000000..4d8b0c6bf7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/MethodrefTraveler.java
@@ -0,0 +1,59 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.constant.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This ConstantVisitor travels from any method handle constants that it visits
+ * to their methodref constants, and applies a given constant visitor.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodrefTraveler
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private ConstantVisitor methodrefConstantVisitor;
+
+
+ /**
+ * Creates a new v that will delegate to the given constant visitor.
+ */
+ public MethodrefTraveler(ConstantVisitor methodrefConstantVisitor)
+ {
+ this.methodrefConstantVisitor = methodrefConstantVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex,
+ methodrefConstantVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/SuperClassConstantVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/SuperClassConstantVisitor.java
new file mode 100644
index 0000000000..7e826c91e7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/SuperClassConstantVisitor.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.constant.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor lets a given ConstantVisitor visit all the constant pool
+ * entries of the super class and interfaces of the program classes it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class SuperClassConstantVisitor implements ClassVisitor
+{
+ private final boolean visitSuperClassConstants;
+ private final boolean visitInterfaceConstants;
+ private final ConstantVisitor constantVisitor;
+
+
+ /**
+ * Creates a new SuperClassConstantVisitor.
+ */
+ public SuperClassConstantVisitor(boolean visitSuperClassConstants,
+ boolean visitInterfaceConstants,
+ ConstantVisitor constantVisitor)
+ {
+ this.visitSuperClassConstants = visitSuperClassConstants;
+ this.visitInterfaceConstants = visitInterfaceConstants;
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (visitSuperClassConstants)
+ {
+ programClass.superClassConstantAccept(constantVisitor);
+ }
+
+ if (visitInterfaceConstants)
+ {
+ programClass.interfaceConstantsAccept(constantVisitor);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/package.html
new file mode 100644
index 0000000000..e20f48e515
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/constant/visitor/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains visitors for class constants.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AccessFixer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AccessFixer.java
new file mode 100644
index 0000000000..c9669499d4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AccessFixer.java
@@ -0,0 +1,262 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor fixes the access modifiers of all classes and class
+ * members that are referenced by the classes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AccessFixer
+extends ReferencedClassVisitor
+implements ClassVisitor
+{
+ private final ConstantVisitor referencedClassStorer = new MyReferencedClassStorer();
+
+
+ /**
+ * Creates a new AccessFixer.
+ */
+ public AccessFixer()
+ {
+ // Unfortunately, the inner class must be static to be passed to the
+ // super constructor. We therefore can't let it refer to this class;
+ // we'll let this class refer to the inner class instead.
+ super(new MyAccessFixer());
+ }
+
+
+ // Overridden methods for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Remember the referencing class.
+ ((MyAccessFixer)classVisitor).referencingClass = programClass;
+
+ // Start visiting and fixing the referenced classes and class members.
+ super.visitProgramClass(programClass);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Remember the referencing class.
+ ((MyAccessFixer)classVisitor).referencingClass = libraryClass;
+
+ // Start visiting and fixing the referenced classes and class members.
+ super.visitLibraryClass(libraryClass);
+ }
+
+
+ // Overridden methods for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Fix the referenced classes and class members.
+ super.visitProgramMember(programClass, programMethod);
+
+ // Fix overridden or implemented methods higher up the hierarchy.
+ // We can ignore private and static methods and initializers.
+ if ((programMethod.getAccessFlags() & (ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC)) == 0 &&
+ !ClassUtil.isInitializer(programMethod.getName(programClass)))
+ {
+ programClass.hierarchyAccept(false, true, false, false,
+ new NamedMethodVisitor(programMethod.getName(programClass),
+ programMethod.getDescriptor(programClass),
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC,
+ (MemberVisitor)classVisitor)));
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ // Fix the referenced classes and class members.
+ super.visitLibraryMember(libraryClass, libraryMethod);
+
+ // Fix overridden or implemented methods higher up the hierarchy.
+ // We can ignore private and static methods and initializers.
+ if ((libraryMethod.getAccessFlags() & (ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC)) == 0 &&
+ !ClassUtil.isInitializer(libraryMethod.getName(libraryClass)))
+ {
+ libraryClass.hierarchyAccept(false, true, false, false,
+ new NamedMethodVisitor(libraryMethod.getName(libraryClass),
+ libraryMethod.getDescriptor(libraryClass),
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC,
+ (MemberVisitor)classVisitor)));
+ }
+ }
+
+
+ // Overridden methods for ConstantVisitor.
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Fix the access flags of the referenced class, if any.
+ super.visitStringConstant(clazz, stringConstant);
+
+ // Fix the access flags of the referenced class member, if any.
+ stringConstant.referencedMemberAccept((MemberVisitor)classVisitor);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Remember the referenced class. Note that we're interested in the
+ // class of the invocation, not in the class in which the member was
+ // actually found, unless it is an array type.
+ if (ClassUtil.isInternalArrayType(refConstant.getClassName(clazz)))
+ {
+ // For an array type, the class will be java.lang.Object.
+ ((MyAccessFixer)classVisitor).referencedClass =
+ refConstant.referencedClass;
+ }
+ else
+ {
+ // Remember the referenced class.
+ clazz.constantPoolEntryAccept(refConstant.u2classIndex,
+ referencedClassStorer);
+ }
+
+ // Fix the access flags of the class of the referenced class member.
+ super.visitAnyRefConstant(clazz, refConstant);
+
+ // Fix the access flags of the referenced class member.
+ refConstant.referencedMemberAccept((MemberVisitor)classVisitor);
+ }
+
+
+ /**
+ * This ConstantVisitor stores the classes referenced by the class
+ * constants that it visits.
+ */
+ private class MyReferencedClassStorer
+ extends SimplifiedVisitor
+ implements ConstantVisitor
+ {
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Remember the referenced class.
+ ((MyAccessFixer)classVisitor).referencedClass =
+ classConstant.referencedClass;
+ }
+ }
+
+
+ /**
+ * This ClassVisitor and MemberVisitor fixes the access flags of the
+ * classes and class members that it visits, relative to the referencing
+ * class.
+ *
+ * This class must be static so it can be passed to the super constructor
+ * of the outer class.
+ */
+ private static class MyAccessFixer
+ extends SimplifiedVisitor
+ implements ClassVisitor,
+ MemberVisitor
+ {
+ private Clazz referencingClass;
+ private Clazz referencedClass;
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ int currentAccessFlags = programClass.getAccessFlags();
+ int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags);
+
+ // Compute the required access level.
+ int requiredAccessLevel =
+ inSamePackage(programClass, referencingClass) ?
+ AccessUtil.PACKAGE_VISIBLE :
+ AccessUtil.PUBLIC;
+
+ // Fix the class access flags if necessary.
+ if (currentAccessLevel < requiredAccessLevel)
+ {
+ programClass.u2accessFlags =
+ AccessUtil.replaceAccessFlags(currentAccessFlags,
+ AccessUtil.accessFlags(requiredAccessLevel));
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) {}
+
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ int currentAccessFlags = programMember.getAccessFlags();
+ int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags);
+
+ // Compute the required access level.
+ // For protected access, we're taking into account the class in the
+ // invocation and the class that actually contains the member.
+ int requiredAccessLevel =
+ programClass.equals(referencingClass) ? AccessUtil.PRIVATE :
+ inSamePackage(programClass, referencingClass) ? AccessUtil.PACKAGE_VISIBLE :
+ referencedClass != null &&
+ referencingClass.extends_(referencedClass) &&
+ referencingClass.extends_(programClass) ? AccessUtil.PROTECTED :
+ AccessUtil.PUBLIC;
+
+ // Fix the class member access flags if necessary.
+ if (currentAccessLevel < requiredAccessLevel)
+ {
+ programMember.u2accessFlags =
+ AccessUtil.replaceAccessFlags(currentAccessFlags,
+ AccessUtil.accessFlags(requiredAccessLevel));
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the two given classes are in the same package.
+ */
+ private boolean inSamePackage(ProgramClass class1, Clazz class2)
+ {
+ return ClassUtil.internalPackageName(class1.getName()).equals(
+ ClassUtil.internalPackageName(class2.getName()));
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AnnotationAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AnnotationAdder.java
new file mode 100644
index 0000000000..3cd4d2f210
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AnnotationAdder.java
@@ -0,0 +1,153 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.AnnotationVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AnnotationVisitor adds all annotations that it visits to the given
+ * target annotation element value, target annotation attribute, or target
+ * parameter annotation attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class AnnotationAdder
+extends SimplifiedVisitor
+implements AnnotationVisitor
+{
+ private static final ElementValue[] EMPTY_ELEMENT_VALUES = new ElementValue[0];
+
+
+ private final ProgramClass targetClass;
+ private final AnnotationElementValue targetAnnotationElementValue;
+ private final AnnotationsAttributeEditor annotationsAttributeEditor;
+ private final ParameterAnnotationsAttributeEditor parameterAnnotationsAttributeEditor;
+
+ private final ConstantAdder constantAdder;
+
+
+ /**
+ * Creates a new AnnotationAdder that will copy annotations into the given
+ * target annotation element value.
+ */
+ public AnnotationAdder(ProgramClass targetClass,
+ AnnotationElementValue targetAnnotationElementValue)
+ {
+ this.targetClass = targetClass;
+ this.targetAnnotationElementValue = targetAnnotationElementValue;
+ this.annotationsAttributeEditor = null;
+ this.parameterAnnotationsAttributeEditor = null;
+
+ constantAdder = new ConstantAdder(targetClass);
+ }
+
+
+ /**
+ * Creates a new AnnotationAdder that will copy annotations into the given
+ * target annotations attribute.
+ */
+ public AnnotationAdder(ProgramClass targetClass,
+ AnnotationsAttribute targetAnnotationsAttribute)
+ {
+ this.targetClass = targetClass;
+ this.targetAnnotationElementValue = null;
+ this.annotationsAttributeEditor = new AnnotationsAttributeEditor(targetAnnotationsAttribute);
+ this.parameterAnnotationsAttributeEditor = null;
+
+ constantAdder = new ConstantAdder(targetClass);
+ }
+
+
+ /**
+ * Creates a new AnnotationAdder that will copy annotations into the given
+ * target parameter annotations attribute.
+ */
+ public AnnotationAdder(ProgramClass targetClass,
+ ParameterAnnotationsAttribute targetParameterAnnotationsAttribute)
+ {
+ this.targetClass = targetClass;
+ this.targetAnnotationElementValue = null;
+ this.annotationsAttributeEditor = null;
+ this.parameterAnnotationsAttributeEditor = new ParameterAnnotationsAttributeEditor(targetParameterAnnotationsAttribute);
+
+ constantAdder = new ConstantAdder(targetClass);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ Annotation newAnnotation =
+ new Annotation(constantAdder.addConstant(clazz, annotation.u2typeIndex),
+ 0,
+ annotation.u2elementValuesCount > 0 ?
+ new ElementValue[annotation.u2elementValuesCount] :
+ EMPTY_ELEMENT_VALUES);
+
+ // TODO: Clone array.
+ newAnnotation.referencedClasses = annotation.referencedClasses;
+
+ // Add the element values.
+ annotation.elementValuesAccept(clazz,
+ new ElementValueAdder(targetClass,
+ newAnnotation,
+ false));
+
+ // What's the target?
+ if (targetAnnotationElementValue != null)
+ {
+ // Simply set the completed annotation.
+ targetAnnotationElementValue.annotationValue = newAnnotation;
+ }
+ else
+ {
+ // Add the completed annotation.
+ annotationsAttributeEditor.addAnnotation(newAnnotation);
+ }
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, int parameterIndex, Annotation annotation)
+ {
+ Annotation newAnnotation =
+ new Annotation(constantAdder.addConstant(clazz, annotation.u2typeIndex),
+ 0,
+ annotation.u2elementValuesCount > 0 ?
+ new ElementValue[annotation.u2elementValuesCount] :
+ EMPTY_ELEMENT_VALUES);
+
+ // TODO: Clone array.
+ newAnnotation.referencedClasses = annotation.referencedClasses;
+
+ // Add the element values.
+ annotation.elementValuesAccept(clazz,
+ new ElementValueAdder(targetClass,
+ newAnnotation,
+ false));
+
+ // Add the completed annotation.
+ parameterAnnotationsAttributeEditor.addAnnotation(parameterIndex, newAnnotation);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AnnotationsAttributeEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AnnotationsAttributeEditor.java
new file mode 100644
index 0000000000..bdd08b5255
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AnnotationsAttributeEditor.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.attribute.annotation.*;
+
+/**
+ * This class can add annotations to a given annotations attribute.
+ * Annotations to be added must have been filled out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class AnnotationsAttributeEditor
+{
+ private AnnotationsAttribute targetAnnotationsAttribute;
+
+
+ /**
+ * Creates a new AnnotationsAttributeEditor that will edit annotations in
+ * the given annotations attribute.
+ */
+ public AnnotationsAttributeEditor(AnnotationsAttribute targetAnnotationsAttribute)
+ {
+ this.targetAnnotationsAttribute = targetAnnotationsAttribute;
+ }
+
+
+ /**
+ * Adds a given annotation to the annotations attribute.
+ */
+ public void addAnnotation(Annotation annotation)
+ {
+ int annotationsCount = targetAnnotationsAttribute.u2annotationsCount;
+ Annotation[] annotations = targetAnnotationsAttribute.annotations;
+
+ // Make sure there is enough space for the new annotation.
+ if (annotations.length <= annotationsCount)
+ {
+ targetAnnotationsAttribute.annotations = new Annotation[annotationsCount+1];
+ System.arraycopy(annotations, 0,
+ targetAnnotationsAttribute.annotations, 0,
+ annotationsCount);
+ annotations = targetAnnotationsAttribute.annotations;
+ }
+
+ // Add the annotation.
+ annotations[targetAnnotationsAttribute.u2annotationsCount++] = annotation;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributeAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributeAdder.java
new file mode 100644
index 0000000000..9c84df39d2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributeAdder.java
@@ -0,0 +1,500 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor adds all attributes that it visits to the given
+ * target class, class member, or attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class AttributeAdder
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private static final byte[] EMPTY_BYTES = new byte[0];
+ private static final int[] EMPTY_INTS = new int[0];
+ private static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0];
+ private static final ExceptionInfo[] EMPTY_EXCEPTIONS = new ExceptionInfo[0];
+ private static final Annotation[] EMPTY_ANNOTATIONS = new Annotation[0];
+
+
+ private final ProgramClass targetClass;
+ private final ProgramMember targetMember;
+ private final CodeAttribute targetCodeAttribute;
+ private final boolean replaceAttributes;
+
+ private final ConstantAdder constantAdder;
+ private final AttributesEditor attributesEditor;
+
+
+ /**
+ * Creates a new AttributeAdder that will copy attributes into the given
+ * target class.
+ */
+ public AttributeAdder(ProgramClass targetClass,
+ boolean replaceAttributes)
+ {
+ this(targetClass, null, null, replaceAttributes);
+ }
+
+
+ /**
+ * Creates a new AttributeAdder that will copy attributes into the given
+ * target class member.
+ */
+ public AttributeAdder(ProgramClass targetClass,
+ ProgramMember targetMember,
+ boolean replaceAttributes)
+ {
+ this(targetClass, targetMember, null, replaceAttributes);
+ }
+
+
+ /**
+ * Creates a new AttributeAdder that will copy attributes into the given
+ * target attribute.
+ */
+ public AttributeAdder(ProgramClass targetClass,
+ ProgramMember targetMember,
+ CodeAttribute targetCodeAttribute,
+ boolean replaceAttributes)
+ {
+ this.targetClass = targetClass;
+ this.targetMember = targetMember;
+ this.targetCodeAttribute = targetCodeAttribute;
+ this.replaceAttributes = replaceAttributes;
+
+ constantAdder = new ConstantAdder(targetClass);
+ attributesEditor = new AttributesEditor(targetClass,
+ targetMember,
+ targetCodeAttribute,
+ replaceAttributes);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ // Create a copy of the attribute.
+ UnknownAttribute newUnknownAttribute =
+ new UnknownAttribute(constantAdder.addConstant(clazz, unknownAttribute.u2attributeNameIndex),
+ unknownAttribute.u4attributeLength,
+ unknownAttribute.info);
+
+ // Add it to the target class.
+ attributesEditor.addAttribute(newUnknownAttribute);
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ // Create a copy of the attribute.
+ SourceFileAttribute newSourceFileAttribute =
+ new SourceFileAttribute(constantAdder.addConstant(clazz, sourceFileAttribute.u2attributeNameIndex),
+ constantAdder.addConstant(clazz, sourceFileAttribute.u2sourceFileIndex));
+
+ // Add it to the target class.
+ attributesEditor.addAttribute(newSourceFileAttribute);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ // Create a copy of the attribute.
+ SourceDirAttribute newSourceDirAttribute =
+ new SourceDirAttribute(constantAdder.addConstant(clazz, sourceDirAttribute.u2attributeNameIndex),
+ constantAdder.addConstant(clazz, sourceDirAttribute.u2sourceDirIndex));
+
+ // Add it to the target class.
+ attributesEditor.addAttribute(newSourceDirAttribute);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ // Create a copy of the attribute.
+ InnerClassesAttribute newInnerClassesAttribute =
+ new InnerClassesAttribute(constantAdder.addConstant(clazz, innerClassesAttribute.u2attributeNameIndex),
+ 0,
+ null);
+
+ // Add it to the target class.
+ attributesEditor.addAttribute(newInnerClassesAttribute);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ // Create a copy of the attribute.
+ EnclosingMethodAttribute newEnclosingMethodAttribute =
+ new EnclosingMethodAttribute(constantAdder.addConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex),
+ constantAdder.addConstant(clazz, enclosingMethodAttribute.u2classIndex),
+ enclosingMethodAttribute.u2nameAndTypeIndex == 0 ? 0 :
+ constantAdder.addConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex));
+
+ newEnclosingMethodAttribute.referencedClass = enclosingMethodAttribute.referencedClass;
+ newEnclosingMethodAttribute.referencedMethod = enclosingMethodAttribute.referencedMethod;
+
+ // Add it to the target class.
+ attributesEditor.addAttribute(newEnclosingMethodAttribute);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ // Create a copy of the attribute.
+ DeprecatedAttribute newDeprecatedAttribute =
+ new DeprecatedAttribute(constantAdder.addConstant(clazz, deprecatedAttribute.u2attributeNameIndex));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newDeprecatedAttribute);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ // Create a copy of the attribute.
+ SyntheticAttribute newSyntheticAttribute =
+ new SyntheticAttribute(constantAdder.addConstant(clazz, syntheticAttribute.u2attributeNameIndex));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newSyntheticAttribute);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ // Create a copy of the attribute.
+ SignatureAttribute newSignatureAttribute =
+ new SignatureAttribute(constantAdder.addConstant(clazz, signatureAttribute.u2attributeNameIndex),
+ constantAdder.addConstant(clazz, signatureAttribute.u2signatureIndex));
+
+ newSignatureAttribute.referencedClasses = signatureAttribute.referencedClasses;
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newSignatureAttribute);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ // Create a copy of the attribute.
+ ConstantValueAttribute newConstantValueAttribute =
+ new ConstantValueAttribute(constantAdder.addConstant(clazz, constantValueAttribute.u2attributeNameIndex),
+ constantAdder.addConstant(clazz, constantValueAttribute.u2constantValueIndex));
+
+ // Add it to the target field.
+ attributesEditor.addAttribute(newConstantValueAttribute);
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ // Create a new local variable table attribute.
+ MethodParametersAttribute newMethodParametersAttribute =
+ new MethodParametersAttribute(constantAdder.addConstant(clazz, methodParametersAttribute.u2attributeNameIndex),
+ methodParametersAttribute.u1parametersCount,
+ new ParameterInfo[methodParametersAttribute.u1parametersCount]);
+
+ // Add the local variables.
+ methodParametersAttribute.parametersAccept(clazz,
+ method,
+ new ParameterInfoAdder(targetClass, newMethodParametersAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newMethodParametersAttribute);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ // Create a new exceptions attribute.
+ ExceptionsAttribute newExceptionsAttribute =
+ new ExceptionsAttribute(constantAdder.addConstant(clazz, exceptionsAttribute.u2attributeNameIndex),
+ 0,
+ exceptionsAttribute.u2exceptionIndexTableLength > 0 ?
+ new int[exceptionsAttribute.u2exceptionIndexTableLength] :
+ EMPTY_INTS);
+
+ // Add the exceptions.
+ exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz,
+ new ExceptionAdder(targetClass,
+ newExceptionsAttribute));
+
+ // Add it to the target method.
+ attributesEditor.addAttribute(newExceptionsAttribute);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Create a new code attribute.
+ CodeAttribute newCodeAttribute =
+ new CodeAttribute(constantAdder.addConstant(clazz, codeAttribute.u2attributeNameIndex),
+ codeAttribute.u2maxStack,
+ codeAttribute.u2maxLocals,
+ 0,
+ EMPTY_BYTES,
+ 0,
+ codeAttribute.u2exceptionTableLength > 0 ?
+ new ExceptionInfo[codeAttribute.u2exceptionTableLength] :
+ EMPTY_EXCEPTIONS,
+ 0,
+ codeAttribute.u2attributesCount > 0 ?
+ new Attribute[codeAttribute.u2attributesCount] :
+ EMPTY_ATTRIBUTES);
+
+ CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
+
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength + 32);
+
+ // Add the instructions.
+ codeAttribute.instructionsAccept(clazz,
+ method,
+ new InstructionAdder(targetClass,
+ codeAttributeComposer));
+
+ // Append a label just after the code.
+ codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
+
+ // Add the exceptions.
+ codeAttribute.exceptionsAccept(clazz,
+ method,
+ new ExceptionInfoAdder(targetClass,
+ codeAttributeComposer));
+
+ // Add a line number if there wasn't a line number table before,
+ // so we keep track of the source.
+ if (codeAttribute.getAttribute(clazz, ClassConstants.ATTR_LineNumberTable) == null)
+ {
+ String source =
+ clazz.getName() + '.' +
+ method.getName(clazz) +
+ method.getDescriptor(clazz) +
+ ":0:0";
+
+ codeAttributeComposer.insertLineNumber(
+ new ExtendedLineNumberInfo(0, 0, source));
+ }
+
+ codeAttributeComposer.endCodeFragment();
+
+ // Add the attributes.
+ codeAttribute.attributesAccept(clazz,
+ method,
+ new AttributeAdder(targetClass,
+ targetMember,
+ newCodeAttribute,
+ replaceAttributes));
+
+ // Apply these changes to the new code attribute.
+ codeAttributeComposer.visitCodeAttribute(targetClass,
+ (Method)targetMember,
+ newCodeAttribute);
+
+ // Add the completed code attribute to the target method.
+ attributesEditor.addAttribute(newCodeAttribute);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ // TODO: Implement method.
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ // TODO: Implement method.
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ // Create a new line number table attribute.
+ LineNumberTableAttribute newLineNumberTableAttribute =
+ new LineNumberTableAttribute(constantAdder.addConstant(clazz, lineNumberTableAttribute.u2attributeNameIndex),
+ 0,
+ new LineNumberInfo[lineNumberTableAttribute.u2lineNumberTableLength]);
+
+ // Add the line numbers.
+ lineNumberTableAttribute.accept(clazz,
+ method,
+ codeAttribute,
+ new LineNumberInfoAdder(newLineNumberTableAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newLineNumberTableAttribute);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Create a new local variable table attribute.
+ LocalVariableTableAttribute newLocalVariableTableAttribute =
+ new LocalVariableTableAttribute(constantAdder.addConstant(clazz, localVariableTableAttribute.u2attributeNameIndex),
+ 0,
+ new LocalVariableInfo[localVariableTableAttribute.u2localVariableTableLength]);
+
+ // Add the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz,
+ method,
+ codeAttribute,
+ new LocalVariableInfoAdder(targetClass, newLocalVariableTableAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newLocalVariableTableAttribute);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Create a new local variable type table attribute.
+ LocalVariableTypeTableAttribute newLocalVariableTypeTableAttribute =
+ new LocalVariableTypeTableAttribute(constantAdder.addConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex),
+ 0,
+ new LocalVariableTypeInfo[localVariableTypeTableAttribute.u2localVariableTypeTableLength]);
+
+ // Add the local variable types.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz,
+ method,
+ codeAttribute,
+ new LocalVariableTypeInfoAdder(targetClass, newLocalVariableTypeTableAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newLocalVariableTypeTableAttribute);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ // Create a new annotations attribute.
+ RuntimeVisibleAnnotationsAttribute newAnnotationsAttribute =
+ new RuntimeVisibleAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleAnnotationsAttribute.u2attributeNameIndex),
+ 0,
+ new Annotation[runtimeVisibleAnnotationsAttribute.u2annotationsCount]);
+
+ // Add the annotations.
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz,
+ new AnnotationAdder(targetClass,
+ newAnnotationsAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ // Create a new annotations attribute.
+ RuntimeInvisibleAnnotationsAttribute newAnnotationsAttribute =
+ new RuntimeInvisibleAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleAnnotationsAttribute.u2attributeNameIndex),
+ 0,
+ new Annotation[runtimeInvisibleAnnotationsAttribute.u2annotationsCount]);
+
+ // Add the annotations.
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz,
+ new AnnotationAdder(targetClass,
+ newAnnotationsAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
+ {
+ // Create a new annotations attribute.
+ Annotation[][] parameterAnnotations =
+ new Annotation[runtimeVisibleParameterAnnotationsAttribute.u1parametersCount][];
+
+ Arrays.fill(parameterAnnotations, EMPTY_ANNOTATIONS);
+
+ RuntimeVisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute =
+ new RuntimeVisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleParameterAnnotationsAttribute.u2attributeNameIndex),
+ 0,
+ new int[runtimeVisibleParameterAnnotationsAttribute.u1parametersCount],
+ parameterAnnotations);
+
+ // Add the annotations.
+ runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz,
+ method,
+ new AnnotationAdder(targetClass,
+ newParameterAnnotationsAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newParameterAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
+ {
+ // Create a new annotations attribute.
+ Annotation[][] parameterAnnotations =
+ new Annotation[runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount][];
+
+ Arrays.fill(parameterAnnotations, EMPTY_ANNOTATIONS);
+
+ RuntimeInvisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute =
+ new RuntimeInvisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleParameterAnnotationsAttribute.u2attributeNameIndex),
+ 0,
+ new int[runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount],
+ parameterAnnotations);
+
+ // Add the annotations.
+ runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz,
+ method,
+ new AnnotationAdder(targetClass,
+ newParameterAnnotationsAttribute));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newParameterAnnotationsAttribute);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Create a new annotation default attribute.
+ AnnotationDefaultAttribute newAnnotationDefaultAttribute =
+ new AnnotationDefaultAttribute(constantAdder.addConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex),
+ null);
+
+ // Add the annotations.
+ annotationDefaultAttribute.defaultValueAccept(clazz,
+ new ElementValueAdder(targetClass,
+ newAnnotationDefaultAttribute,
+ false));
+
+ // Add it to the target.
+ attributesEditor.addAttribute(newAnnotationDefaultAttribute);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributeSorter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributeSorter.java
new file mode 100644
index 0000000000..4da8dcd965
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributeSorter.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+import java.util.*;
+
+/**
+ * This ClassVisitor sorts the attributes of the classes that it visits.
+ * The sorting order is based on the types of the attributes.
+ *
+ * @author Eric Lafortune
+ */
+public class AttributeSorter
+extends SimplifiedVisitor
+implements ClassVisitor, MemberVisitor, AttributeVisitor, Comparator
+{
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Sort the attributes.
+ Arrays.sort(programClass.attributes, 0, programClass.u2attributesCount, this);
+
+ // Sort the attributes of the class members.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ // Sort the attributes.
+ Arrays.sort(programMember.attributes, 0, programMember.u2attributesCount, this);
+
+ // Sort the attributes of the attributes.
+ programMember.attributesAccept(programClass, this);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Sort the attributes.
+ Arrays.sort(codeAttribute.attributes, 0, codeAttribute.u2attributesCount, this);
+ }
+
+
+ // Implementations for Comparator.
+
+ public int compare(Object object1, Object object2)
+ {
+ Attribute attribute1 = (Attribute)object1;
+ Attribute attribute2 = (Attribute)object2;
+
+ return attribute1.u2attributeNameIndex < attribute2.u2attributeNameIndex ? -1 :
+ attribute1.u2attributeNameIndex > attribute2.u2attributeNameIndex ? 1 :
+ 0;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributesEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributesEditor.java
new file mode 100644
index 0000000000..9944549b4f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/AttributesEditor.java
@@ -0,0 +1,314 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+
+/**
+ * This class can add and delete attributes to and from classes, fields,
+ * methods, and code attributes. Attributes to be added must be filled out
+ * beforehand, including their references to the constant pool. Existing
+ * attributes of the same type are always replaced.
+ *
+ * @author Eric Lafortune
+ */
+public class AttributesEditor
+{
+ private final ProgramClass targetClass;
+ private final ProgramMember targetMember;
+ private final CodeAttribute targetAttribute;
+ private final boolean replaceAttributes;
+
+
+ /**
+ * Creates a new AttributeAdder that will edit attributes in the given
+ * target class.
+ */
+ public AttributesEditor(ProgramClass targetClass,
+ boolean replaceAttributes)
+ {
+ this(targetClass, null, null, replaceAttributes);
+ }
+
+
+ /**
+ * Creates a new AttributeAdder that will edit attributes in the given
+ * target class member.
+ */
+ public AttributesEditor(ProgramClass targetClass,
+ ProgramMember targetMember,
+ boolean replaceAttributes)
+ {
+ this(targetClass, targetMember, null, replaceAttributes);
+ }
+
+
+ /**
+ * Creates a new AttributeAdder that will edit attributes in the given
+ * target code attribute.
+ */
+ public AttributesEditor(ProgramClass targetClass,
+ ProgramMember targetMember,
+ CodeAttribute targetAttribute,
+ boolean replaceAttributes)
+ {
+ this.targetClass = targetClass;
+ this.targetMember = targetMember;
+ this.targetAttribute = targetAttribute;
+ this.replaceAttributes = replaceAttributes;
+ }
+
+
+ /**
+ * Finds the specified attribute in the target.
+ */
+ public Attribute findAttribute(String attributeName)
+ {
+ // What's the target?
+ return
+ targetAttribute != null ?
+ findAttribute(targetAttribute.u2attributesCount,
+ targetAttribute.attributes,
+ attributeName) :
+ targetMember != null ?
+ findAttribute(targetMember.u2attributesCount,
+ targetMember.attributes,
+ attributeName) :
+ findAttribute(targetClass.u2attributesCount,
+ targetClass.attributes,
+ attributeName);
+ }
+
+
+ /**
+ * Adds the given attribute to the target.
+ */
+ public void addAttribute(Attribute attribute)
+ {
+ // What's the target?
+ if (targetAttribute != null)
+ {
+ // Try to replace an existing attribute.
+ if (!replaceAttributes ||
+ !replaceAttribute(targetAttribute.u2attributesCount,
+ targetAttribute.attributes,
+ attribute))
+ {
+ // Otherwise append the attribute.
+ targetAttribute.attributes =
+ addAttribute(targetAttribute.u2attributesCount,
+ targetAttribute.attributes,
+ attribute);
+
+ targetAttribute.u2attributesCount++;
+ }
+ }
+ else if (targetMember != null)
+ {
+ // Try to replace an existing attribute.
+ if (!replaceAttributes ||
+ !replaceAttribute(targetMember.u2attributesCount,
+ targetMember.attributes,
+ attribute))
+ {
+ // Otherwise append the attribute.
+ targetMember.attributes =
+ addAttribute(targetMember.u2attributesCount,
+ targetMember.attributes,
+ attribute);
+
+ targetMember.u2attributesCount++;
+ }
+ }
+ else
+ {
+ // Try to replace an existing attribute.
+ if (!replaceAttributes ||
+ !replaceAttribute(targetClass.u2attributesCount,
+ targetClass.attributes,
+ attribute))
+ {
+ // Otherwise append the attribute.
+ targetClass.attributes =
+ addAttribute(targetClass.u2attributesCount,
+ targetClass.attributes,
+ attribute);
+
+ targetClass.u2attributesCount++;
+ }
+ }
+ }
+
+
+ /**
+ * Deletes the specified attribute from the target.
+ */
+ public void deleteAttribute(String attributeName)
+ {
+ // What's the target?
+ if (targetAttribute != null)
+ {
+ targetAttribute.u2attributesCount =
+ deleteAttribute(targetAttribute.u2attributesCount,
+ targetAttribute.attributes,
+ attributeName);
+ }
+ else if (targetMember != null)
+ {
+ targetMember.u2attributesCount =
+ deleteAttribute(targetMember.u2attributesCount,
+ targetMember.attributes,
+ attributeName);
+ }
+ else
+ {
+ targetClass.u2attributesCount =
+ deleteAttribute(targetClass.u2attributesCount,
+ targetClass.attributes,
+ attributeName);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Tries to put the given attribute in place of an existing attribute of
+ * the same name, returning whether it was present.
+ */
+ private boolean replaceAttribute(int attributesCount,
+ Attribute[] attributes,
+ Attribute attribute)
+ {
+ // Find the attribute with the same name.
+ int index = findAttributeIndex(attributesCount,
+ attributes,
+ attribute.getAttributeName(targetClass));
+ if (index < 0)
+ {
+ return false;
+ }
+
+ attributes[index] = attribute;
+
+ return true;
+ }
+
+
+ /**
+ * Appends the given attribute to the given array of attributes, creating a
+ * new array if necessary.
+ */
+ private Attribute[] addAttribute(int attributesCount,
+ Attribute[] attributes,
+ Attribute attribute)
+ {
+ // Is the array too small to contain the additional attribute?
+ if (attributes.length <= attributesCount)
+ {
+ // Create a new array and copy the attributes into it.
+ Attribute[] newAttributes = new Attribute[attributesCount + 1];
+ System.arraycopy(attributes, 0,
+ newAttributes, 0,
+ attributesCount);
+ attributes = newAttributes;
+ }
+
+ // Append the attribute.
+ attributes[attributesCount] = attribute;
+
+ return attributes;
+ }
+
+
+ /**
+ * Deletes the attributes with the given name from the given array of
+ * attributes, returning the new number of attributes.
+ */
+ private int deleteAttribute(int attributesCount,
+ Attribute[] attributes,
+ String attributeName)
+ {
+ // Find the attribute.
+ int index = findAttributeIndex(attributesCount,
+ attributes,
+ attributeName);
+ if (index < 0)
+ {
+ return attributesCount;
+ }
+
+ // Shift the other attributes in the array.
+ System.arraycopy(attributes, index + 1,
+ attributes, index,
+ attributesCount - index - 1);
+
+ // Clear the last entry in the array.
+ attributes[--attributesCount] = null;
+
+ return attributesCount;
+ }
+
+
+ /**
+ * Finds the index of the attribute with the given name in the given
+ * array of attributes.
+ */
+ private int findAttributeIndex(int attributesCount,
+ Attribute[] attributes,
+ String attributeName)
+ {
+ for (int index = 0; index < attributesCount; index++)
+ {
+ Attribute attribute = attributes[index];
+
+ if (attribute.getAttributeName(targetClass).equals(attributeName))
+ {
+ return index;
+ }
+ }
+
+ return -1;
+ }
+
+
+ /**
+ * Finds the attribute with the given name in the given
+ * array of attributes.
+ */
+ private Attribute findAttribute(int attributesCount,
+ Attribute[] attributes,
+ String attributeName)
+ {
+ for (int index = 0; index < attributesCount; index++)
+ {
+ Attribute attribute = attributes[index];
+
+ if (attribute.getAttributeName(targetClass).equals(attributeName))
+ {
+ return attribute;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodInfoAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodInfoAdder.java
new file mode 100644
index 0000000000..05f0fcbb2e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodInfoAdder.java
@@ -0,0 +1,86 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.BootstrapMethodInfoVisitor;
+
+/**
+ * This BootstrapMethodInfoVisitor adds all bootstrap methods that it visits to
+ * the given target bootstrap methods attribute.
+ */
+public class BootstrapMethodInfoAdder
+implements BootstrapMethodInfoVisitor
+{
+ private final ConstantAdder constantAdder;
+ private final BootstrapMethodsAttributeEditor bootstrapMethodsAttributeEditor;
+
+ private int bootstrapMethodIndex;
+
+
+ /**
+ * Creates a new BootstrapMethodInfoAdder that will copy bootstrap methods
+ * into the given bootstrap methods attribute.
+ */
+ public BootstrapMethodInfoAdder(ProgramClass targetClass,
+ BootstrapMethodsAttribute targetBootstrapMethodsAttribute)
+ {
+ this.constantAdder = new ConstantAdder(targetClass);
+ this.bootstrapMethodsAttributeEditor = new BootstrapMethodsAttributeEditor(targetBootstrapMethodsAttribute);
+ }
+
+
+ /**
+ * Returns the index of the most recently added bootstrap method.
+ */
+ public int getBootstrapMethodIndex()
+ {
+ return bootstrapMethodIndex;
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ // Copy the method arguments.
+ int methodArgumentCount = bootstrapMethodInfo.u2methodArgumentCount;
+ int[] methodArguments = bootstrapMethodInfo.u2methodArguments;
+ int[] newMethodArguments = new int[methodArgumentCount];
+
+ for (int index = 0; index < methodArgumentCount; index++)
+ {
+ newMethodArguments[index] =
+ constantAdder.addConstant(clazz, methodArguments[index]);
+ }
+
+ // Create a new bootstrap method.
+ BootstrapMethodInfo newBootstrapMethodInfo =
+ new BootstrapMethodInfo(constantAdder.addConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex),
+ methodArgumentCount,
+ newMethodArguments);
+
+ // Add it to the target.
+ bootstrapMethodIndex =
+ bootstrapMethodsAttributeEditor.addBootstrapMethodInfo(newBootstrapMethodInfo);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodRemapper.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodRemapper.java
new file mode 100644
index 0000000000..c13310b3c0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodRemapper.java
@@ -0,0 +1,88 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ConstantVisitor remaps all possible indices of bootstrap methods
+ * of the constants that it visits, based on a given index map.
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodRemapper
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private int[] constantIndexMap;
+
+
+ /**
+ * Sets the given mapping of old constant pool entry indexes to their new
+ * indexes.
+ */
+ public void setConstantIndexMap(int[] constantIndexMap)
+ {
+ this.constantIndexMap = constantIndexMap;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ invokeDynamicConstant.u2bootstrapMethodAttributeIndex =
+ remapConstantIndex(invokeDynamicConstant.u2bootstrapMethodAttributeIndex);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the new bootstrap method index of the entry at the
+ * given index.
+ */
+ private int remapConstantIndex(int constantIndex)
+ {
+ int remappedConstantIndex = constantIndexMap[constantIndex];
+ if (remappedConstantIndex < 0)
+ {
+ throw new IllegalArgumentException("Can't remap constant index ["+constantIndex+"]");
+ }
+
+ return remappedConstantIndex;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodsAttributeAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodsAttributeAdder.java
new file mode 100644
index 0000000000..5ac2281a29
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodsAttributeAdder.java
@@ -0,0 +1,91 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.BootstrapMethodInfoVisitor;
+
+/**
+ * This BootstrapMethodInfoVisitor adds all bootstrap methods that it visits to
+ * the given target class, creating a bootstrap methods attribute if necessary.
+ */
+public class BootstrapMethodsAttributeAdder
+implements BootstrapMethodInfoVisitor
+{
+ private final ProgramClass targetClass;
+ private final ConstantPoolEditor constantPoolEditor;
+ private BootstrapMethodInfoAdder bootstrapMethodInfoAdder;
+
+
+ /**
+ * Creates a new BootstrapMethodsAttributeAdder that will copy bootstrap
+ * methods into the given target class/
+ */
+ public BootstrapMethodsAttributeAdder(ProgramClass targetClass)
+ {
+ this.targetClass = targetClass;
+ this.constantPoolEditor = new ConstantPoolEditor(targetClass);
+ }
+
+
+ /**
+ * Returns the index of the most recently added bootstrap method.
+ */
+ public int getBootstrapMethodIndex()
+ {
+ return bootstrapMethodInfoAdder.getBootstrapMethodIndex();
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ // Make sure we have a bootstrap methods attribute adder.
+ if (bootstrapMethodInfoAdder == null)
+ {
+ // Make sure we have a target bootstrap methods attribute.
+ AttributesEditor attributesEditor =
+ new AttributesEditor(targetClass, false);
+
+ BootstrapMethodsAttribute targetBootstrapMethodsAttribute =
+ (BootstrapMethodsAttribute)attributesEditor.findAttribute(ClassConstants.ATTR_BootstrapMethods);
+
+ if (targetBootstrapMethodsAttribute == null)
+ {
+ targetBootstrapMethodsAttribute =
+ new BootstrapMethodsAttribute(constantPoolEditor.addUtf8Constant(ClassConstants.ATTR_BootstrapMethods),
+ 0,
+ new BootstrapMethodInfo[0]);
+
+ attributesEditor.addAttribute(targetBootstrapMethodsAttribute);
+ }
+
+ // Create a bootstrap method adder for it.
+ bootstrapMethodInfoAdder = new BootstrapMethodInfoAdder(targetClass,
+ targetBootstrapMethodsAttribute);
+ }
+
+ // Delegate to the bootstrap method adder.
+ bootstrapMethodInfoAdder.visitBootstrapMethodInfo(clazz, bootstrapMethodInfo);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodsAttributeEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodsAttributeEditor.java
new file mode 100644
index 0000000000..c2ed13a0c6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BootstrapMethodsAttributeEditor.java
@@ -0,0 +1,60 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.attribute.*;
+import proguard.util.ArrayUtil;
+
+/**
+ * This class can add bootstrap methods to a given bootstrap methods attribute.
+ * Bootstrap methods to be added must have been filled out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodsAttributeEditor
+{
+ private BootstrapMethodsAttribute targetBootstrapMethodsAttribute;
+
+
+ /**
+ * Creates a new BootstrapMethodsAttributeEditor that will edit bootstrap
+ * methods in the given bootstrap methods attribute.
+ */
+ public BootstrapMethodsAttributeEditor(BootstrapMethodsAttribute targetBootstrapMethodsAttribute)
+ {
+ this.targetBootstrapMethodsAttribute = targetBootstrapMethodsAttribute;
+ }
+
+
+ /**
+ * Adds a given bootstrap method to the bootstrap methods attribute.
+ * @return the index of the bootstrap method.
+ */
+ public int addBootstrapMethodInfo(BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ targetBootstrapMethodsAttribute.bootstrapMethods =
+ (BootstrapMethodInfo[])ArrayUtil.add(targetBootstrapMethodsAttribute.bootstrapMethods,
+ targetBootstrapMethodsAttribute.u2bootstrapMethodsCount,
+ bootstrapMethodInfo);
+
+ return targetBootstrapMethodsAttribute.u2bootstrapMethodsCount++;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BridgeMethodFixer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BridgeMethodFixer.java
new file mode 100644
index 0000000000..f58ee97a82
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/BridgeMethodFixer.java
@@ -0,0 +1,117 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.RefConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor fixes all inappropriate bridge access flags of the
+ * program methods that it visits, checking whether the methods to which they
+ * bridge have the same name. Some compilers, like in Eclipse and in later
+ * versions of JDK 1.6, complain if they can't find the method with the same
+ * name.
+ *
+ * @author Eric Lafortune
+ */
+public class BridgeMethodFixer
+extends SimplifiedVisitor
+implements MemberVisitor,
+ AttributeVisitor,
+ InstructionVisitor,
+ ConstantVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ // Return values for the visitor methods.
+ private String bridgedMethodName;
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if ((programMethod.getAccessFlags() & ClassConstants.ACC_BRIDGE) != 0)
+ {
+ programMethod.attributesAccept(programClass, this);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Go over the instructions of the bridge method.
+ codeAttribute.instructionsAccept(clazz, method, this);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ // Get the name of the bridged method.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+
+ // Check if the name is different.
+ if (!method.getName(clazz).equals(bridgedMethodName))
+ {
+ if (DEBUG)
+ {
+ System.out.println("BridgeMethodFixer: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] does not bridge to ["+bridgedMethodName+"]");
+ }
+
+ // Clear the bridge flag.
+ ((ProgramMethod)method).u2accessFlags &= ~ClassConstants.ACC_BRIDGE;
+ }
+ break;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ bridgedMethodName = refConstant.getName(clazz);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassEditor.java
new file mode 100644
index 0000000000..086a0310f3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassEditor.java
@@ -0,0 +1,255 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+
+/**
+ * This class can add interfaces and class members to a given class.
+ * Elements to be added must be filled out beforehand, including their
+ * references to the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassEditor
+{
+ private static final boolean DEBUG = false;
+
+ private ProgramClass targetClass;
+
+
+ /**
+ * Creates a new ClassEditor that will edit elements in the given
+ * target class.
+ */
+ public ClassEditor(ProgramClass targetClass)
+ {
+ this.targetClass = targetClass;
+ }
+
+
+ /**
+ * Adds the given interface.
+ */
+ public void addInterface(int interfaceConstantIndex)
+ {
+ int interfacesCount = targetClass.u2interfacesCount;
+ int[] interfaces = targetClass.u2interfaces;
+
+ // Make sure there is enough space for the new interface.
+ if (interfaces.length <= interfacesCount)
+ {
+ targetClass.u2interfaces = new int[interfacesCount+1];
+ System.arraycopy(interfaces, 0,
+ targetClass.u2interfaces, 0,
+ interfacesCount);
+ interfaces = targetClass.u2interfaces;
+ }
+
+ if (DEBUG)
+ {
+ System.out.println(targetClass.getName()+": adding interface ["+targetClass.getClassName(interfaceConstantIndex)+"]");
+ }
+
+ // Add the interface.
+ interfaces[targetClass.u2interfacesCount++] = interfaceConstantIndex;
+ }
+
+ /**
+ * Removes the given interface.
+ */
+ public void removeInterface(int interfaceConstantIndex)
+ {
+ int interfacesCount = targetClass.u2interfacesCount;
+ int[] interfaces = targetClass.u2interfaces;
+
+ int interfaceIndex = findInterfaceIndex(interfaceConstantIndex);
+
+ // Shift the interface entries.
+ System.arraycopy(interfaces, interfaceIndex+1,
+ interfaces, interfaceIndex,
+ interfacesCount - interfaceIndex - 1);
+
+ // Clear the last entry.
+ interfaces[--targetClass.u2interfacesCount] = 0;
+ }
+
+
+ /**
+ * Finds the index of the given interface in the target class.
+ */
+
+ private int findInterfaceIndex(int interfaceConstantIndex)
+ {
+ int interfacesCount = targetClass.u2interfacesCount;
+ int[] interfaces = targetClass.u2interfaces;
+
+ for (int index = 0; index < interfacesCount; index++)
+ {
+ if (interfaces[index] == interfaceConstantIndex)
+ {
+ return index;
+ }
+ }
+
+ return interfacesCount;
+ }
+
+
+ /**
+ * Adds the given field.
+ */
+ public void addField(Field field)
+ {
+ int fieldsCount = targetClass.u2fieldsCount;
+ Field[] fields = targetClass.fields;
+
+ // Make sure there is enough space for the new field.
+ if (fields.length <= fieldsCount)
+ {
+ targetClass.fields = new ProgramField[fieldsCount+1];
+ System.arraycopy(fields, 0,
+ targetClass.fields, 0,
+ fieldsCount);
+ fields = targetClass.fields;
+ }
+
+ if (DEBUG)
+ {
+ System.out.println(targetClass.getName()+": adding field ["+field.getName(targetClass)+" "+field.getDescriptor(targetClass)+"]");
+ }
+
+ // Add the field.
+ fields[targetClass.u2fieldsCount++] = field;
+ }
+
+
+ /**
+ * Removes the given field. Note that removing a field that is still being
+ * referenced can cause unpredictable effects.
+ */
+ public void removeField(Field field)
+ {
+ int fieldsCount = targetClass.u2fieldsCount;
+ Field[] fields = targetClass.fields;
+
+ int fieldIndex = findFieldIndex(field);
+
+ // Shift the field entries.
+ System.arraycopy(fields, fieldIndex+1,
+ fields, fieldIndex,
+ fieldsCount - fieldIndex - 1);
+
+ // Clear the last entry.
+ fields[--targetClass.u2fieldsCount] = null;
+ }
+
+
+ /**
+ * Finds the index of the given field in the target class.
+ */
+
+ private int findFieldIndex(Field field)
+ {
+ int fieldsCount = targetClass.u2fieldsCount;
+ Field[] fields = targetClass.fields;
+
+ for (int index = 0; index < fieldsCount; index++)
+ {
+ if (fields[index].equals(field))
+ {
+ return index;
+ }
+ }
+
+ return fieldsCount;
+ }
+
+
+ /**
+ * Adds the given method.
+ */
+ public void addMethod(Method method)
+ {
+ int methodsCount = targetClass.u2methodsCount;
+ Method[] methods = targetClass.methods;
+
+ // Make sure there is enough space for the new method.
+ if (methods.length <= methodsCount)
+ {
+ targetClass.methods = new ProgramMethod[methodsCount+1];
+ System.arraycopy(methods, 0,
+ targetClass.methods, 0,
+ methodsCount);
+ methods = targetClass.methods;
+ }
+
+ if (DEBUG)
+ {
+ System.out.println(targetClass.getName()+": adding method ["+method.getName(targetClass)+method.getDescriptor(targetClass)+"]");
+ }
+
+ // Add the method.
+ methods[targetClass.u2methodsCount++] = method;
+ }
+
+
+ /**
+ * Removes the given method. Note that removing a method that is still being
+ * referenced can cause unpredictable effects.
+ */
+ public void removeMethod(Method method)
+ {
+ int methodsCount = targetClass.u2methodsCount;
+ Method[] methods = targetClass.methods;
+
+ int methodIndex = findMethodIndex(method);
+
+ // Shift the method entries.
+ System.arraycopy(methods, methodIndex+1,
+ methods, methodIndex,
+ methodsCount - methodIndex - 1);
+
+ // Clear the last entry.
+ methods[--targetClass.u2methodsCount] = null;
+ }
+
+
+ /**
+ * Finds the index of the given method in the target class.
+ */
+
+ private int findMethodIndex(Method method)
+ {
+ int methodsCount = targetClass.u2methodsCount;
+ Method[] methods = targetClass.methods;
+
+ for (int index = 0; index < methodsCount; index++)
+ {
+ if (methods[index].equals(method))
+ {
+ return index;
+ }
+ }
+
+ return methodsCount;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassElementSorter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassElementSorter.java
new file mode 100644
index 0000000000..a9cdf0c3a7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassElementSorter.java
@@ -0,0 +1,52 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.ProgramClass;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor sorts the various elements of the classes that it visits:
+ * interfaces, constants, fields, methods, and attributes.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassElementSorter
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final ClassVisitor interfaceSorter = new InterfaceSorter();
+ private final ClassVisitor constantPoolSorter = new ConstantPoolSorter();
+// private ClassVisitor classMemberSorter = new ClassMemberSorter();
+ private final ClassVisitor attributeSorter = new AttributeSorter();
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.accept(constantPoolSorter);
+ programClass.accept(interfaceSorter);
+// programClass.accept(classMemberSorter);
+ programClass.accept(attributeSorter);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassMemberSorter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassMemberSorter.java
new file mode 100644
index 0000000000..4efcf914a6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassMemberSorter.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.util.*;
+
+/**
+ * This ClassVisitor sorts the class members of the classes that it visits.
+ * The sorting order is based on the access flags, the names, and the
+ * descriptors.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassMemberSorter implements ClassVisitor, Comparator
+{
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Sort the fields.
+ Arrays.sort(programClass.fields, 0, programClass.u2fieldsCount, this);
+
+ // Sort the methods.
+ Arrays.sort(programClass.methods, 0, programClass.u2methodsCount, this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ }
+
+
+ // Implementations for Comparator.
+
+ public int compare(Object object1, Object object2)
+ {
+ ProgramMember member1 = (ProgramMember)object1;
+ ProgramMember member2 = (ProgramMember)object2;
+
+ return member1.u2accessFlags < member2.u2accessFlags ? -1 :
+ member1.u2accessFlags > member2.u2accessFlags ? 1 :
+ member1.u2nameIndex < member2.u2nameIndex ? -1 :
+ member1.u2nameIndex > member2.u2nameIndex ? 1 :
+ member1.u2descriptorIndex < member2.u2descriptorIndex ? -1 :
+ member1.u2descriptorIndex > member2.u2descriptorIndex ? 1 :
+ 0;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassReferenceFixer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassReferenceFixer.java
new file mode 100644
index 0000000000..ffe7aa8fa8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ClassReferenceFixer.java
@@ -0,0 +1,591 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor fixes references of constant pool entries, fields,
+ * methods, and attributes to classes whose names have changed. Descriptors
+ * of member references are not updated yet.
+ *
+ * @see MemberReferenceFixer
+ * @author Eric Lafortune
+ */
+public class ClassReferenceFixer
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor,
+ MemberVisitor,
+ AttributeVisitor,
+ InnerClassesInfoVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor
+{
+ private final boolean ensureUniqueMemberNames;
+
+
+ /**
+ * Creates a new ClassReferenceFixer.
+ * @param ensureUniqueMemberNames specifies whether class members whose
+ * descriptor changes should get new, unique
+ * names, in order to avoid naming conflicts
+ * with similar methods.
+ */
+ public ClassReferenceFixer(boolean ensureUniqueMemberNames)
+ {
+ this.ensureUniqueMemberNames = ensureUniqueMemberNames;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Fix the constant pool.
+ programClass.constantPoolEntriesAccept(this);
+
+ // Fix class members.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ // Fix the attributes.
+ programClass.attributesAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Fix class members.
+ libraryClass.fieldsAccept(this);
+ libraryClass.methodsAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Has the descriptor changed?
+ String descriptor = programField.getDescriptor(programClass);
+ String newDescriptor = newDescriptor(descriptor,
+ programField.referencedClass);
+
+ if (!descriptor.equals(newDescriptor))
+ {
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor(programClass);
+
+ // Update the descriptor.
+ programField.u2descriptorIndex =
+ constantPoolEditor.addUtf8Constant(newDescriptor);
+
+ // Update the name, if requested.
+ if (ensureUniqueMemberNames)
+ {
+ String name = programField.getName(programClass);
+ String newName = newUniqueMemberName(name, descriptor);
+ programField.u2nameIndex =
+ constantPoolEditor.addUtf8Constant(newName);
+ }
+ }
+
+ // Fix the attributes.
+ programField.attributesAccept(programClass, this);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Has the descriptor changed?
+ String descriptor = programMethod.getDescriptor(programClass);
+ String newDescriptor = newDescriptor(descriptor,
+ programMethod.referencedClasses);
+
+ if (!descriptor.equals(newDescriptor))
+ {
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor(programClass);
+
+ // Update the descriptor.
+ programMethod.u2descriptorIndex =
+ constantPoolEditor.addUtf8Constant(newDescriptor);
+
+ // Update the name, if requested.
+ if (ensureUniqueMemberNames)
+ {
+ String name = programMethod.getName(programClass);
+ String newName = newUniqueMemberName(name, descriptor);
+ programMethod.u2nameIndex =
+ constantPoolEditor.addUtf8Constant(newName);
+ }
+ }
+
+ // Fix the attributes.
+ programMethod.attributesAccept(programClass, this);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ // Has the descriptor changed?
+ String descriptor = libraryField.getDescriptor(libraryClass);
+ String newDescriptor = newDescriptor(descriptor,
+ libraryField.referencedClass);
+
+ // Update the descriptor.
+ libraryField.descriptor = newDescriptor;
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ // Has the descriptor changed?
+ String descriptor = libraryMethod.getDescriptor(libraryClass);
+ String newDescriptor = newDescriptor(descriptor,
+ libraryMethod.referencedClasses);
+
+ if (!descriptor.equals(newDescriptor))
+ {
+ // Update the descriptor.
+ libraryMethod.descriptor = newDescriptor;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Does the string refer to a class, due to a Class.forName construct?
+ Clazz referencedClass = stringConstant.referencedClass;
+ Member referencedMember = stringConstant.referencedMember;
+ if (referencedClass != null &&
+ referencedMember == null)
+ {
+ // Reconstruct the new class name.
+ String externalClassName = stringConstant.getString(clazz);
+ String internalClassName = ClassUtil.internalClassName(externalClassName);
+ String newInternalClassName = newClassName(internalClassName,
+ referencedClass);
+
+ // Update the String entry if required.
+ if (!newInternalClassName.equals(internalClassName))
+ {
+ // Only convert to an external class name if the original was
+ // an external class name too.
+ String newExternalClassName =
+ externalClassName.indexOf(JavaConstants.PACKAGE_SEPARATOR) >= 0 ?
+ ClassUtil.externalClassName(newInternalClassName) :
+ newInternalClassName;
+
+ // Refer to a new Utf8 entry.
+ stringConstant.u2stringIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newExternalClassName);
+ }
+ }
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Has the descriptor changed?
+ String descriptor = invokeDynamicConstant.getType(clazz);
+ String newDescriptor = newDescriptor(descriptor,
+ invokeDynamicConstant.referencedClasses);
+
+ if (!descriptor.equals(newDescriptor))
+ {
+ String name = invokeDynamicConstant.getName(clazz);
+
+ // Refer to a new NameAndType entry.
+ invokeDynamicConstant.u2nameAndTypeIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(name, newDescriptor);
+ }
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Do we know the referenced class?
+ Clazz referencedClass = classConstant.referencedClass;
+ if (referencedClass != null)
+ {
+ // Has the class name changed?
+ String className = classConstant.getName(clazz);
+ String newClassName = newClassName(className, referencedClass);
+ if (!className.equals(newClassName))
+ {
+ // Refer to a new Utf8 entry.
+ classConstant.u2nameIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newClassName);
+ }
+ }
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ // Has the descriptor changed?
+ String descriptor = methodTypeConstant.getType(clazz);
+ String newDescriptor = newDescriptor(descriptor,
+ methodTypeConstant.referencedClasses);
+
+ if (!descriptor.equals(newDescriptor))
+ {
+ // Update the descriptor.
+ methodTypeConstant.u2descriptorIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newDescriptor);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ // Fix the inner class names.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Fix the attributes.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Fix the types of the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Fix the signatures of the local variables.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ // Has the signature changed?
+ String signature = signatureAttribute.getSignature(clazz);
+ String newSignature = newDescriptor(signature,
+ signatureAttribute.referencedClasses);
+
+ if (!signature.equals(newSignature))
+ {
+ // Update the signature.
+ signatureAttribute.u2signatureIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature);
+ }
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ // Fix the annotations.
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Fix the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Fix the annotation.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ // Fix the inner class name.
+ int innerClassIndex = innerClassesInfo.u2innerClassIndex;
+ int innerNameIndex = innerClassesInfo.u2innerNameIndex;
+ if (innerClassIndex != 0 &&
+ innerNameIndex != 0)
+ {
+ String newInnerName = clazz.getClassName(innerClassIndex);
+ int index = newInnerName.lastIndexOf(ClassConstants.INNER_CLASS_SEPARATOR);
+ if (index >= 0)
+ {
+ innerClassesInfo.u2innerNameIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newInnerName.substring(index + 1));
+ }
+ }
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Has the descriptor changed?
+ String descriptor = localVariableInfo.getDescriptor(clazz);
+ String newDescriptor = newDescriptor(descriptor,
+ localVariableInfo.referencedClass);
+
+ if (!descriptor.equals(newDescriptor))
+ {
+ // Refer to a new Utf8 entry.
+ localVariableInfo.u2descriptorIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newDescriptor);
+ }
+ }
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Has the signature changed?
+ String signature = localVariableTypeInfo.getSignature(clazz);
+ String newSignature = newDescriptor(signature,
+ localVariableTypeInfo.referencedClasses);
+
+ if (!signature.equals(newSignature))
+ {
+ // Update the signature.
+ localVariableTypeInfo.u2signatureIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature);
+ }
+ }
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ // Has the type changed?
+ String typeName = annotation.getType(clazz);
+ String newTypeName = newDescriptor(typeName,
+ annotation.referencedClasses);
+
+ if (!typeName.equals(newTypeName))
+ {
+ // Update the type.
+ annotation.u2typeIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newTypeName);
+ }
+
+ // Fix the element values.
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ // Has the type name chamged?
+ String typeName = enumConstantElementValue.getTypeName(clazz);
+ String newTypeName = newDescriptor(typeName,
+ enumConstantElementValue.referencedClasses);
+
+ if (!typeName.equals(newTypeName))
+ {
+ // Update the type name.
+ enumConstantElementValue.u2typeNameIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newTypeName);
+ }
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ // Has the class info changed?
+ String className = classElementValue.getClassName(clazz);
+ String newClassName = newDescriptor(className,
+ classElementValue.referencedClasses);
+
+ if (!className.equals(newClassName))
+ {
+ // Update the class info.
+ classElementValue.u2classInfoIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newClassName);
+ }
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ // Fix the annotation.
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ // Fix the element values.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ }
+
+
+ // Small utility methods.
+
+ private static String newDescriptor(String descriptor,
+ Clazz referencedClass)
+ {
+ // If there is no referenced class, the descriptor won't change.
+ if (referencedClass == null)
+ {
+ return descriptor;
+ }
+
+ // Unravel and reconstruct the class element of the descriptor.
+ DescriptorClassEnumeration descriptorClassEnumeration =
+ new DescriptorClassEnumeration(descriptor);
+
+ StringBuffer newDescriptorBuffer = new StringBuffer(descriptor.length());
+ newDescriptorBuffer.append(descriptorClassEnumeration.nextFluff());
+
+ // Only if the descriptor contains a class name (e.g. with an array of
+ // primitive types), the descriptor can change.
+ if (descriptorClassEnumeration.hasMoreClassNames())
+ {
+ String className = descriptorClassEnumeration.nextClassName();
+ String fluff = descriptorClassEnumeration.nextFluff();
+
+ String newClassName = newClassName(className,
+ referencedClass);
+
+ newDescriptorBuffer.append(newClassName);
+ newDescriptorBuffer.append(fluff);
+ }
+
+ return newDescriptorBuffer.toString();
+ }
+
+
+ private static String newDescriptor(String descriptor,
+ Clazz[] referencedClasses)
+ {
+ // If there are no referenced classes, the descriptor won't change.
+ if (referencedClasses == null ||
+ referencedClasses.length == 0)
+ {
+ return descriptor;
+ }
+
+ // Unravel and reconstruct the class elements of the descriptor.
+ DescriptorClassEnumeration descriptorClassEnumeration =
+ new DescriptorClassEnumeration(descriptor);
+
+ StringBuffer newDescriptorBuffer = new StringBuffer(descriptor.length());
+ newDescriptorBuffer.append(descriptorClassEnumeration.nextFluff());
+
+ int index = 0;
+ while (descriptorClassEnumeration.hasMoreClassNames())
+ {
+ String className = descriptorClassEnumeration.nextClassName();
+ boolean isInnerClassName = descriptorClassEnumeration.isInnerClassName();
+ String fluff = descriptorClassEnumeration.nextFluff();
+
+ String newClassName = newClassName(className,
+ referencedClasses[index++]);
+
+ // Strip the outer class name again, if it's an inner class.
+ if (isInnerClassName)
+ {
+ newClassName =
+ newClassName.substring(newClassName.lastIndexOf(ClassConstants.INNER_CLASS_SEPARATOR)+1);
+ }
+
+ newDescriptorBuffer.append(newClassName);
+ newDescriptorBuffer.append(fluff);
+ }
+
+ return newDescriptorBuffer.toString();
+ }
+
+
+ /**
+ * Returns a unique class member name, based on the given name and descriptor.
+ */
+ private String newUniqueMemberName(String name, String descriptor)
+ {
+ return name.equals(ClassConstants.METHOD_NAME_INIT) ?
+ ClassConstants.METHOD_NAME_INIT :
+ name + ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode()));
+ }
+
+
+ /**
+ * Returns the new class name based on the given class name and the new
+ * name of the given referenced class. Class names of array types
+ * are handled properly.
+ */
+ private static String newClassName(String className,
+ Clazz referencedClass)
+ {
+ // If there is no referenced class, the class name won't change.
+ if (referencedClass == null)
+ {
+ return className;
+ }
+
+ // Reconstruct the class name.
+ String newClassName = referencedClass.getName();
+
+ // Is it an array type?
+ if (className.charAt(0) == ClassConstants.TYPE_ARRAY)
+ {
+ // Add the array prefixes and suffix "[L...;".
+ newClassName =
+ className.substring(0, className.indexOf(ClassConstants.TYPE_CLASS_START)+1) +
+ newClassName +
+ ClassConstants.TYPE_CLASS_END;
+ }
+
+ return newClassName;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeComposer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeComposer.java
new file mode 100644
index 0000000000..a3de9a9d66
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeComposer.java
@@ -0,0 +1,1069 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassPrinter;
+import proguard.util.ArrayUtil;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor accumulates instructions and exceptions, and then
+ * copies them into code attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class CodeAttributeComposer
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ExceptionInfoVisitor,
+ StackMapFrameVisitor,
+ VerificationTypeVisitor,
+ LineNumberInfoVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ public static boolean DEBUG = false;
+ //*/
+
+
+ private static final int MAXIMUM_LEVELS = 32;
+ private static final int INVALID = -1;
+
+
+ private final boolean allowExternalBranchTargets;
+ private final boolean allowExternalExceptionHandlers;
+ private final boolean shrinkInstructions;
+
+ private int maximumCodeLength;
+ private int codeLength;
+ private int exceptionTableLength;
+ private int lineNumberTableLength;
+ private int level = -1;
+
+ private byte[] code = new byte[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int[] oldInstructionOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+
+ private final int[] codeFragmentOffsets = new int[MAXIMUM_LEVELS];
+ private final int[] codeFragmentLengths = new int[MAXIMUM_LEVELS];
+ private final int[][] instructionOffsetMap = new int[MAXIMUM_LEVELS][ClassConstants.TYPICAL_CODE_LENGTH + 1];
+
+ private ExceptionInfo[] exceptionTable = new ExceptionInfo[ClassConstants.TYPICAL_EXCEPTION_TABLE_LENGTH];
+ private LineNumberInfo[] lineNumberTable = new LineNumberInfo[ClassConstants.TYPICAL_LINE_NUMBER_TABLE_LENGTH];
+
+ private int expectedStackMapFrameOffset;
+
+ private final StackSizeUpdater stackSizeUpdater = new StackSizeUpdater();
+ private final VariableSizeUpdater variableSizeUpdater = new VariableSizeUpdater();
+ private final InstructionWriter instructionWriter = new InstructionWriter();
+
+
+ /**
+ * Creates a new CodeAttributeComposer that doesn't allow external branch
+ * targets or exception handlers and that automatically shrinks
+ * instructions.
+ */
+ public CodeAttributeComposer()
+ {
+ this(false, false, true);
+ }
+
+
+ /**
+ * Creates a new CodeAttributeComposer.
+ * @param allowExternalBranchTargets specifies whether branch targets
+ * can lie outside the code fragment
+ * of the branch instructions.
+ * @param allowExternalExceptionHandlers specifies whether exception
+ * handlers can lie outside the code
+ * fragment in which exceptions are
+ * defined.
+ * @param shrinkInstructions specifies whether instructions
+ * should automatically be shrunk
+ * before being written.
+ */
+ public CodeAttributeComposer(boolean allowExternalBranchTargets,
+ boolean allowExternalExceptionHandlers,
+ boolean shrinkInstructions)
+ {
+ this.allowExternalBranchTargets = allowExternalBranchTargets;
+ this.allowExternalExceptionHandlers = allowExternalExceptionHandlers;
+ this.shrinkInstructions = shrinkInstructions;
+ }
+
+
+ /**
+ * Starts a new code definition.
+ */
+ public void reset()
+ {
+ maximumCodeLength = 0;
+ codeLength = 0;
+ exceptionTableLength = 0;
+ lineNumberTableLength = 0;
+ level = -1;
+
+ // Make sure the instruction writer has at least the same buffer size
+ // as the local arrays.
+ instructionWriter.reset(code.length);
+ }
+
+
+ /**
+ * Starts a new code fragment. Branch instructions that are added are
+ * assumed to be relative within such code fragments.
+ * @param maximumCodeFragmentLength the maximum length of the code that will
+ * be added as part of this fragment (more
+ * precisely, the maximum old instruction
+ * offset or label that is specified, plus
+ * one).
+ */
+ public void beginCodeFragment(int maximumCodeFragmentLength)
+ {
+ level++;
+
+ if (level >= MAXIMUM_LEVELS)
+ {
+ throw new IllegalArgumentException("Maximum number of code fragment levels exceeded ["+level+"]");
+ }
+
+ // Make sure there is sufficient space for adding the code fragment.
+ // It's only a rough initial estimate for the code length, not even
+ // necessarily a length expressed in bytes.
+ maximumCodeLength += maximumCodeFragmentLength;
+
+ ensureCodeLength(maximumCodeLength);
+
+ // Try to reuse the previous array for this code fragment.
+ if (instructionOffsetMap[level].length <= maximumCodeFragmentLength)
+ {
+ instructionOffsetMap[level] = new int[maximumCodeFragmentLength + 1];
+ }
+
+ // Initialize the offset map.
+ for (int index = 0; index <= maximumCodeFragmentLength; index++)
+ {
+ instructionOffsetMap[level][index] = INVALID;
+ }
+
+ // Remember the location of the code fragment.
+ codeFragmentOffsets[level] = codeLength;
+ codeFragmentLengths[level] = maximumCodeFragmentLength;
+ }
+
+
+ /**
+ * Appends the given instruction with the given old offset.
+ * Branch instructions must fit, for instance by enabling automatic
+ * shrinking of instructions.
+ * @param oldInstructionOffset the old offset of the instruction, to which
+ * branches and other references in the current
+ * code fragment are pointing.
+ * @param instruction the instruction to be appended.
+ */
+ public void appendInstruction(int oldInstructionOffset,
+ Instruction instruction)
+ {
+ if (shrinkInstructions)
+ {
+ instruction = instruction.shrink();
+ }
+
+ if (DEBUG)
+ {
+ println("["+codeLength+"] <- ", instruction.toString(oldInstructionOffset));
+ }
+
+ // Make sure the code and offset arrays are large enough.
+ int newCodeLength = codeLength + instruction.length(codeLength);
+
+ ensureCodeLength(newCodeLength);
+
+ // Remember the old offset of the appended instruction.
+ oldInstructionOffsets[codeLength] = oldInstructionOffset;
+
+ // Fill out the new offset of the appended instruction.
+ instructionOffsetMap[level][oldInstructionOffset] = codeLength;
+
+ // Write the instruction. The instruction writer may widen it later on,
+ // if necessary.
+ instruction.accept(null,
+ null,
+ new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
+ codeLength,
+ instructionWriter);
+ //instruction.write(code, codeLength);
+
+ // Continue appending at the next instruction offset.
+ codeLength = newCodeLength;
+ }
+
+
+ /**
+ * Appends the given label with the given old offset.
+ * @param oldInstructionOffset the old offset of the label, to which
+ * branches and other references in the current
+ * code fragment are pointing.
+ */
+ public void appendLabel(int oldInstructionOffset)
+ {
+ if (DEBUG)
+ {
+ println("["+codeLength+"] <- ", "[" + oldInstructionOffset + "] (label)");
+ }
+
+ // Make sure the code and offset arrays are large enough.
+ ensureCodeLength(codeLength + 1);
+
+ // Remember the old offset of the following instruction.
+ oldInstructionOffsets[codeLength] = oldInstructionOffset;
+
+ // Fill out the new offset of the following instruction.
+ instructionOffsetMap[level][oldInstructionOffset] = codeLength;
+ }
+
+
+ /**
+ * Appends the given instruction without defined offsets.
+ * @param instructions the instructions to be appended.
+ */
+ public void appendInstructions(Instruction[] instructions)
+ {
+ for (int index = 0; index < instructions.length; index++)
+ {
+ appendInstruction(instructions[index]);
+ }
+ }
+
+
+ /**
+ * Appends the given instruction without a defined offset.
+ * Branch instructions should have a label, to allow computing the
+ * new relative offset.
+ * Branch instructions must fit, for instance by enabling automatic
+ * shrinking of instructions.
+ * @param instruction the instruction to be appended.
+ */
+ public void appendInstruction(Instruction instruction)
+ {
+ if (shrinkInstructions)
+ {
+ instruction = instruction.shrink();
+ }
+
+ if (DEBUG)
+ {
+ println("["+codeLength+"] <- ", instruction.toString());
+ }
+
+ // Make sure the code array is large enough.
+ int newCodeLength = codeLength + instruction.length(codeLength);
+
+ ensureCodeLength(newCodeLength);
+
+ // Write the instruction. The instruction writer may widen it later on,
+ // if necessary.
+ instruction.accept(null,
+ null,
+ new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
+ codeLength,
+ instructionWriter);
+ //instruction.write(code, codeLength);
+
+ // Continue appending at the next instruction offset.
+ codeLength = newCodeLength;
+ }
+
+
+ /**
+ * Appends the given exception to the exception table.
+ * @param exceptionInfo the exception to be appended.
+ */
+ public void appendException(ExceptionInfo exceptionInfo)
+ {
+ if (DEBUG)
+ {
+ print(" ", "Exception ["+exceptionInfo.u2startPC+" -> "+exceptionInfo.u2endPC+": "+exceptionInfo.u2handlerPC+"]");
+ }
+
+ // Remap the exception right away.
+ visitExceptionInfo(null, null, null, exceptionInfo);
+
+ if (DEBUG)
+ {
+ System.out.println(" -> ["+exceptionInfo.u2startPC+" -> "+exceptionInfo.u2endPC+": "+exceptionInfo.u2handlerPC+"]");
+ }
+
+ // Don't add the exception if its instruction range is empty.
+ if (exceptionInfo.u2startPC == exceptionInfo.u2endPC)
+ {
+ if (DEBUG)
+ {
+ println(" ", " (not added because of empty instruction range)");
+ }
+
+ return;
+ }
+
+ // Add the exception.
+ exceptionTable =
+ (ExceptionInfo[])ArrayUtil.add(exceptionTable,
+ exceptionTableLength++,
+ exceptionInfo);
+ }
+
+
+ /**
+ * Inserts the given line number at the appropriate position in the line
+ * number table.
+ * @param lineNumberInfo the line number to be inserted.
+ * @return the index where the line number was actually inserted.
+ */
+ public int insertLineNumber(LineNumberInfo lineNumberInfo)
+ {
+ return insertLineNumber(0, lineNumberInfo);
+ }
+
+
+ /**
+ * Inserts the given line number at the appropriate position in the line
+ * number table.
+ * @param minimumIndex the minimum index where the line number may be
+ * inserted.
+ * @param lineNumberInfo the line number to be inserted.
+ * @return the index where the line number was inserted.
+ */
+ public int insertLineNumber(int minimumIndex, LineNumberInfo lineNumberInfo)
+ {
+ if (DEBUG)
+ {
+ print(" ", "Line number ["+lineNumberInfo.u2startPC+"]");
+ }
+
+ // Remap the line number right away.
+ visitLineNumberInfo(null, null, null, lineNumberInfo);
+
+ if (DEBUG)
+ {
+ System.out.println(" -> ["+lineNumberInfo.u2startPC+"] line "+lineNumberInfo.u2lineNumber+(lineNumberInfo.getSource()==null ? "":" ["+lineNumberInfo.getSource()+"]"));
+ }
+
+ lineNumberTable =
+ (LineNumberInfo[])ArrayUtil.extendArray(lineNumberTable,
+ lineNumberTableLength + 1);
+
+ // Find the insertion index, starting from the end.
+ // Don't insert before a negative line number, in case of a tie.
+ int index = lineNumberTableLength++;
+ while (index > minimumIndex &&
+ (lineNumberTable[index - 1].u2startPC > lineNumberInfo.u2startPC ||
+ lineNumberTable[index - 1].u2startPC >= lineNumberInfo.u2startPC &&
+ lineNumberTable[index - 1].u2lineNumber >= 0))
+ {
+ lineNumberTable[index] = lineNumberTable[--index];
+ }
+
+ lineNumberTable[index] = lineNumberInfo;
+
+ return index;
+ }
+
+
+ /**
+ * Appends the given line number to the line number table.
+ * @param lineNumberInfo the line number to be appended.
+ */
+ public void appendLineNumber(LineNumberInfo lineNumberInfo)
+ {
+ if (DEBUG)
+ {
+ print(" ", "Line number ["+lineNumberInfo.u2startPC+"]");
+ }
+
+ // Remap the line number right away.
+ visitLineNumberInfo(null, null, null, lineNumberInfo);
+
+ if (DEBUG)
+ {
+ System.out.println(" -> ["+lineNumberInfo.u2startPC+"] line "+lineNumberInfo.u2lineNumber+(lineNumberInfo.getSource()==null ? "":" ["+lineNumberInfo.getSource()+"]"));
+ }
+
+ // Add the line number.
+ lineNumberTable =
+ (LineNumberInfo[])ArrayUtil.add(lineNumberTable,
+ lineNumberTableLength++,
+ lineNumberInfo);
+ }
+
+
+ /**
+ * Wraps up the current code fragment, continuing with the previous one on
+ * the stack.
+ */
+ public void endCodeFragment()
+ {
+ if (level < 0)
+ {
+ throw new IllegalArgumentException("Code fragment not begun ["+level+"]");
+ }
+
+ // Remap the instructions of the code fragment.
+ int instructionOffset = codeFragmentOffsets[level];
+ while (instructionOffset < codeLength)
+ {
+ // Get the next instruction.
+ Instruction instruction = InstructionFactory.create(code, instructionOffset);
+
+ // Does this instruction still have to be remapped?
+ if (oldInstructionOffsets[instructionOffset] >= 0)
+ {
+ // Adapt the instruction for its new offset.
+ instruction.accept(null, null, null, instructionOffset, this);
+
+ // Write the instruction back. The instruction writer may still
+ // widen it later on, if necessary.
+ instruction.accept(null,
+ null,
+ new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
+ instructionOffset,
+ instructionWriter);
+ //instruction.write(code, codeLength);
+ }
+
+ // Continue remapping at the next instruction offset.
+ instructionOffset += instruction.length(instructionOffset);
+ }
+
+ // Correct the estimated maximum code length, now that we know the
+ // actual length of this code fragment.
+ maximumCodeLength += codeLength - codeFragmentOffsets[level] -
+ codeFragmentLengths[level];
+
+ // Try to remap the exception handlers that couldn't be remapped before.
+ if (allowExternalExceptionHandlers)
+ {
+ for (int index = 0; index < exceptionTableLength; index++)
+ {
+ ExceptionInfo exceptionInfo = exceptionTable[index];
+
+ // Unmapped exception handlers are still negated.
+ int handlerPC = -exceptionInfo.u2handlerPC;
+ if (handlerPC > 0)
+ {
+ if (remappableExceptionHandler(handlerPC))
+ {
+ exceptionInfo.u2handlerPC = newInstructionOffset(handlerPC);
+ }
+ else if (level == 0)
+ {
+ throw new IllegalStateException("Couldn't remap exception handler offset ["+handlerPC+"]");
+ }
+ }
+ }
+ }
+
+ level--;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (DEBUG)
+ {
+ System.out.println("CodeAttributeComposer: putting results in ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ }
+
+ if (level != -1)
+ {
+ throw new IllegalArgumentException("Code fragment not ended ["+level+"]");
+ }
+
+ level++;
+
+ // Make sure the code attribute has sufficient space for the composed
+ // code.
+ if (codeAttribute.u4codeLength < codeLength)
+ {
+ codeAttribute.code = new byte[codeLength];
+ }
+
+ // Copy the composed code over into the code attribute.
+ codeAttribute.u4codeLength = codeLength;
+ System.arraycopy(code, 0, codeAttribute.code, 0, codeLength);
+
+ // Remove exceptions with empty code blocks (done before).
+ //exceptionTableLength =
+ // removeEmptyExceptions(exceptionTable, exceptionTableLength);
+
+ // Make sure the exception table has sufficient space for the composed
+ // exceptions.
+ if (codeAttribute.exceptionTable.length < exceptionTableLength)
+ {
+ codeAttribute.exceptionTable = new ExceptionInfo[exceptionTableLength];
+ }
+
+ // Copy the exception table.
+ codeAttribute.u2exceptionTableLength = exceptionTableLength;
+ System.arraycopy(exceptionTable, 0, codeAttribute.exceptionTable, 0, exceptionTableLength);
+
+ // Update the maximum stack size and local variable frame size.
+ stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
+ variableSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Add a new line number table for the line numbers, if necessary.
+ if (lineNumberTableLength > 0 &&
+ codeAttribute.getAttribute(clazz, ClassConstants.ATTR_LineNumberTable) == null)
+ {
+ int attributeNameIndex =
+ new ConstantPoolEditor((ProgramClass)clazz)
+ .addUtf8Constant(ClassConstants.ATTR_LineNumberTable);
+
+ new AttributesEditor((ProgramClass)clazz, (ProgramMember)method, codeAttribute, false)
+ .addAttribute(new LineNumberTableAttribute(attributeNameIndex, 0, null));
+ }
+
+ // Copy the line number table and the local variable table.
+ codeAttribute.attributesAccept(clazz, method, this);
+
+ // Remap the exception table (done before).
+ //codeAttribute.exceptionsAccept(clazz, method, this);
+
+ // Remove exceptions with empty code blocks (done before).
+ //codeAttribute.u2exceptionTableLength =
+ // removeEmptyExceptions(codeAttribute.exceptionTable,
+ // codeAttribute.u2exceptionTableLength);
+
+ // Make sure instructions are widened if necessary.
+ instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);
+
+ level--;
+
+ if (DEBUG)
+ {
+ codeAttribute.accept(clazz, method, new ClassPrinter());
+ }
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ // Remap all stack map entries.
+ expectedStackMapFrameOffset = -1;
+ stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ // Remap all stack map table entries.
+ expectedStackMapFrameOffset = 0;
+ stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ // Didn't we get line number new definitions?
+ if (lineNumberTableLength == 0)
+ {
+ // Remap all line number table entries of the existing table.
+ lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
+ }
+ else
+ {
+ // Remove line numbers with empty code blocks.
+ // Actually, we'll do this elsewhere, to allow processing the
+ // line numbers of inlined methods.
+ //lineNumberTableLength =
+ // removeEmptyLineNumbers(lineNumberTable,
+ // lineNumberTableLength,
+ // codeAttribute.u4codeLength);
+
+ // Copy the line number table.
+ lineNumberTableAttribute.lineNumberTable = new LineNumberInfo[lineNumberTableLength];
+ lineNumberTableAttribute.u2lineNumberTableLength = lineNumberTableLength;
+ System.arraycopy(lineNumberTable, 0, lineNumberTableAttribute.lineNumberTable, 0, lineNumberTableLength);
+ }
+ }
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Remap all local variable table entries.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+
+ // Remove local variables with empty code blocks.
+ localVariableTableAttribute.u2localVariableTableLength =
+ removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable,
+ localVariableTableAttribute.u2localVariableTableLength,
+ codeAttribute.u2maxLocals);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Remap all local variable table entries.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+
+ // Remove local variables with empty code blocks.
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength =
+ removeEmptyLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength,
+ codeAttribute.u2maxLocals);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ try
+ {
+ // Adjust the branch offset.
+ branchInstruction.branchOffset =
+ newBranchOffset(offset, branchInstruction.branchOffset);
+
+ // Don't remap this instruction again.
+ oldInstructionOffsets[offset] = -1;
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (level == 0 || !allowExternalBranchTargets)
+ {
+ throw e;
+ }
+ }
+ }
+
+
+ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ {
+ try
+ {
+ // TODO: We're assuming we can adjust no offsets or all offsets at once.
+ // Adjust the default jump offset.
+ switchInstruction.defaultOffset =
+ newBranchOffset(offset, switchInstruction.defaultOffset);
+
+ // Adjust the jump offsets.
+ updateJumpOffsets(offset,
+ switchInstruction.jumpOffsets);
+
+ // Don't remap this instruction again.
+ oldInstructionOffsets[offset] = -1;
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (level == 0 || !allowExternalBranchTargets)
+ {
+ throw e;
+ }
+ }
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ // Remap the code offsets. Note that the instruction offset map also has
+ // an entry for the first offset after the code, for u2endPC.
+ exceptionInfo.u2startPC = newInstructionOffset(exceptionInfo.u2startPC);
+ exceptionInfo.u2endPC = newInstructionOffset(exceptionInfo.u2endPC);
+
+ // See if we can remap the handler right away. Unmapped exception
+ // handlers are negated, in order to mark them as external.
+ int handlerPC = exceptionInfo.u2handlerPC;
+ exceptionInfo.u2handlerPC =
+ !allowExternalExceptionHandlers ||
+ remappableExceptionHandler(handlerPC) ?
+ newInstructionOffset(handlerPC) :
+ -handlerPC;
+ }
+
+
+ // Implementations for StackMapFrameVisitor.
+
+ public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)
+ {
+ // Remap the stack map frame offset.
+ int stackMapFrameOffset = newInstructionOffset(offset);
+
+ int offsetDelta = stackMapFrameOffset;
+
+ // Compute the offset delta if the frame is part of a stack map frame
+ // table (for JDK 6.0) instead of a stack map (for Java Micro Edition).
+ if (expectedStackMapFrameOffset >= 0)
+ {
+ offsetDelta -= expectedStackMapFrameOffset;
+
+ expectedStackMapFrameOffset = stackMapFrameOffset + 1;
+ }
+
+ stackMapFrame.u2offsetDelta = offsetDelta;
+ }
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ // Remap the stack map frame offset.
+ visitAnyStackMapFrame(clazz, method, codeAttribute, offset, sameOneFrame);
+
+ // Remap the verification type offset.
+ sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ // Remap the stack map frame offset.
+ visitAnyStackMapFrame(clazz, method, codeAttribute, offset, moreZeroFrame);
+
+ // Remap the verification type offsets.
+ moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ // Remap the stack map frame offset.
+ visitAnyStackMapFrame(clazz, method, codeAttribute, offset, fullFrame);
+
+ // Remap the verification type offsets.
+ fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
+ fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
+
+
+ public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
+ {
+ // Remap the offset of the 'new' instruction.
+ uninitializedType.u2newInstructionOffset = newInstructionOffset(uninitializedType.u2newInstructionOffset);
+ }
+
+
+ // Implementations for LineNumberInfoVisitor.
+
+ public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
+ {
+ // Remap the code offset.
+ lineNumberInfo.u2startPC = newInstructionOffset(lineNumberInfo.u2startPC);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Remap the code offset and length.
+ // TODO: The local variable frame might not be strictly preserved.
+ int startPC = newInstructionOffset(localVariableInfo.u2startPC);
+ int endPC = newInstructionOffset(localVariableInfo.u2startPC +
+ localVariableInfo.u2length);
+
+ localVariableInfo.u2startPC = startPC;
+ localVariableInfo.u2length = endPC - startPC;
+ }
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Remap the code offset and length.
+ // TODO: The local variable frame might not be strictly preserved.
+ int startPC = newInstructionOffset(localVariableTypeInfo.u2startPC);
+ int endPC = newInstructionOffset(localVariableTypeInfo.u2startPC +
+ localVariableTypeInfo.u2length);
+
+ localVariableTypeInfo.u2startPC = startPC;
+ localVariableTypeInfo.u2length = endPC - startPC;
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Make sure the code arrays have at least the given size.
+ */
+ private void ensureCodeLength(int newCodeLength)
+ {
+ if (code.length < newCodeLength)
+ {
+ // Add 20% to avoid extending the arrays too often.
+ newCodeLength = newCodeLength * 6 / 5;
+
+ code = ArrayUtil.extendArray(code, newCodeLength);
+ oldInstructionOffsets = ArrayUtil.extendArray(oldInstructionOffsets, newCodeLength);
+
+ instructionWriter.extend(newCodeLength);
+ }
+ }
+
+
+ /**
+ * Adjusts the given jump offsets for the instruction at the given offset.
+ */
+ private void updateJumpOffsets(int offset, int[] jumpOffsets)
+ {
+ for (int index = 0; index < jumpOffsets.length; index++)
+ {
+ jumpOffsets[index] = newBranchOffset(offset, jumpOffsets[index]);
+ }
+ }
+
+
+ /**
+ * Computes the new branch offset for the instruction at the given new offset
+ * with the given old branch offset.
+ */
+ private int newBranchOffset(int newInstructionOffset, int oldBranchOffset)
+ {
+ if (newInstructionOffset < 0 ||
+ newInstructionOffset > codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+newInstructionOffset +"] in code with length ["+codeLength+"]");
+ }
+
+ int oldInstructionOffset = oldInstructionOffsets[newInstructionOffset];
+
+ // For ordinary branch instructions, we can compute the offset
+ // relative to the instruction itself.
+ return newInstructionOffset(oldInstructionOffset + oldBranchOffset) -
+ newInstructionOffset;
+ }
+
+
+ /**
+ * Computes the new instruction offset for the instruction at the given old
+ * offset.
+ */
+ private int newInstructionOffset(int oldInstructionOffset)
+ {
+ if (oldInstructionOffset < 0 ||
+ oldInstructionOffset > codeFragmentLengths[level])
+ {
+ throw new IllegalArgumentException("Instruction offset ["+oldInstructionOffset +"] out of range in code fragment with length ["+codeFragmentLengths[level]+"] at level "+level);
+ }
+
+ int newInstructionOffset = instructionOffsetMap[level][oldInstructionOffset];
+ if (newInstructionOffset == INVALID)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+oldInstructionOffset +"] in code fragment at level "+level);
+ }
+
+ return newInstructionOffset;
+ }
+
+
+ /**
+ * Returns whether the given old exception handler can be remapped in the
+ * current code fragment.
+ */
+ private boolean remappableExceptionHandler(int oldInstructionOffset)
+ {
+ // Can we index in the array?
+ if (oldInstructionOffset > codeFragmentLengths[level])
+ {
+ return false;
+ }
+
+ // Do we have a valid new instruction offset, but not yet right after
+ // the code? That offset is only labeled for mapping try blocks, not
+ // for mapping handlers.
+ int newInstructionOffset =
+ instructionOffsetMap[level][oldInstructionOffset];
+
+ return newInstructionOffset > INVALID &&
+ newInstructionOffset < codeLength;
+ }
+
+
+ /**
+ * Returns the given list of exceptions, without the ones that have empty
+ * code blocks.
+ */
+ private int removeEmptyExceptions(ExceptionInfo[] exceptionInfos,
+ int exceptionInfoCount)
+ {
+ // Overwrite all empty exceptions.
+ int newIndex = 0;
+ for (int index = 0; index < exceptionInfoCount; index++)
+ {
+ ExceptionInfo exceptionInfo = exceptionInfos[index];
+ if (exceptionInfo.u2startPC < exceptionInfo.u2endPC)
+ {
+ exceptionInfos[newIndex++] = exceptionInfo;
+ }
+ }
+
+ // Clear the unused array entries.
+ Arrays.fill(exceptionInfos, newIndex, exceptionInfoCount, null);
+
+ return newIndex;
+ }
+
+
+ /**
+ * Returns the given list of line numbers, without the ones that have empty
+ * code blocks or that exceed the code size.
+ */
+ private int removeEmptyLineNumbers(LineNumberInfo[] lineNumberInfos,
+ int lineNumberInfoCount,
+ int codeLength)
+ {
+ // Overwrite all empty line number entries.
+ int newIndex = 0;
+ for (int index = 0; index < lineNumberInfoCount; index++)
+ {
+ LineNumberInfo lineNumberInfo = lineNumberInfos[index];
+ int startPC = lineNumberInfo.u2startPC;
+ if (startPC < codeLength &&
+ (index == 0 || startPC > lineNumberInfos[index-1].u2startPC))
+ {
+ lineNumberInfos[newIndex++] = lineNumberInfo;
+ }
+ }
+
+ // Clear the unused array entries.
+ Arrays.fill(lineNumberInfos, newIndex, lineNumberInfoCount, null);
+
+ return newIndex;
+ }
+
+
+ /**
+ * Returns the given list of local variables, without the ones that have empty
+ * code blocks or that exceed the actual number of local variables.
+ */
+ private int removeEmptyLocalVariables(LocalVariableInfo[] localVariableInfos,
+ int localVariableInfoCount,
+ int maxLocals)
+ {
+ // Overwrite all empty local variable entries.
+ int newIndex = 0;
+ for (int index = 0; index < localVariableInfoCount; index++)
+ {
+ LocalVariableInfo localVariableInfo = localVariableInfos[index];
+ if (localVariableInfo.u2length > 0 &&
+ localVariableInfo.u2index < maxLocals)
+ {
+ localVariableInfos[newIndex++] = localVariableInfo;
+ }
+ }
+
+ // Clear the unused array entries.
+ Arrays.fill(localVariableInfos, newIndex, localVariableInfoCount, null);
+
+ return newIndex;
+ }
+
+
+ /**
+ * Returns the given list of local variable types, without the ones that
+ * have empty code blocks or that exceed the actual number of local variables.
+ */
+ private int removeEmptyLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
+ int localVariableTypeInfoCount,
+ int maxLocals)
+ {
+ // Overwrite all empty local variable type entries.
+ int newIndex = 0;
+ for (int index = 0; index < localVariableTypeInfoCount; index++)
+ {
+ LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
+ if (localVariableTypeInfo.u2length > 0 &&
+ localVariableTypeInfo.u2index < maxLocals)
+ {
+ localVariableTypeInfos[newIndex++] = localVariableTypeInfo;
+ }
+ }
+
+ // Clear the unused array entries.
+ Arrays.fill(localVariableTypeInfos, newIndex, localVariableTypeInfoCount, null);
+
+ return newIndex;
+ }
+
+
+ private void println(String string1, String string2)
+ {
+ print(string1, string2);
+
+ System.out.println();
+ }
+
+ private void print(String string1, String string2)
+ {
+ System.out.print(string1);
+
+ for (int index = 0; index < level; index++)
+ {
+ System.out.print(" ");
+ }
+
+ System.out.print(string2);
+ }
+
+
+ public static void main(String[] args)
+ {
+ CodeAttributeComposer composer = new CodeAttributeComposer();
+
+ composer.beginCodeFragment(4);
+ composer.appendInstruction(0, new SimpleInstruction(InstructionConstants.OP_ICONST_0));
+ composer.appendInstruction(1, new VariableInstruction(InstructionConstants.OP_ISTORE, 0));
+ composer.appendInstruction(2, new BranchInstruction(InstructionConstants.OP_GOTO, 1));
+
+ composer.beginCodeFragment(4);
+ composer.appendInstruction(0, new VariableInstruction(InstructionConstants.OP_IINC, 0, 1));
+ composer.appendInstruction(1, new VariableInstruction(InstructionConstants.OP_ILOAD, 0));
+ composer.appendInstruction(2, new SimpleInstruction(InstructionConstants.OP_ICONST_5));
+ composer.appendInstruction(3, new BranchInstruction(InstructionConstants.OP_IFICMPLT, -3));
+ composer.endCodeFragment();
+
+ composer.appendInstruction(3, new SimpleInstruction(InstructionConstants.OP_RETURN));
+ composer.endCodeFragment();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeEditor.java
new file mode 100644
index 0000000000..b374705163
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeEditor.java
@@ -0,0 +1,1267 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.target.*;
+import proguard.classfile.attribute.annotation.target.visitor.*;
+import proguard.classfile.attribute.annotation.visitor.TypeAnnotationVisitor;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.util.ArrayUtil;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor accumulates specified changes to code, and then applies
+ * these accumulated changes to the code attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class CodeAttributeEditor
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ExceptionInfoVisitor,
+ StackMapFrameVisitor,
+ VerificationTypeVisitor,
+ LineNumberInfoVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ TypeAnnotationVisitor,
+ TargetInfoVisitor,
+ LocalVariableTargetElementVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ public static boolean DEBUG = false;
+ //*/
+
+
+ private final boolean updateFrameSizes;
+ private final boolean shrinkInstructions;
+
+ private int codeLength;
+ private boolean modified;
+ private boolean simple;
+
+ /*private*/public Instruction[] preInsertions = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH];
+ /*private*/public Instruction[] replacements = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH];
+ /*private*/public Instruction[] postInsertions = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH];
+ /*private*/public boolean[] deleted = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
+
+ private int[] newInstructionOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int newOffset;
+ private boolean lengthIncreased;
+
+ private int expectedStackMapFrameOffset;
+
+ private final StackSizeUpdater stackSizeUpdater = new StackSizeUpdater();
+ private final VariableSizeUpdater variableSizeUpdater = new VariableSizeUpdater();
+ private final InstructionWriter instructionWriter = new InstructionWriter();
+
+
+ /**
+ * Creates a new CodeAttributeEditor that automatically updates frame
+ * sizes and shrinks instructions.
+ */
+ public CodeAttributeEditor()
+ {
+ this(true, true);
+ }
+
+
+ /**
+ * Creates a new CodeAttributeEditor.
+ * @param updateFrameSizes specifies whether frame sizes of edited code
+ * should be updated.
+ * @param shrinkInstructions specifies whether added instructions should
+ * automatically be shrunk before being written.
+ */
+ public CodeAttributeEditor(boolean updateFrameSizes,
+ boolean shrinkInstructions)
+ {
+ this.updateFrameSizes = updateFrameSizes;
+ this.shrinkInstructions = shrinkInstructions;
+ }
+
+
+ /**
+ * Resets the accumulated code changes.
+ * @param codeLength the length of the code that will be edited next.
+ */
+ public void reset(int codeLength)
+ {
+ // Try to reuse the previous arrays.
+ if (preInsertions.length < codeLength)
+ {
+ preInsertions = new Instruction[codeLength];
+ replacements = new Instruction[codeLength];
+ postInsertions = new Instruction[codeLength];
+ deleted = new boolean[codeLength];
+ }
+ else
+ {
+ Arrays.fill(preInsertions, 0, codeLength, null);
+ Arrays.fill(replacements, 0, codeLength, null);
+ Arrays.fill(postInsertions, 0, codeLength, null);
+ Arrays.fill(deleted, 0, codeLength, false);
+ }
+
+ this.codeLength = codeLength;
+
+ modified = false;
+ simple = true;
+ }
+
+
+ /**
+ * Extends the size of the accumulated code changes.
+ * @param codeLength the length of the code that will be edited next.
+ */
+ public void extend(int codeLength)
+ {
+ // Try to reuse the previous arrays.
+ if (preInsertions.length < codeLength)
+ {
+ preInsertions = (Instruction[])ArrayUtil.extendArray(preInsertions, codeLength);
+ replacements = (Instruction[])ArrayUtil.extendArray(replacements, codeLength);
+ postInsertions = (Instruction[])ArrayUtil.extendArray(postInsertions, codeLength);
+ deleted = ArrayUtil.extendArray(deleted, codeLength);
+ }
+ else
+ {
+ Arrays.fill(preInsertions, this.codeLength, codeLength, null);
+ Arrays.fill(replacements, this.codeLength, codeLength, null);
+ Arrays.fill(postInsertions, this.codeLength, codeLength, null);
+ Arrays.fill(deleted, this.codeLength, codeLength, false);
+ }
+
+ this.codeLength = codeLength;
+ }
+
+
+ /**
+ * Remembers to place the given instruction right before the instruction
+ * at the given offset.
+ * @param instructionOffset the offset of the instruction.
+ * @param instruction the new instruction.
+ */
+ public void insertBeforeInstruction(int instructionOffset, Instruction instruction)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ preInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
+
+ modified = true;
+ simple = false;
+ }
+
+
+ /**
+ * Remembers to place the given instructions right before the instruction
+ * at the given offset.
+ * @param instructionOffset the offset of the instruction.
+ * @param instructions the new instructions.
+ */
+ public void insertBeforeInstruction(int instructionOffset, Instruction[] instructions)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ preInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
+
+ modified = true;
+ simple = false;
+ }
+
+
+ /**
+ * Remembers to replace the instruction at the given offset by the given
+ * instruction.
+ * @param instructionOffset the offset of the instruction to be replaced.
+ * @param instruction the new instruction.
+ */
+ public void replaceInstruction(int instructionOffset, Instruction instruction)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ replacements[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
+
+ modified = true;
+ }
+
+
+ /**
+ * Remembers to replace the instruction at the given offset by the given
+ * instructions.
+ * @param instructionOffset the offset of the instruction to be replaced.
+ * @param instructions the new instructions.
+ */
+ public void replaceInstruction(int instructionOffset, Instruction[] instructions)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ replacements[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
+
+ modified = true;
+ }
+
+
+ /**
+ * Remembers to place the given instruction right after the instruction
+ * at the given offset.
+ * @param instructionOffset the offset of the instruction.
+ * @param instruction the new instruction.
+ */
+ public void insertAfterInstruction(int instructionOffset, Instruction instruction)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ postInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
+
+ modified = true;
+ simple = false;
+ }
+
+
+ /**
+ * Remembers to place the given instructions right after the instruction
+ * at the given offset.
+ * @param instructionOffset the offset of the instruction.
+ * @param instructions the new instructions.
+ */
+ public void insertAfterInstruction(int instructionOffset, Instruction[] instructions)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ postInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
+
+ modified = true;
+ simple = false;
+ }
+
+
+ /**
+ * Remembers to delete the instruction at the given offset.
+ * @param instructionOffset the offset of the instruction to be deleted.
+ */
+ public void deleteInstruction(int instructionOffset)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ deleted[instructionOffset] = true;
+
+ modified = true;
+ simple = false;
+ }
+
+
+ /**
+ * Remembers not to delete the instruction at the given offset.
+ * @param instructionOffset the offset of the instruction not to be deleted.
+ */
+ public void undeleteInstruction(int instructionOffset)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ deleted[instructionOffset] = false;
+ }
+
+
+ /**
+ * Clears all modifications of the instruction at the given offset.
+ * @param instructionOffset the offset of the instruction to be deleted.
+ */
+ public void clearModifications(int instructionOffset)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ preInsertions[instructionOffset] = null;
+ replacements[instructionOffset] = null;
+ postInsertions[instructionOffset] = null;
+ deleted[instructionOffset] = false;
+ }
+
+
+ /**
+ * Returns whether the code has been modified in any way.
+ */
+ public boolean isModified()
+ {
+ return modified;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset has been modified
+ * in any way.
+ */
+ public boolean isModified(int instructionOffset)
+ {
+ return preInsertions[instructionOffset] != null ||
+ replacements[instructionOffset] != null ||
+ postInsertions[instructionOffset] != null ||
+ deleted[instructionOffset];
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ // TODO: Remove this when the code has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while editing code:");
+ System.err.println(" Class = ["+clazz.getName()+"]");
+ System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+
+ throw ex;
+ }
+ }
+
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Do we have to update the code?
+ if (modified)
+ {
+ if (DEBUG)
+ {
+ System.out.println("CodeAttributeEditor: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ }
+
+ // Can we perform a faster simple replacement of instructions?
+ if (canPerformSimpleReplacements(codeAttribute))
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Simple editing");
+ }
+
+ // Simply overwrite the instructions.
+ performSimpleReplacements(codeAttribute);
+ }
+ else
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Full editing");
+ }
+
+ // Move and remap the instructions.
+ codeAttribute.u4codeLength =
+ updateInstructions(clazz, method, codeAttribute);
+
+ // Update the exception table.
+ codeAttribute.exceptionsAccept(clazz, method, this);
+
+ // Remove exceptions with empty code blocks.
+ codeAttribute.u2exceptionTableLength =
+ removeEmptyExceptions(codeAttribute.exceptionTable,
+ codeAttribute.u2exceptionTableLength);
+
+ // Update the line number table and the local variable tables.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+ // Make sure instructions are widened if necessary.
+ instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+ // Update the maximum stack size and local variable frame size.
+ if (updateFrameSizes)
+ {
+ stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
+ variableSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ // Update all stack map entries.
+ expectedStackMapFrameOffset = -1;
+ stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ // Update all stack map table entries.
+ expectedStackMapFrameOffset = 0;
+ stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ // Update all line number table entries.
+ lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
+
+ // Remove line numbers with empty code blocks.
+// lineNumberTableAttribute.u2lineNumberTableLength =
+// removeEmptyLineNumbers(lineNumberTableAttribute.lineNumberTable,
+// lineNumberTableAttribute.u2lineNumberTableLength,
+// codeAttribute.u4codeLength);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Update all local variable table entries.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Update all local variable table entries.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute)
+ {
+ typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this);
+ }
+
+
+ /**
+ * Checks if it is possible to modifies the given code without having to
+ * update any offsets.
+ * @param codeAttribute the code to be changed.
+ * @return the new code length.
+ */
+ private boolean canPerformSimpleReplacements(CodeAttribute codeAttribute)
+ {
+ if (!simple)
+ {
+ return false;
+ }
+
+ byte[] code = codeAttribute.code;
+ int codeLength = codeAttribute.u4codeLength;
+
+ // Go over all replacement instructions.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ // Check if the replacement instruction, if any, has a different
+ // length than the original instruction.
+ Instruction replacementInstruction = replacements[offset];
+ if (replacementInstruction != null &&
+ replacementInstruction.length(offset) !=
+ InstructionFactory.create(code, offset).length(offset))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Modifies the given code without updating any offsets.
+ * @param codeAttribute the code to be changed.
+ */
+ private void performSimpleReplacements(CodeAttribute codeAttribute)
+ {
+ int codeLength = codeAttribute.u4codeLength;
+
+ // Go over all replacement instructions.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ // Overwrite the original instruction with the replacement
+ // instruction if any.
+ Instruction replacementInstruction = replacements[offset];
+ if (replacementInstruction != null)
+ {
+ replacementInstruction.write(codeAttribute, offset);
+
+ if (DEBUG)
+ {
+ System.out.println(" Replaced "+replacementInstruction.toString(offset));
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Modifies the given code based on the previously specified changes.
+ * @param clazz the class file of the code to be changed.
+ * @param method the method of the code to be changed.
+ * @param codeAttribute the code to be changed.
+ * @return the new code length.
+ */
+ private int updateInstructions(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute)
+ {
+ byte[] oldCode = codeAttribute.code;
+ int oldLength = codeAttribute.u4codeLength;
+
+ // Make sure there is a sufficiently large instruction offset map.
+ if (newInstructionOffsets.length < oldLength + 1)
+ {
+ newInstructionOffsets = new int[oldLength + 1];
+ }
+
+ // Fill out the instruction offset map.
+ int newLength = mapInstructions(oldCode,
+ oldLength);
+
+ // Create a new code array if necessary.
+ if (lengthIncreased)
+ {
+ codeAttribute.code = new byte[newLength];
+ }
+
+ // Prepare for possible widening of instructions.
+ instructionWriter.reset(newLength);
+
+ // Move the instructions into the new code array.
+ moveInstructions(clazz,
+ method,
+ codeAttribute,
+ oldCode,
+ oldLength);
+
+ // We can return the new length.
+ return newLength;
+ }
+
+
+ /**
+ * Fills out the instruction offset map for the given code block.
+ * @param oldCode the instructions to be moved.
+ * @param oldLength the code length.
+ * @return the new code length.
+ */
+ private int mapInstructions(byte[] oldCode, int oldLength)
+ {
+ // Start mapping instructions at the beginning.
+ newOffset = 0;
+ lengthIncreased = false;
+
+ int oldOffset = 0;
+ do
+ {
+ // Get the next instruction.
+ Instruction instruction = InstructionFactory.create(oldCode, oldOffset);
+
+ // Compute the mapping of the instruction.
+ mapInstruction(oldOffset, instruction);
+
+ oldOffset += instruction.length(oldOffset);
+
+ if (newOffset > oldOffset)
+ {
+ lengthIncreased = true;
+ }
+ }
+ while (oldOffset < oldLength);
+
+ // Also add an entry for the first offset after the code.
+ newInstructionOffsets[oldOffset] = newOffset;
+
+ return newOffset;
+ }
+
+
+ /**
+ * Fills out the instruction offset map for the given instruction.
+ * @param oldOffset the instruction's old offset.
+ * @param instruction the instruction to be moved.
+ */
+ private void mapInstruction(int oldOffset,
+ Instruction instruction)
+ {
+ newInstructionOffsets[oldOffset] = newOffset;
+
+ // Account for the pre-inserted instruction, if any.
+ Instruction preInstruction = preInsertions[oldOffset];
+ if (preInstruction != null)
+ {
+ newOffset += preInstruction.length(newOffset);
+ }
+
+ // Account for the replacement instruction, or for the current
+ // instruction, if it shouldn't be deleted.
+ Instruction replacementInstruction = replacements[oldOffset];
+ if (replacementInstruction != null)
+ {
+ newOffset += replacementInstruction.length(newOffset);
+ }
+ else if (!deleted[oldOffset])
+ {
+ // Note that the instruction's length may change at its new offset,
+ // e.g. if it is a switch instruction.
+ newOffset += instruction.length(newOffset);
+ }
+
+ // Account for the post-inserted instruction, if any.
+ Instruction postInstruction = postInsertions[oldOffset];
+ if (postInstruction != null)
+ {
+ newOffset += postInstruction.length(newOffset);
+ }
+ }
+
+
+ /**
+ * Moves the given code block to the new offsets.
+ * @param clazz the class file of the code to be changed.
+ * @param method the method of the code to be changed.
+ * @param codeAttribute the code to be changed.
+ * @param oldCode the original code to be moved.
+ * @param oldLength the original code length.
+ */
+ private void moveInstructions(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ byte[] oldCode,
+ int oldLength)
+ {
+ // Start writing instructions at the beginning.
+ newOffset = 0;
+
+ int oldOffset = 0;
+ do
+ {
+ // Get the next instruction.
+ Instruction instruction = InstructionFactory.create(oldCode, oldOffset);
+
+ // Move the instruction to its new offset.
+ moveInstruction(clazz,
+ method,
+ codeAttribute,
+ oldOffset,
+ instruction);
+
+ oldOffset += instruction.length(oldOffset);
+ }
+ while (oldOffset < oldLength);
+ }
+
+
+ /**
+ * Moves the given instruction to its new offset.
+ * @param clazz the class file of the code to be changed.
+ * @param method the method of the code to be changed.
+ * @param codeAttribute the code to be changed.
+ * @param oldOffset the original instruction offset.
+ * @param instruction the original instruction.
+ */
+ private void moveInstruction(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int oldOffset,
+ Instruction instruction)
+ {
+ // Update and insert the pre-inserted instruction, if any.
+ Instruction preInstruction = preInsertions[oldOffset];
+ if (preInstruction != null)
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Pre-inserted ["+oldOffset+"] -> "+preInstruction.toString(newOffset));
+ }
+
+ // Update the instruction.
+ preInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
+ }
+
+ // Update and insert the replacement instruction, or the current
+ // instruction, if it shouldn't be deleted.
+ Instruction replacementInstruction = replacements[oldOffset];
+ if (replacementInstruction != null)
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Replaced ["+oldOffset+"] -> "+replacementInstruction.toString(newOffset));
+ }
+
+ // Update the instruction.
+ replacementInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
+ }
+ else if (!deleted[oldOffset])
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Copied ["+oldOffset+"] -> "+instruction.toString(newOffset));
+ }
+
+ // Update the instruction.
+ instruction.accept(clazz, method, codeAttribute, oldOffset, this);
+ }
+
+ // Update and insert the post-inserted instruction, if any.
+ Instruction postInstruction = postInsertions[oldOffset];
+ if (postInstruction != null)
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Post-inserted ["+oldOffset+"] -> "+postInstruction.toString(newOffset));
+ }
+
+ // Update the instruction.
+ postInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
+ }
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ // Write out the instruction.
+ instructionWriter.visitSimpleInstruction(clazz,
+ method,
+ codeAttribute,
+ newOffset,
+ simpleInstruction);
+
+ newOffset += simpleInstruction.length(newOffset);
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ // Write out the instruction.
+ instructionWriter.visitConstantInstruction(clazz,
+ method,
+ codeAttribute,
+ newOffset,
+ constantInstruction);
+
+ newOffset += constantInstruction.length(newOffset);
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ // Write out the instruction.
+ instructionWriter.visitVariableInstruction(clazz,
+ method,
+ codeAttribute,
+ newOffset,
+ variableInstruction);
+
+ newOffset += variableInstruction.length(newOffset);
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ // Update the branch offset, relative to the precise new offset.
+ branchInstruction.branchOffset =
+ newBranchOffset(offset, branchInstruction.branchOffset, newOffset);
+
+ // Write out the instruction.
+ instructionWriter.visitBranchInstruction(clazz,
+ method,
+ codeAttribute,
+ newOffset,
+ branchInstruction);
+
+ newOffset += branchInstruction.length(newOffset);
+ }
+
+
+ public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
+ {
+ // Update the default jump offset, relative to the precise new offset.
+ tableSwitchInstruction.defaultOffset =
+ newBranchOffset(offset, tableSwitchInstruction.defaultOffset, newOffset);
+
+ // Update the jump offsets, relative to the precise new offset.
+ newJumpOffsets(offset,
+ tableSwitchInstruction.jumpOffsets,
+ newOffset);
+
+ // Write out the instruction.
+ instructionWriter.visitTableSwitchInstruction(clazz,
+ method,
+ codeAttribute,
+ newOffset,
+ tableSwitchInstruction);
+
+ newOffset += tableSwitchInstruction.length(newOffset);
+ }
+
+
+ public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
+ {
+ // Update the default jump offset, relative to the precise new offset.
+ lookUpSwitchInstruction.defaultOffset =
+ newBranchOffset(offset, lookUpSwitchInstruction.defaultOffset, newOffset);
+
+ // Update the jump offsets, relative to the precise new offset.
+ newJumpOffsets(offset,
+ lookUpSwitchInstruction.jumpOffsets,
+ newOffset);
+
+ // Write out the instruction.
+ instructionWriter.visitLookUpSwitchInstruction(clazz,
+ method,
+ codeAttribute,
+ newOffset,
+ lookUpSwitchInstruction);
+
+ newOffset += lookUpSwitchInstruction.length(newOffset);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ // Update the code offsets. Note that the instruction offset map also
+ // has an entry for the first offset after the code, for u2endPC.
+ exceptionInfo.u2startPC = newInstructionOffset(exceptionInfo.u2startPC);
+ exceptionInfo.u2endPC = newInstructionOffset(exceptionInfo.u2endPC);
+ exceptionInfo.u2handlerPC = newInstructionOffset(exceptionInfo.u2handlerPC);
+ }
+
+
+ // Implementations for StackMapFrameVisitor.
+
+ public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)
+ {
+ // Update the stack map frame offset.
+ int stackMapFrameOffset = newInstructionOffset(offset);
+
+ int offsetDelta = stackMapFrameOffset;
+
+ // Compute the offset delta if the frame is part of a stack map frame
+ // table (for JDK 6.0) instead of a stack map (for Java Micro Edition).
+ if (expectedStackMapFrameOffset >= 0)
+ {
+ offsetDelta -= expectedStackMapFrameOffset;
+
+ expectedStackMapFrameOffset = stackMapFrameOffset + 1;
+ }
+
+ stackMapFrame.u2offsetDelta = offsetDelta;
+ }
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ // Update the stack map frame offset.
+ visitAnyStackMapFrame(clazz, method, codeAttribute, offset, sameOneFrame);
+
+ // Update the verification type offset.
+ sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ // Update the stack map frame offset.
+ visitAnyStackMapFrame(clazz, method, codeAttribute, offset, moreZeroFrame);
+
+ // Update the verification type offsets.
+ moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ // Update the stack map frame offset.
+ visitAnyStackMapFrame(clazz, method, codeAttribute, offset, fullFrame);
+
+ // Update the verification type offsets.
+ fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
+ fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
+
+
+ public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
+ {
+ // Update the offset of the 'new' instruction.
+ uninitializedType.u2newInstructionOffset = newInstructionOffset(uninitializedType.u2newInstructionOffset);
+ }
+
+
+ // Implementations for LineNumberInfoVisitor.
+
+ public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
+ {
+ // Update the code offset.
+ lineNumberInfo.u2startPC = newInstructionOffset(lineNumberInfo.u2startPC);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Update the code offset and length.
+ // Be careful to update the length first.
+ localVariableInfo.u2length = newBranchOffset(localVariableInfo.u2startPC, localVariableInfo.u2length);
+ localVariableInfo.u2startPC = newInstructionOffset(localVariableInfo.u2startPC);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Update the code offset and length.
+ // Be careful to update the length first.
+ localVariableTypeInfo.u2length = newBranchOffset(localVariableTypeInfo.u2startPC, localVariableTypeInfo.u2length);
+ localVariableTypeInfo.u2startPC = newInstructionOffset(localVariableTypeInfo.u2startPC);
+ }
+
+
+ // Implementations for TypeAnnotationVisitor.
+
+ public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)
+ {
+ // Update all local variable targets.
+ typeAnnotation.targetInfoAccept(clazz, this);
+ }
+
+
+ // Implementations for TargetInfoVisitor.
+
+ public void visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo) {}
+
+
+ public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)
+ {
+ // Update the offsets of the variables.
+ localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this);
+ }
+
+
+ public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo)
+ {
+ // Update the offset.
+ offsetTargetInfo.u2offset = newInstructionOffset(offsetTargetInfo.u2offset);
+ }
+
+
+ // Implementations for LocalVariableTargetElementVisitor.
+
+ public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)
+ {
+ // Update the variable start offset and length.
+ // Be careful to update the length first.
+ localVariableTargetElement.u2length = newBranchOffset(localVariableTargetElement.u2startPC, localVariableTargetElement.u2length);
+ localVariableTargetElement.u2startPC = newInstructionOffset(localVariableTargetElement.u2startPC);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Updates the given jump offsets for the instruction at the given offset,
+ * relative to the given new offset.
+ */
+ private void newJumpOffsets(int oldInstructionOffset,
+ int[] oldJumpOffsets,
+ int newInstructionOffset)
+ {
+ for (int index = 0; index < oldJumpOffsets.length; index++)
+ {
+ oldJumpOffsets[index] = newBranchOffset(oldInstructionOffset,
+ oldJumpOffsets[index],
+ newInstructionOffset);
+ }
+ }
+
+
+ /**
+ * Computes the new branch offset for the instruction at the given offset
+ * with the given branch offset, relative to the new instruction (block)
+ * offset.
+ */
+ private int newBranchOffset(int oldInstructionOffset,
+ int oldBranchOffset)
+ {
+ return newInstructionOffset(oldInstructionOffset + oldBranchOffset) -
+ newInstructionOffset(oldInstructionOffset);
+ }
+
+
+ /**
+ * Computes the new branch offset for the instruction at the given offset
+ * with the given branch offset, relative to the given new offset.
+ */
+ private int newBranchOffset(int oldInstructionOffset,
+ int oldBranchOffset,
+ int newInstructionOffset)
+ {
+ return newInstructionOffset(oldInstructionOffset + oldBranchOffset) -
+ newInstructionOffset;
+ }
+
+
+ /**
+ * Computes the new instruction offset for the instruction at the given
+ * offset.
+ */
+ private int newInstructionOffset(int oldInstructionOffset)
+ {
+ if (oldInstructionOffset < 0 ||
+ oldInstructionOffset > codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+oldInstructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ return newInstructionOffsets[oldInstructionOffset];
+ }
+
+
+ /**
+ * Returns the given list of exceptions, without the ones that have empty
+ * code blocks.
+ */
+ private int removeEmptyExceptions(ExceptionInfo[] exceptionInfos,
+ int exceptionInfoCount)
+ {
+ // Overwrite all empty exceptions.
+ int newIndex = 0;
+ for (int index = 0; index < exceptionInfoCount; index++)
+ {
+ ExceptionInfo exceptionInfo = exceptionInfos[index];
+ if (exceptionInfo.u2startPC < exceptionInfo.u2endPC)
+ {
+ exceptionInfos[newIndex++] = exceptionInfo;
+ }
+ }
+
+ return newIndex;
+ }
+
+
+ /**
+ * Returns the given list of line numbers, without the ones that have empty
+ * code blocks or that exceed the code size.
+ */
+ private int removeEmptyLineNumbers(LineNumberInfo[] lineNumberInfos,
+ int lineNumberInfoCount,
+ int codeLength)
+ {
+ // Overwrite all empty line number entries.
+ int newIndex = 0;
+ for (int index = 0; index < lineNumberInfoCount; index++)
+ {
+ LineNumberInfo lineNumberInfo = lineNumberInfos[index];
+ int startPC = lineNumberInfo.u2startPC;
+ if (startPC < codeLength &&
+ (index == 0 || startPC > lineNumberInfos[index-1].u2startPC))
+ {
+ lineNumberInfos[newIndex++] = lineNumberInfo;
+ }
+ }
+
+ return newIndex;
+ }
+
+
+ /**
+ * This instruction is a composite of other instructions, for local use
+ * inside the editor class only.
+ */
+ private class CompositeInstruction
+ extends Instruction
+ {
+ private Instruction[] instructions;
+
+
+ private CompositeInstruction(Instruction[] instructions)
+ {
+ this.instructions = instructions;
+ }
+
+
+ // Implementations for Instruction.
+
+ public Instruction shrink()
+ {
+ for (int index = 0; index < instructions.length; index++)
+ {
+ instructions[index] = instructions[index].shrink();
+ }
+
+ return this;
+ }
+
+
+ public void write(byte[] code, int offset)
+ {
+ for (int index = 0; index < instructions.length; index++)
+ {
+ Instruction instruction = instructions[index];
+
+ instruction.write(code, offset);
+
+ offset += instruction.length(offset);
+ }
+ }
+
+
+ protected void readInfo(byte[] code, int offset)
+ {
+ throw new UnsupportedOperationException("Can't read composite instruction");
+ }
+
+
+ protected void writeInfo(byte[] code, int offset)
+ {
+ throw new UnsupportedOperationException("Can't write composite instruction");
+ }
+
+
+ public int length(int offset)
+ {
+ int newOffset = offset;
+
+ for (int index = 0; index < instructions.length; index++)
+ {
+ newOffset += instructions[index].length(newOffset);
+ }
+
+ return newOffset - offset;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
+ {
+ if (instructionVisitor != CodeAttributeEditor.this)
+ {
+ throw new UnsupportedOperationException("Unexpected visitor ["+instructionVisitor+"]");
+ }
+
+ for (int index = 0; index < instructions.length; index++)
+ {
+ Instruction instruction = instructions[index];
+
+ instruction.accept(clazz, method, codeAttribute, offset, CodeAttributeEditor.this);
+
+ offset += instruction.length(offset);
+ }
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ StringBuffer stringBuffer = new StringBuffer();
+
+ for (int index = 0; index < instructions.length; index++)
+ {
+ stringBuffer.append(instructions[index].toString()).append("; ");
+ }
+
+ return stringBuffer.toString();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeEditorResetter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
new file mode 100644
index 0000000000..8abb3f6baa
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
@@ -0,0 +1,60 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor resets it CodeAttributeEditor whenever it visits a
+ * code attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class CodeAttributeEditorResetter
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final CodeAttributeEditor codeAttributeEditor;
+
+
+ /**
+ * Creates a new CodeAttributeEditorResetter.
+ * @param codeAttributeEditor the code attribute editor that will be reset.
+ */
+ public CodeAttributeEditorResetter(CodeAttributeEditor codeAttributeEditor)
+ {
+ this.codeAttributeEditor = codeAttributeEditor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttributeEditor.reset(codeAttribute.u4codeLength);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ComparableConstant.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ComparableConstant.java
new file mode 100644
index 0000000000..55d3c27678
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ComparableConstant.java
@@ -0,0 +1,276 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+
+/**
+ * This class is a <code>Comparable</code> wrapper of <code>Constant</code>
+ * objects. It can store an index, in order to identify the constant pool
+ * entry after it has been sorted. The comparison is primarily based on the
+ * types of the constant pool entries, and secondarily on the contents of
+ * the constant pool entries.
+ *
+ * @author Eric Lafortune
+ */
+class ComparableConstant
+extends SimplifiedVisitor
+implements Comparable, ConstantVisitor
+{
+ private static final int[] PRIORITIES = new int[19];
+ static
+ {
+ PRIORITIES[ClassConstants.CONSTANT_Integer] = 0; // Possibly byte index (ldc).
+ PRIORITIES[ClassConstants.CONSTANT_Float] = 1;
+ PRIORITIES[ClassConstants.CONSTANT_String] = 2;
+ PRIORITIES[ClassConstants.CONSTANT_Class] = 3;
+ PRIORITIES[ClassConstants.CONSTANT_Long] = 4; // Always wide index (ldc2_w).
+ PRIORITIES[ClassConstants.CONSTANT_Double] = 5; // Always wide index (ldc2_w).
+ PRIORITIES[ClassConstants.CONSTANT_Fieldref] = 6; // Always wide index (getfield,...).
+ PRIORITIES[ClassConstants.CONSTANT_Methodref] = 7; // Always wide index (invokespecial,...).
+ PRIORITIES[ClassConstants.CONSTANT_InterfaceMethodref] = 8; // Always wide index (invokeinterface).
+ PRIORITIES[ClassConstants.CONSTANT_InvokeDynamic] = 9; // Always wide index (invokedynamic).
+ PRIORITIES[ClassConstants.CONSTANT_MethodHandle] = 10;
+ PRIORITIES[ClassConstants.CONSTANT_NameAndType] = 11;
+ PRIORITIES[ClassConstants.CONSTANT_MethodType] = 12;
+ PRIORITIES[ClassConstants.CONSTANT_Utf8] = 13;
+ }
+
+ private final Clazz clazz;
+ private final int thisIndex;
+ private final Constant thisConstant;
+
+ private Constant otherConstant;
+ private int result;
+
+
+ public ComparableConstant(Clazz clazz, int index, Constant constant)
+ {
+ this.clazz = clazz;
+ this.thisIndex = index;
+ this.thisConstant = constant;
+ }
+
+
+ public int getIndex()
+ {
+ return thisIndex;
+ }
+
+
+ public Constant getConstant()
+ {
+ return thisConstant;
+ }
+
+
+ // Implementations for Comparable.
+
+ public int compareTo(Object other)
+ {
+ ComparableConstant otherComparableConstant = (ComparableConstant)other;
+
+ otherConstant = otherComparableConstant.thisConstant;
+
+ // Compare based on the original indices, if the actual constant pool
+ // entries are the same.
+ if (thisConstant == otherConstant)
+ {
+ int otherIndex = otherComparableConstant.thisIndex;
+
+ return thisIndex < otherIndex ? -1 :
+ thisIndex == otherIndex ? 0 :
+ 1;
+ }
+
+ // Compare based on the tags, if they are different.
+ int thisTag = thisConstant.getTag();
+ int otherTag = otherConstant.getTag();
+
+ if (thisTag != otherTag)
+ {
+ return PRIORITIES[thisTag] < PRIORITIES[otherTag] ? -1 : 1;
+ }
+
+ // Otherwise compare based on the contents of the Constant objects.
+ thisConstant.accept(clazz, this);
+
+ return result;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ int value = integerConstant.getValue();
+ int otherValue = ((IntegerConstant)otherConstant).getValue();
+ result = value < otherValue ? -1 :
+ value == otherValue ? 0 :
+ 1;
+ }
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ long value = longConstant.getValue();
+ long otherValue = ((LongConstant)otherConstant).getValue();
+ result = value < otherValue ? -1 :
+ value == otherValue ? 0 :
+ 1;
+ }
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ result = Float.compare(floatConstant.getValue(),
+ ((FloatConstant)otherConstant).getValue());
+ }
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ result = Double.compare(doubleConstant.getValue(),
+ ((DoubleConstant)otherConstant).getValue());
+ }
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ result = stringConstant.getString(clazz).compareTo(((StringConstant)otherConstant).getString(clazz));
+ }
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ result = utf8Constant.getString().compareTo(((Utf8Constant)otherConstant).getString());
+ }
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ InvokeDynamicConstant otherInvokeDynamicConstant = (InvokeDynamicConstant)otherConstant;
+
+ int index = invokeDynamicConstant.getBootstrapMethodAttributeIndex();
+ int otherIndex = otherInvokeDynamicConstant.getBootstrapMethodAttributeIndex();
+
+ result = index < otherIndex ? -1 :
+ index > otherIndex ? 1 :
+ compare(invokeDynamicConstant.getName(clazz),
+ invokeDynamicConstant.getType(clazz),
+ otherInvokeDynamicConstant.getName(clazz),
+ otherInvokeDynamicConstant.getType(clazz));
+ }
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ MethodHandleConstant otherMethodHandleConstant = (MethodHandleConstant)otherConstant;
+
+ int kind = methodHandleConstant.getReferenceKind();
+ int otherKind = otherMethodHandleConstant.getReferenceKind();
+
+ result = kind < otherKind ? -1 :
+ kind > otherKind ? 1 :
+ compare(methodHandleConstant.getClassName(clazz),
+ methodHandleConstant.getName(clazz),
+ methodHandleConstant.getType(clazz),
+ otherMethodHandleConstant.getClassName(clazz),
+ otherMethodHandleConstant.getName(clazz),
+ otherMethodHandleConstant.getType(clazz));
+ }
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ RefConstant otherRefConstant = (RefConstant)otherConstant;
+ result = compare(refConstant.getClassName(clazz),
+ refConstant.getName(clazz),
+ refConstant.getType(clazz),
+ otherRefConstant.getClassName(clazz),
+ otherRefConstant.getName(clazz),
+ otherRefConstant.getType(clazz));
+ }
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ result = classConstant.getName(clazz).compareTo(((ClassConstant)otherConstant).getName(clazz));
+ }
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant MethodTypeConstant)
+ {
+ MethodTypeConstant otherMethodTypeConstant = (MethodTypeConstant)otherConstant;
+ result = MethodTypeConstant.getType(clazz)
+ .compareTo
+ (otherMethodTypeConstant.getType(clazz));
+ }
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ NameAndTypeConstant otherNameAndTypeConstant = (NameAndTypeConstant)otherConstant;
+ result = compare(nameAndTypeConstant.getName(clazz),
+ nameAndTypeConstant.getType(clazz),
+ otherNameAndTypeConstant.getName(clazz),
+ otherNameAndTypeConstant.getType(clazz));
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object other)
+ {
+ return other != null &&
+ this.getClass().equals(other.getClass()) &&
+ this.getConstant().getClass().equals(((ComparableConstant)other).getConstant().getClass()) &&
+ this.compareTo(other) == 0;
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode();
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Compares the given two pairs of strings.
+ */
+ private int compare(String string1a, String string1b,
+ String string2a, String string2b)
+ {
+ int comparison;
+ return
+ (comparison = string1a.compareTo(string2a)) != 0 ? comparison :
+ string1b.compareTo(string2b);
+ }
+
+
+ /**
+ * Compares the given two triplets of strings.
+ */
+ private int compare(String string1a, String string1b, String string1c,
+ String string2a, String string2b, String string2c)
+ {
+ int comparison;
+ return
+ (comparison = string1a.compareTo(string2a)) != 0 ? comparison :
+ (comparison = string1b.compareTo(string2b)) != 0 ? comparison :
+ string1c.compareTo(string2c);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantAdder.java
new file mode 100644
index 0000000000..ed1fd934c8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantAdder.java
@@ -0,0 +1,256 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This ConstantVisitor adds all constants that it visits to the constant pool
+ * of a given target class.
+ *
+ * Bootstrap methods attributes are automatically updated for invokedynamic
+ * constants.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantAdder
+implements ConstantVisitor
+{
+ private final ConstantPoolEditor constantPoolEditor;
+ private final BootstrapMethodsAttributeAdder bootstrapMethodsAttributeAdder;
+
+ private int constantIndex;
+
+
+ /**
+ * Creates a new ConstantAdder that will copy constants into the given
+ * target class.
+ */
+ public ConstantAdder(ProgramClass targetClass)
+ {
+ constantPoolEditor = new ConstantPoolEditor(targetClass);
+ bootstrapMethodsAttributeAdder = new BootstrapMethodsAttributeAdder(targetClass);
+ }
+
+
+ /**
+ * Adds a copy of the specified constant in the given class and returns
+ * its index. If the specified index is 0, the returned value is 0 too.
+ */
+ public int addConstant(Clazz clazz, int constantIndex)
+ {
+ clazz.constantPoolEntryAccept(constantIndex, this);
+
+ return this.constantIndex;
+ }
+
+
+ /**
+ * Adds a copy of the given constant in the given class and returns
+ * its index.
+ */
+ public int addConstant(Clazz clazz, Constant constant)
+ {
+ constant.accept(clazz, this);
+
+ return this.constantIndex;
+ }
+
+
+ /**
+ * Returns the index of the most recently created constant in the constant
+ * pool of the target class.
+ */
+ public int getConstantIndex()
+ {
+ return constantIndex;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ constantIndex =
+ constantPoolEditor.addIntegerConstant(integerConstant.getValue());
+ }
+
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ constantIndex =
+ constantPoolEditor.addLongConstant(longConstant.getValue());
+ }
+
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ constantIndex =
+ constantPoolEditor.addFloatConstant(floatConstant.getValue());
+ }
+
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ constantIndex =
+ constantPoolEditor.addDoubleConstant(doubleConstant.getValue());
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ constantIndex =
+ constantPoolEditor.addStringConstant(stringConstant.getString(clazz),
+ stringConstant.referencedClass,
+ stringConstant.referencedMember);
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ constantIndex =
+ constantPoolEditor.addUtf8Constant(utf8Constant.getString());
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Find the bootstrap methods attribute.
+ AttributesEditor attributesEditor =
+ new AttributesEditor((ProgramClass)clazz, false);
+
+ BootstrapMethodsAttribute bootstrapMethodsAttribute =
+ (BootstrapMethodsAttribute)attributesEditor.findAttribute(ClassConstants.ATTR_BootstrapMethods);
+
+ // Add the name and type constant.
+ clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this);
+
+ // Copy the referenced classes.
+ Clazz[] referencedClasses = invokeDynamicConstant.referencedClasses;
+ Clazz[] referencedClassesCopy = null;
+ if (referencedClasses != null)
+ {
+ referencedClassesCopy = new Clazz[referencedClasses.length];
+ System.arraycopy(referencedClasses, 0,
+ referencedClassesCopy, 0,
+ referencedClasses.length);
+ }
+
+ bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz,
+ invokeDynamicConstant.getBootstrapMethodAttributeIndex(),
+ bootstrapMethodsAttributeAdder);
+
+ // Then add the actual invoke dynamic constant.
+ constantIndex =
+ constantPoolEditor.addInvokeDynamicConstant(bootstrapMethodsAttributeAdder.getBootstrapMethodIndex(),
+ constantIndex,
+ referencedClassesCopy);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // First add the field ref, interface method ref, or method ref
+ // constant.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+
+ // Then add the actual method handle constant.
+ constantIndex =
+ constantPoolEditor.addMethodHandleConstant(methodHandleConstant.getReferenceKind(),
+ constantIndex);
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ // First add the referenced class constant, with its own referenced class.
+ clazz.constantPoolEntryAccept(fieldrefConstant.u2classIndex, this);
+
+ // Then add the actual field reference constant, with its referenced
+ // class and class member.
+ constantIndex =
+ constantPoolEditor.addFieldrefConstant(constantIndex,
+ fieldrefConstant.getName(clazz),
+ fieldrefConstant.getType(clazz),
+ fieldrefConstant.referencedClass,
+ fieldrefConstant.referencedMember);
+ }
+
+
+ public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
+ {
+ // First add the referenced class constant, with its own referenced class.
+ clazz.constantPoolEntryAccept(interfaceMethodrefConstant.u2classIndex, this);
+
+ // Then add the actual interface method reference constant, with its
+ // referenced class and class member.
+ constantIndex =
+ constantPoolEditor.addInterfaceMethodrefConstant(constantIndex,
+ interfaceMethodrefConstant.getName(clazz),
+ interfaceMethodrefConstant.getType(clazz),
+ interfaceMethodrefConstant.referencedClass,
+ interfaceMethodrefConstant.referencedMember);
+ }
+
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ // First add the referenced class constant, with its own referenced class.
+ clazz.constantPoolEntryAccept(methodrefConstant.u2classIndex, this);
+
+ // Then add the actual method reference constant, with its referenced
+ // class and class member.
+ constantIndex =
+ constantPoolEditor.addMethodrefConstant(constantIndex,
+ methodrefConstant.getName(clazz),
+ methodrefConstant.getType(clazz),
+ methodrefConstant.referencedClass,
+ methodrefConstant.referencedMember);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Add the class constant, with its referenced class..
+ constantIndex =
+ constantPoolEditor.addClassConstant(classConstant.getName(clazz),
+ classConstant.referencedClass);
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ constantIndex =
+ constantPoolEditor.addMethodTypeConstant(methodTypeConstant.getType(clazz),
+ methodTypeConstant.referencedClasses);
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ constantIndex =
+ constantPoolEditor.addNameAndTypeConstant(nameAndTypeConstant.getName(clazz),
+ nameAndTypeConstant.getType(clazz));
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolEditor.java
new file mode 100644
index 0000000000..1f6e950de4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolEditor.java
@@ -0,0 +1,784 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+
+/**
+ * This class can add constant pool entries to a given class.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantPoolEditor
+{
+ private static final boolean DEBUG = false;
+
+ private ProgramClass targetClass;
+
+
+ /**
+ * Creates a new ConstantPoolEditor that will edit constants in the given
+ * target class.
+ */
+ public ConstantPoolEditor(ProgramClass targetClass)
+ {
+ this.targetClass = targetClass;
+ }
+
+
+ /**
+ * Finds or creates a IntegerConstant constant pool entry with the given
+ * value.
+ * @return the constant pool index of the Utf8Constant.
+ */
+ public int addIntegerConstant(int value)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Integer)
+ {
+ IntegerConstant integerConstant = (IntegerConstant)constant;
+ if (integerConstant.getValue() == value)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new IntegerConstant(value));
+ }
+
+
+ /**
+ * Finds or creates a LongConstant constant pool entry with the given value.
+ * @return the constant pool index of the LongConstant.
+ */
+ public int addLongConstant(long value)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Long)
+ {
+ LongConstant longConstant = (LongConstant)constant;
+ if (longConstant.getValue() == value)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new LongConstant(value));
+ }
+
+
+ /**
+ * Finds or creates a FloatConstant constant pool entry with the given
+ * value.
+ * @return the constant pool index of the FloatConstant.
+ */
+ public int addFloatConstant(float value)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Float)
+ {
+ FloatConstant floatConstant = (FloatConstant)constant;
+ if (floatConstant.getValue() == value)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new FloatConstant(value));
+ }
+
+
+ /**
+ * Finds or creates a DoubleConstant constant pool entry with the given
+ * value.
+ * @return the constant pool index of the DoubleConstant.
+ */
+ public int addDoubleConstant(double value)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Double)
+ {
+ DoubleConstant doubleConstant = (DoubleConstant)constant;
+ if (doubleConstant.getValue() == value)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new DoubleConstant(value));
+ }
+
+
+ /**
+ * Finds or creates a StringConstant constant pool entry with the given
+ * value.
+ * @return the constant pool index of the StringConstant.
+ */
+ public int addStringConstant(String string,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_String)
+ {
+ StringConstant stringConstant = (StringConstant)constant;
+ if (stringConstant.getString(targetClass).equals(string))
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new StringConstant(addUtf8Constant(string),
+ referencedClass,
+ referencedMember));
+ }
+
+
+ /**
+ * Finds or creates a InvokeDynamicConstant constant pool entry with the
+ * given bootstrap method constant pool entry index, method name, and
+ * descriptor.
+ * @return the constant pool index of the InvokeDynamicConstant.
+ */
+ public int addInvokeDynamicConstant(int bootstrapMethodIndex,
+ String name,
+ String descriptor,
+ Clazz[] referencedClasses)
+ {
+ return addInvokeDynamicConstant(bootstrapMethodIndex,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClasses);
+ }
+
+
+ /**
+ * Finds or creates a InvokeDynamicConstant constant pool entry with the given
+ * class constant pool entry index and name and type constant pool entry
+ * index.
+ * @return the constant pool index of the InvokeDynamicConstant.
+ */
+ public int addInvokeDynamicConstant(int bootstrapMethodIndex,
+ int nameAndTypeIndex,
+ Clazz[] referencedClasses)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_InvokeDynamic)
+ {
+ InvokeDynamicConstant invokeDynamicConstant = (InvokeDynamicConstant)constant;
+ if (invokeDynamicConstant.u2bootstrapMethodAttributeIndex == bootstrapMethodIndex &&
+ invokeDynamicConstant.u2nameAndTypeIndex == nameAndTypeIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new InvokeDynamicConstant(bootstrapMethodIndex,
+ nameAndTypeIndex,
+ referencedClasses));
+ }
+
+
+ /**
+ * Finds or creates a MethodHandleConstant constant pool entry of the
+ * specified kind and with the given field ref, interface method ref,
+ * or method ref constant pool entry index.
+ * @return the constant pool index of the MethodHandleConstant.
+ */
+ public int addMethodHandleConstant(int referenceKind,
+ int referenceIndex)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_MethodHandle)
+ {
+ MethodHandleConstant methodHandleConstant = (MethodHandleConstant)constant;
+ if (methodHandleConstant.u1referenceKind == referenceKind &&
+ methodHandleConstant.u2referenceIndex == referenceIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new MethodHandleConstant(referenceKind,
+ referenceIndex));
+ }
+
+
+ /**
+ * Finds or creates a FieldrefConstant constant pool entry for the given
+ * class and field.
+ * @return the constant pool index of the FieldrefConstant.
+ */
+ public int addFieldrefConstant(Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addFieldrefConstant(referencedClass.getName(),
+ referencedMember.getName(referencedClass),
+ referencedMember.getDescriptor(referencedClass),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a FieldrefConstant constant pool entry with the given
+ * class name, field name, and descriptor.
+ * @return the constant pool index of the FieldrefConstant.
+ */
+ public int addFieldrefConstant(String className,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addFieldrefConstant(className,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a FieldrefConstant constant pool entry with the given
+ * class name, field name, and descriptor.
+ * @return the constant pool index of the FieldrefConstant.
+ */
+ public int addFieldrefConstant(String className,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addFieldrefConstant(addClassConstant(className, referencedClass),
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a FieldrefConstant constant pool entry with the given
+ * class constant pool entry index, field name, and descriptor.
+ * @return the constant pool index of the FieldrefConstant.
+ */
+ public int addFieldrefConstant(int classIndex,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addFieldrefConstant(classIndex,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a FieldrefConstant constant pool entry with the given
+ * class constant pool entry index and name and type constant pool entry
+ * index.
+ * @return the constant pool index of the FieldrefConstant.
+ */
+ public int addFieldrefConstant(int classIndex,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Fieldref)
+ {
+ FieldrefConstant fieldrefConstant = (FieldrefConstant)constant;
+ if (fieldrefConstant.u2classIndex == classIndex &&
+ fieldrefConstant.u2nameAndTypeIndex == nameAndTypeIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new FieldrefConstant(classIndex,
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember));
+ }
+
+
+ /**
+ * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
+ * given class name, method name, and descriptor.
+ * @return the constant pool index of the InterfaceMethodrefConstant.
+ */
+ public int addInterfaceMethodrefConstant(String className,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addInterfaceMethodrefConstant(className,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
+ * given class name, method name, and descriptor.
+ * @return the constant pool index of the InterfaceMethodrefConstant.
+ */
+ public int addInterfaceMethodrefConstant(String className,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addInterfaceMethodrefConstant(addClassConstant(className, referencedClass),
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a InterfaceMethodrefConstant constant pool entry for the
+ * given class and method.
+ * @return the constant pool index of the InterfaceMethodrefConstant.
+ */
+ public int addInterfaceMethodrefConstant(Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addInterfaceMethodrefConstant(referencedClass.getName(),
+ referencedMember.getName(referencedClass),
+ referencedMember.getDescriptor(referencedClass),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
+ * given class constant pool entry index, method name, and descriptor.
+ * @return the constant pool index of the InterfaceMethodrefConstant.
+ */
+ public int addInterfaceMethodrefConstant(int classIndex,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addInterfaceMethodrefConstant(classIndex,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
+ * given class constant pool entry index and name and type constant pool
+ * entry index.
+ * @return the constant pool index of the InterfaceMethodrefConstant.
+ */
+ public int addInterfaceMethodrefConstant(int classIndex,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_InterfaceMethodref)
+ {
+ InterfaceMethodrefConstant methodrefConstant = (InterfaceMethodrefConstant)constant;
+ if (methodrefConstant.u2classIndex == classIndex &&
+ methodrefConstant.u2nameAndTypeIndex == nameAndTypeIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new InterfaceMethodrefConstant(classIndex,
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember));
+ }
+
+
+ /**
+ * Finds or creates a MethodrefConstant constant pool entry for the given
+ * class and method.
+ * @return the constant pool index of the MethodrefConstant.
+ */
+ public int addMethodrefConstant(Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addMethodrefConstant(referencedClass.getName(),
+ referencedMember.getName(referencedClass),
+ referencedMember.getDescriptor(referencedClass),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a MethodrefConstant constant pool entry with the given
+ * class name, method name, and descriptor.
+ * @return the constant pool index of the MethodrefConstant.
+ */
+ public int addMethodrefConstant(String className,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addMethodrefConstant(className,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a MethodrefConstant constant pool entry with the given
+ * class name, method name, and descriptor.
+ * @return the constant pool index of the MethodrefConstant.
+ */
+ public int addMethodrefConstant(String className,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addMethodrefConstant(addClassConstant(className, referencedClass),
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a MethodrefConstant constant pool entry with the given
+ * class constant pool entry index, method name, and descriptor.
+ * @return the constant pool index of the MethodrefConstant.
+ */
+ public int addMethodrefConstant(int classIndex,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addMethodrefConstant(classIndex,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a MethodrefConstant constant pool entry with the given
+ * class constant pool entry index and name and type constant pool entry
+ * index.
+ * @return the constant pool index of the MethodrefConstant.
+ */
+ public int addMethodrefConstant(int classIndex,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Methodref)
+ {
+ MethodrefConstant methodrefConstant = (MethodrefConstant)constant;
+ if (methodrefConstant.u2classIndex == classIndex &&
+ methodrefConstant.u2nameAndTypeIndex == nameAndTypeIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new MethodrefConstant(classIndex,
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember));
+ }
+
+
+ /**
+ * Finds or creates a ClassConstant constant pool entry for the given class.
+ * @return the constant pool index of the ClassConstant.
+ */
+ public int addClassConstant(Clazz referencedClass)
+ {
+ return addClassConstant(referencedClass.getName(),
+ referencedClass);
+ }
+
+
+ /**
+ * Finds or creates a ClassConstant constant pool entry with the given name.
+ * @return the constant pool index of the ClassConstant.
+ */
+ public int addClassConstant(String name,
+ Clazz referencedClass)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Class)
+ {
+ ClassConstant classConstant = (ClassConstant)constant;
+ if (classConstant.getName(targetClass).equals(name))
+ {
+ return index;
+ }
+ }
+ }
+
+ int nameIndex = addUtf8Constant(name);
+
+ return addConstant(new ClassConstant(nameIndex, referencedClass));
+ }
+
+
+ /**
+ * Finds or creates a MethodTypeConstant constant pool entry with the given
+ * type.
+ * @return the constant pool index of the MethodTypeConstant.
+ */
+ public int addMethodTypeConstant(String type,
+ Clazz[] referencedClasses)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_MethodType)
+ {
+ MethodTypeConstant methodTypeConstant = (MethodTypeConstant)constant;
+ if (methodTypeConstant.getType(targetClass).equals(type))
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new MethodTypeConstant(addUtf8Constant(type),
+ referencedClasses));
+ }
+
+
+ /**
+ * Finds or creates a NameAndTypeConstant constant pool entry with the given
+ * name and type.
+ * @return the constant pool index of the NameAndTypeConstant.
+ */
+ public int addNameAndTypeConstant(String name,
+ String type)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_NameAndType)
+ {
+ NameAndTypeConstant nameAndTypeConstant = (NameAndTypeConstant)constant;
+ if (nameAndTypeConstant.getName(targetClass).equals(name) &&
+ nameAndTypeConstant.getType(targetClass).equals(type))
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new NameAndTypeConstant(addUtf8Constant(name),
+ addUtf8Constant(type)));
+ }
+
+
+ /**
+ * Finds or creates a Utf8Constant constant pool entry for the given string.
+ * @return the constant pool index of the Utf8Constant.
+ */
+ public int addUtf8Constant(String string)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Utf8)
+ {
+ Utf8Constant utf8Constant = (Utf8Constant)constant;
+ if (utf8Constant.getString().equals(string))
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new Utf8Constant(string));
+ }
+
+
+ /**
+ * Adds a given constant pool entry to the end of the constant pool/
+ * @return the constant pool index for the added entry.
+ */
+ public int addConstant(Constant constant)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Make sure there is enough space for another constant pool entry.
+ if (constantPool.length < constantPoolCount+2)
+ {
+ targetClass.constantPool = new Constant[constantPoolCount+2];
+ System.arraycopy(constantPool, 0,
+ targetClass.constantPool, 0,
+ constantPoolCount);
+ constantPool = targetClass.constantPool;
+ }
+
+ if (DEBUG)
+ {
+ System.out.println(targetClass.getName()+": adding ["+constant.getClass().getName()+"] at index "+targetClass.u2constantPoolCount);
+ }
+
+ // Create a new Utf8Constant for the given string.
+ constantPool[targetClass.u2constantPoolCount++] = constant;
+
+ // Long constants and double constants take up two entries in the
+ // constant pool.
+ int tag = constant.getTag();
+ if (tag == ClassConstants.CONSTANT_Long ||
+ tag == ClassConstants.CONSTANT_Double)
+ {
+ constantPool[targetClass.u2constantPoolCount++] = null;
+ }
+
+ return constantPoolCount;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolRemapper.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolRemapper.java
new file mode 100644
index 0000000000..562854d4c3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolRemapper.java
@@ -0,0 +1,688 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor remaps all possible references to constant pool entries
+ * of the classes that it visits, based on a given index map. It is assumed that
+ * the constant pool entries themselves have already been remapped.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantPoolRemapper
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor,
+ MemberVisitor,
+ AttributeVisitor,
+ BootstrapMethodInfoVisitor,
+ InnerClassesInfoVisitor,
+ ExceptionInfoVisitor,
+ InstructionVisitor,
+ StackMapFrameVisitor,
+ VerificationTypeVisitor,
+ ParameterInfoVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor
+{
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false, true);
+
+ private int[] constantIndexMap;
+
+
+ /**
+ * Sets the given mapping of old constant pool entry indexes to their new
+ * indexes.
+ */
+ public void setConstantIndexMap(int[] constantIndexMap)
+ {
+ this.constantIndexMap = constantIndexMap;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Remap the local constant pool references.
+ programClass.u2thisClass = remapConstantIndex(programClass.u2thisClass);
+ programClass.u2superClass = remapConstantIndex(programClass.u2superClass);
+
+ remapConstantIndexArray(programClass.u2interfaces,
+ programClass.u2interfacesCount);
+
+ // Remap the references of the contant pool entries themselves.
+ programClass.constantPoolEntriesAccept(this);
+
+ // Remap the references in all fields, methods, and attributes.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+ programClass.attributesAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ // Nothing to do.
+ }
+
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ // Nothing to do.
+ }
+
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ // Nothing to do.
+ }
+
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ // Nothing to do.
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ stringConstant.u2stringIndex =
+ remapConstantIndex(stringConstant.u2stringIndex);
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ // Nothing to do.
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ invokeDynamicConstant.u2nameAndTypeIndex =
+ remapConstantIndex(invokeDynamicConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ methodHandleConstant.u2referenceIndex =
+ remapConstantIndex(methodHandleConstant.u2referenceIndex);
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ fieldrefConstant.u2classIndex =
+ remapConstantIndex(fieldrefConstant.u2classIndex);
+ fieldrefConstant.u2nameAndTypeIndex =
+ remapConstantIndex(fieldrefConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
+ {
+ interfaceMethodrefConstant.u2classIndex =
+ remapConstantIndex(interfaceMethodrefConstant.u2classIndex);
+ interfaceMethodrefConstant.u2nameAndTypeIndex =
+ remapConstantIndex(interfaceMethodrefConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ methodrefConstant.u2classIndex =
+ remapConstantIndex(methodrefConstant.u2classIndex);
+ methodrefConstant.u2nameAndTypeIndex =
+ remapConstantIndex(methodrefConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.u2nameIndex =
+ remapConstantIndex(classConstant.u2nameIndex);
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ methodTypeConstant.u2descriptorIndex =
+ remapConstantIndex(methodTypeConstant.u2descriptorIndex);
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ nameAndTypeConstant.u2nameIndex =
+ remapConstantIndex(nameAndTypeConstant.u2nameIndex);
+ nameAndTypeConstant.u2descriptorIndex =
+ remapConstantIndex(nameAndTypeConstant.u2descriptorIndex);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ visitMember(programClass, programField);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ visitMember(programClass, programMethod);
+ }
+
+
+ private void visitMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ // Remap the local constant pool references.
+ programMember.u2nameIndex =
+ remapConstantIndex(programMember.u2nameIndex);
+ programMember.u2descriptorIndex =
+ remapConstantIndex(programMember.u2descriptorIndex);
+
+ // Remap the constant pool references of the remaining attributes.
+ programMember.attributesAccept(programClass, this);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ // Library classes are left unchanged.
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ // Library classes are left unchanged.
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ unknownAttribute.u2attributeNameIndex =
+ remapConstantIndex(unknownAttribute.u2attributeNameIndex);
+
+ // There's not much else we can do with unknown attributes.
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ bootstrapMethodsAttribute.u2attributeNameIndex =
+ remapConstantIndex(bootstrapMethodsAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the bootstrap method entries.
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ sourceFileAttribute.u2attributeNameIndex =
+ remapConstantIndex(sourceFileAttribute.u2attributeNameIndex);
+ sourceFileAttribute.u2sourceFileIndex =
+ remapConstantIndex(sourceFileAttribute.u2sourceFileIndex);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ sourceDirAttribute.u2attributeNameIndex =
+ remapConstantIndex(sourceDirAttribute.u2attributeNameIndex);
+ sourceDirAttribute.u2sourceDirIndex =
+ remapConstantIndex(sourceDirAttribute.u2sourceDirIndex);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ innerClassesAttribute.u2attributeNameIndex =
+ remapConstantIndex(innerClassesAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the inner classes.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ enclosingMethodAttribute.u2attributeNameIndex =
+ remapConstantIndex(enclosingMethodAttribute.u2attributeNameIndex);
+ enclosingMethodAttribute.u2classIndex =
+ remapConstantIndex(enclosingMethodAttribute.u2classIndex);
+ enclosingMethodAttribute.u2nameAndTypeIndex =
+ remapConstantIndex(enclosingMethodAttribute.u2nameAndTypeIndex);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ deprecatedAttribute.u2attributeNameIndex =
+ remapConstantIndex(deprecatedAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ syntheticAttribute.u2attributeNameIndex =
+ remapConstantIndex(syntheticAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ signatureAttribute.u2attributeNameIndex =
+ remapConstantIndex(signatureAttribute.u2attributeNameIndex);
+ signatureAttribute.u2signatureIndex =
+ remapConstantIndex(signatureAttribute.u2signatureIndex);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ constantValueAttribute.u2attributeNameIndex =
+ remapConstantIndex(constantValueAttribute.u2attributeNameIndex);
+ constantValueAttribute.u2constantValueIndex =
+ remapConstantIndex(constantValueAttribute.u2constantValueIndex);
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ methodParametersAttribute.u2attributeNameIndex =
+ remapConstantIndex(methodParametersAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the parameter information.
+ methodParametersAttribute.parametersAccept(clazz, method, this);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ exceptionsAttribute.u2attributeNameIndex =
+ remapConstantIndex(exceptionsAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the exceptions.
+ remapConstantIndexArray(exceptionsAttribute.u2exceptionIndexTable,
+ exceptionsAttribute.u2exceptionIndexTableLength);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.u2attributeNameIndex =
+ remapConstantIndex(codeAttribute.u2attributeNameIndex);
+
+ // Initially, the code attribute editor doesn't contain any changes.
+ codeAttributeEditor.reset(codeAttribute.u4codeLength);
+
+ // Remap the constant pool references of the instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
+
+ // Apply the code atribute editor. It will only contain any changes if
+ // the code length is changing at any point.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Remap the constant pool references of the exceptions and attributes.
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ stackMapAttribute.u2attributeNameIndex =
+ remapConstantIndex(stackMapAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the stack map frames.
+ stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ stackMapTableAttribute.u2attributeNameIndex =
+ remapConstantIndex(stackMapTableAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the stack map frames.
+ stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ lineNumberTableAttribute.u2attributeNameIndex =
+ remapConstantIndex(lineNumberTableAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ localVariableTableAttribute.u2attributeNameIndex =
+ remapConstantIndex(localVariableTableAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ localVariableTypeTableAttribute.u2attributeNameIndex =
+ remapConstantIndex(localVariableTypeTableAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the local variables.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ annotationsAttribute.u2attributeNameIndex =
+ remapConstantIndex(annotationsAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the annotations.
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ parameterAnnotationsAttribute.u2attributeNameIndex =
+ remapConstantIndex(parameterAnnotationsAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ annotationDefaultAttribute.u2attributeNameIndex =
+ remapConstantIndex(annotationDefaultAttribute.u2attributeNameIndex);
+
+ // Remap the constant pool references of the annotations.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ bootstrapMethodInfo.u2methodHandleIndex =
+ remapConstantIndex(bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Remap the constant pool references of the bootstrap methods..
+ remapConstantIndexArray(bootstrapMethodInfo.u2methodArguments,
+ bootstrapMethodInfo.u2methodArgumentCount);
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ if (innerClassesInfo.u2innerClassIndex != 0)
+ {
+ innerClassesInfo.u2innerClassIndex =
+ remapConstantIndex(innerClassesInfo.u2innerClassIndex);
+ }
+
+ if (innerClassesInfo.u2outerClassIndex != 0)
+ {
+ innerClassesInfo.u2outerClassIndex =
+ remapConstantIndex(innerClassesInfo.u2outerClassIndex);
+ }
+
+ if (innerClassesInfo.u2innerNameIndex != 0)
+ {
+ innerClassesInfo.u2innerNameIndex =
+ remapConstantIndex(innerClassesInfo.u2innerNameIndex);
+ }
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ if (exceptionInfo.u2catchType != 0)
+ {
+ exceptionInfo.u2catchType =
+ remapConstantIndex(exceptionInfo.u2catchType);
+ }
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ // Is the new constant pool index different from the original one?
+ int newConstantIndex = remapConstantIndex(constantInstruction.constantIndex);
+ if (newConstantIndex != constantInstruction.constantIndex)
+ {
+ // Replace the instruction.
+ Instruction replacementInstruction =
+ new ConstantInstruction(constantInstruction.opcode,
+ newConstantIndex,
+ constantInstruction.constant);
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
+ }
+ }
+
+
+ // Implementations for StackMapFrameVisitor.
+
+ public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) {}
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ // Remap the constant pool references of the verification types.
+ sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ // Remap the constant pool references of the verification types.
+ moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ // Remap the constant pool references of the verification types.
+ fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
+ fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
+
+
+ public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
+ {
+ objectType.u2classIndex =
+ remapConstantIndex(objectType.u2classIndex);
+ }
+
+
+ // Implementations for ParameterInfoVisitor.
+
+ public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
+ {
+ parameterInfo.u2nameIndex =
+ remapConstantIndex(parameterInfo.u2nameIndex);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ localVariableInfo.u2nameIndex =
+ remapConstantIndex(localVariableInfo.u2nameIndex);
+ localVariableInfo.u2descriptorIndex =
+ remapConstantIndex(localVariableInfo.u2descriptorIndex);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ localVariableTypeInfo.u2nameIndex =
+ remapConstantIndex(localVariableTypeInfo.u2nameIndex);
+ localVariableTypeInfo.u2signatureIndex =
+ remapConstantIndex(localVariableTypeInfo.u2signatureIndex);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ annotation.u2typeIndex =
+ remapConstantIndex(annotation.u2typeIndex);
+
+ // Remap the constant pool references of the element values.
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ constantElementValue.u2elementNameIndex =
+ remapConstantIndex(constantElementValue.u2elementNameIndex);
+ constantElementValue.u2constantValueIndex =
+ remapConstantIndex(constantElementValue.u2constantValueIndex);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ enumConstantElementValue.u2elementNameIndex =
+ remapConstantIndex(enumConstantElementValue.u2elementNameIndex);
+ enumConstantElementValue.u2typeNameIndex =
+ remapConstantIndex(enumConstantElementValue.u2typeNameIndex);
+ enumConstantElementValue.u2constantNameIndex =
+ remapConstantIndex(enumConstantElementValue.u2constantNameIndex);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ classElementValue.u2elementNameIndex =
+ remapConstantIndex(classElementValue.u2elementNameIndex);
+ classElementValue.u2classInfoIndex =
+ remapConstantIndex(classElementValue.u2classInfoIndex);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ annotationElementValue.u2elementNameIndex =
+ remapConstantIndex(annotationElementValue.u2elementNameIndex);
+
+ // Remap the constant pool references of the annotation.
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ arrayElementValue.u2elementNameIndex =
+ remapConstantIndex(arrayElementValue.u2elementNameIndex);
+
+ // Remap the constant pool references of the element values.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ }
+
+
+ /**
+ * Remaps all constant pool indices in the given array.
+ */
+ private void remapConstantIndexArray(int[] array, int length)
+ {
+ for (int index = 0; index < length; index++)
+ {
+ array[index] = remapConstantIndex(array[index]);
+ }
+ }
+
+ // Small utility methods.
+
+
+ /**
+ * Returns the new constant pool index of the entry at the
+ * given index.
+ */
+ private int remapConstantIndex(int constantIndex)
+ {
+ int remappedConstantIndex = constantIndexMap[constantIndex];
+ if (remappedConstantIndex < 0)
+ {
+ throw new IllegalArgumentException("Can't remap constant index ["+constantIndex+"]");
+ }
+
+ return remappedConstantIndex;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolShrinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolShrinker.java
new file mode 100644
index 0000000000..08231648b9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolShrinker.java
@@ -0,0 +1,604 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+import java.util.Arrays;
+
+/**
+ * This ClassVisitor removes all unused entries from the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantPoolShrinker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ ConstantVisitor,
+ AttributeVisitor,
+ BootstrapMethodInfoVisitor,
+ InnerClassesInfoVisitor,
+ ExceptionInfoVisitor,
+ StackMapFrameVisitor,
+ VerificationTypeVisitor,
+ ParameterInfoVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor,
+ InstructionVisitor
+{
+ // A visitor info flag to indicate the constant is being used.
+ private static final Object USED = new Object();
+
+ private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
+ private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Mark this class's name.
+ markConstant(programClass, programClass.u2thisClass);
+
+ // Mark the superclass class constant.
+ programClass.superClassConstantAccept(this);
+
+ // Mark the interface class constants.
+ programClass.interfaceConstantsAccept(this);
+
+ // Mark the constants referenced by the class members.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ // Mark the attributes.
+ programClass.attributesAccept(this);
+
+ // Shift the used constant pool entries together, filling out the
+ // index map.
+ int newConstantPoolCount =
+ shrinkConstantPool(programClass.constantPool,
+ programClass.u2constantPoolCount);
+
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
+
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ // Mark the name and descriptor.
+ markConstant(programClass, programMember.u2nameIndex);
+ markConstant(programClass, programMember.u2descriptorIndex);
+
+ // Mark the attributes.
+ programMember.attributesAccept(programClass, this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ markAsUsed(constant);
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ markAsUsed(stringConstant);
+
+ markConstant(clazz, stringConstant.u2stringIndex);
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ markAsUsed(invokeDynamicConstant);
+
+ markConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);
+
+ // Mark the bootstrap methods attribute.
+ clazz.attributesAccept(this);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ markAsUsed(methodHandleConstant);
+
+ markConstant(clazz, methodHandleConstant.u2referenceIndex);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ markAsUsed(refConstant);
+
+ markConstant(clazz, refConstant.u2classIndex);
+ markConstant(clazz, refConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ markAsUsed(classConstant);
+
+ markConstant(clazz, classConstant.u2nameIndex);
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ markAsUsed(methodTypeConstant);
+
+ markConstant(clazz, methodTypeConstant.u2descriptorIndex);
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ markAsUsed(nameAndTypeConstant);
+
+ markConstant(clazz, nameAndTypeConstant.u2nameIndex);
+ markConstant(clazz, nameAndTypeConstant.u2descriptorIndex);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute)
+ {
+ markConstant(clazz, attribute.u2attributeNameIndex);
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ markConstant(clazz, bootstrapMethodsAttribute.u2attributeNameIndex);
+
+ // Mark the bootstrap method entries.
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ markConstant(clazz, sourceFileAttribute.u2attributeNameIndex);
+ markConstant(clazz, sourceFileAttribute.u2sourceFileIndex);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ markConstant(clazz, sourceDirAttribute.u2attributeNameIndex);
+ markConstant(clazz, sourceDirAttribute.u2sourceDirIndex);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ markConstant(clazz, innerClassesAttribute.u2attributeNameIndex);
+
+ // Mark the outer class entries.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ markConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex);
+ markConstant(clazz, enclosingMethodAttribute.u2classIndex);
+
+ if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
+ {
+ markConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex);
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ markConstant(clazz, signatureAttribute.u2attributeNameIndex);
+ markConstant(clazz, signatureAttribute.u2signatureIndex);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ markConstant(clazz, constantValueAttribute.u2attributeNameIndex);
+ markConstant(clazz, constantValueAttribute.u2constantValueIndex);
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ markConstant(clazz, methodParametersAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the parameter information.
+ methodParametersAttribute.parametersAccept(clazz, method, this);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ markConstant(clazz, exceptionsAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the exceptions.
+ exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ markConstant(clazz, codeAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the instructions,
+ // by the exceptions, and by the attributes.
+ codeAttribute.instructionsAccept(clazz, method, this);
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ markConstant(clazz, stackMapAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the stack map frames.
+ stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ markConstant(clazz, stackMapTableAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the stack map frames.
+ stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the local variable types.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the annotations.
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the element value.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ markConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Mark the constant pool entries referenced by the arguments.
+ bootstrapMethodInfo.methodArgumentsAccept(clazz, this);
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ innerClassesInfo.innerClassConstantAccept(clazz, this);
+ innerClassesInfo.outerClassConstantAccept(clazz, this);
+ innerClassesInfo.innerNameConstantAccept(clazz, this);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ if (exceptionInfo.u2catchType != 0)
+ {
+ markConstant(clazz, exceptionInfo.u2catchType);
+ }
+ }
+
+
+ // Implementations for StackMapFrameVisitor.
+
+ public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) {}
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
+ fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
+
+
+ public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
+ {
+ markConstant(clazz, objectType.u2classIndex);
+ }
+
+
+ // Implementations for ParameterInfoVisitor.
+
+ public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
+ {
+ markConstant(clazz, parameterInfo.u2nameIndex);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ markConstant(clazz, localVariableInfo.u2nameIndex);
+ markConstant(clazz, localVariableInfo.u2descriptorIndex);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ markConstant(clazz, localVariableTypeInfo.u2nameIndex);
+ markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ markConstant(clazz, annotation.u2typeIndex);
+
+ // Mark the constant pool entries referenced by the element values.
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ if (constantElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, constantElementValue.u2elementNameIndex);
+ }
+
+ markConstant(clazz, constantElementValue.u2constantValueIndex);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ if (enumConstantElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, enumConstantElementValue.u2elementNameIndex);
+ }
+
+ markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
+ markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ if (classElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, classElementValue.u2elementNameIndex);
+ }
+
+ markConstant(clazz, classElementValue.u2classInfoIndex);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ if (annotationElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, annotationElementValue.u2elementNameIndex);
+ }
+
+ // Mark the constant pool entries referenced by the annotation.
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ if (arrayElementValue.u2elementNameIndex != 0)
+ {
+ markConstant(clazz, arrayElementValue.u2elementNameIndex);
+ }
+
+ // Mark the constant pool entries referenced by the element values.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ markConstant(clazz, constantInstruction.constantIndex);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given constant pool entry of the given class. This includes
+ * visiting any referenced objects.
+ */
+ private void markConstant(Clazz clazz, int index)
+ {
+ clazz.constantPoolEntryAccept(index, this);
+ }
+
+
+ /**
+ * Marks the given visitor accepter as being used.
+ */
+ private void markAsUsed(Constant constant)
+ {
+ constant.setVisitorInfo(USED);
+ }
+
+
+ /**
+ * Returns whether the given visitor accepter has been marked as being used.
+ */
+ private boolean isUsed(VisitorAccepter visitorAccepter)
+ {
+ return visitorAccepter.getVisitorInfo() == USED;
+ }
+
+
+ /**
+ * Removes all constants that are not marked as being used from the given
+ * constant pool.
+ * @return the new number of entries.
+ */
+ private int shrinkConstantPool(Constant[] constantPool, int length)
+ {
+ // Create a new index map, if necessary.
+ if (constantIndexMap.length < length)
+ {
+ constantIndexMap = new int[length];
+ }
+
+ int counter = 1;
+ boolean isUsed = false;
+
+ // Shift the used constant pool entries together.
+ for (int index = 1; index < length; index++)
+ {
+ Constant constant = constantPool[index];
+
+ // Is the constant being used? Don't update the flag if this is the
+ // second half of a long entry.
+ if (constant != null)
+ {
+ isUsed = isUsed(constant);
+ }
+
+ if (isUsed)
+ {
+ // Remember the new index.
+ constantIndexMap[index] = counter;
+
+ // Shift the constant pool entry.
+ constantPool[counter++] = constant;
+ }
+ else
+ {
+ // Remember an invalid index.
+ constantIndexMap[index] = -1;
+ }
+ }
+
+ // Clear the remaining constant pool elements.
+ Arrays.fill(constantPool, counter, length, null);
+
+ return counter;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolSorter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolSorter.java
new file mode 100644
index 0000000000..9fc2e3307c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ConstantPoolSorter.java
@@ -0,0 +1,123 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.Constant;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.util.Arrays;
+
+/**
+ * This ClassVisitor sorts the constant pool entries of the program classes
+ * that it visits. The sorting order is based on the types of the constant pool
+ * entries in the first place, and on their contents in the second place.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantPoolSorter
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
+ private ComparableConstant[] comparableConstantPool = new ComparableConstant[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
+ private Constant[] newConstantPool = new Constant[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
+
+ private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ int constantPoolCount = programClass.u2constantPoolCount;
+
+ // Sort the constant pool and set up an index map.
+ if (constantIndexMap.length < constantPoolCount)
+ {
+ constantIndexMap = new int[constantPoolCount];
+ comparableConstantPool = new ComparableConstant[constantPoolCount];
+ newConstantPool = new Constant[constantPoolCount];
+ }
+
+ // Initialize an array whose elements can be compared.
+ int sortLength = 0;
+ for (int oldIndex = 1; oldIndex < constantPoolCount; oldIndex++)
+ {
+ Constant constant = programClass.constantPool[oldIndex];
+ if (constant != null)
+ {
+ comparableConstantPool[sortLength++] =
+ new ComparableConstant(programClass, oldIndex, constant);
+ }
+ }
+
+ // Sort the array.
+ Arrays.sort(comparableConstantPool, 0, sortLength);
+
+ // Save the sorted elements.
+ int newLength = 1;
+ int newIndex = 1;
+ ComparableConstant previousComparableConstant = null;
+ for (int sortIndex = 0; sortIndex < sortLength; sortIndex++)
+ {
+ ComparableConstant comparableConstant = comparableConstantPool[sortIndex];
+
+ // Isn't this a duplicate of the previous constant?
+ if (!comparableConstant.equals(previousComparableConstant))
+ {
+ // Remember the index of the new entry.
+ newIndex = newLength;
+
+ // Copy the sorted constant pool entry over to the constant pool.
+ Constant constant = comparableConstant.getConstant();
+
+ newConstantPool[newLength++] = constant;
+
+ // Long entries take up two slots, the second of which is null.
+ int tag = constant.getTag();
+ if (tag == ClassConstants.CONSTANT_Long ||
+ tag == ClassConstants.CONSTANT_Double)
+ {
+ newConstantPool[newLength++] = null;
+ }
+
+ previousComparableConstant = comparableConstant;
+ }
+
+ // Fill out the map array.
+ constantIndexMap[comparableConstant.getIndex()] = newIndex;
+ }
+
+ // Copy the new constant pool over.
+ System.arraycopy(newConstantPool, 0, programClass.constantPool, 0, newLength);
+
+ // Clear any remaining entries.
+ Arrays.fill(programClass.constantPool, newLength, constantPoolCount, null);
+
+ programClass.u2constantPoolCount = newLength;
+
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ElementValueAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ElementValueAdder.java
new file mode 100644
index 0000000000..808adbdfea
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ElementValueAdder.java
@@ -0,0 +1,217 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+
+/**
+ * This AnnotationVisitor adds all element values that it visits to the given
+ * target annotation default attribute, annotation, or element value.
+ *
+ * @author Eric Lafortune
+ */
+public class ElementValueAdder
+implements ElementValueVisitor
+{
+ private static final ElementValue[] EMPTY_ELEMENT_VALUES = new ElementValue[0];
+
+
+ private final ProgramClass targetClass;
+ private final AnnotationDefaultAttribute targetAnnotationDefaultAttribute;
+
+ private final ConstantAdder constantAdder;
+ private final ElementValuesEditor elementValuesEditor;
+
+
+ /**
+ * Creates a new ElementValueAdder that will copy element values into the
+ * given target annotation default attribute value.
+ */
+ public ElementValueAdder(ProgramClass targetClass,
+ AnnotationDefaultAttribute targetAnnotationDefaultAttribute,
+ boolean replaceElementValues)
+ {
+ this.targetClass = targetClass;
+ this.targetAnnotationDefaultAttribute = targetAnnotationDefaultAttribute;
+
+ constantAdder = new ConstantAdder(targetClass);
+ elementValuesEditor = null;
+ }
+
+
+ /**
+ * Creates a new ElementValueAdder that will copy element values into the
+ * given target annotation.
+ */
+ public ElementValueAdder(ProgramClass targetClass,
+ Annotation targetAnnotation,
+ boolean replaceElementValues)
+ {
+ this.targetClass = targetClass;
+ this.targetAnnotationDefaultAttribute = null;
+
+ constantAdder = new ConstantAdder(targetClass);
+ elementValuesEditor = new ElementValuesEditor(targetClass,
+ targetAnnotation,
+ replaceElementValues);
+ }
+
+
+ /**
+ * Creates a new ElementValueAdder that will copy element values into the
+ * given target element value.
+ */
+ public ElementValueAdder(ProgramClass targetClass,
+ ArrayElementValue targetArrayElementValue,
+ boolean replaceElementValues)
+ {
+ this.targetClass = targetClass;
+ this.targetAnnotationDefaultAttribute = null;
+
+ constantAdder = new ConstantAdder(targetClass);
+ elementValuesEditor = new ElementValuesEditor(targetClass,
+ targetArrayElementValue,
+ replaceElementValues);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ // Create a copy of the element value.
+ ConstantElementValue newConstantElementValue =
+ new ConstantElementValue(constantElementValue.u1tag,
+ constantElementValue.u2elementNameIndex == 0 ? 0 :
+ constantAdder.addConstant(clazz, constantElementValue.u2elementNameIndex),
+ constantAdder.addConstant(clazz, constantElementValue.u2constantValueIndex));
+
+ newConstantElementValue.referencedClass = constantElementValue.referencedClass;
+ newConstantElementValue.referencedMethod = constantElementValue.referencedMethod;
+
+ // Add it to the target.
+ addElementValue(newConstantElementValue);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ // Create a copy of the element value.
+ EnumConstantElementValue newEnumConstantElementValue =
+ new EnumConstantElementValue(enumConstantElementValue.u2elementNameIndex == 0 ? 0 :
+ constantAdder.addConstant(clazz, enumConstantElementValue.u2elementNameIndex),
+ constantAdder.addConstant(clazz, enumConstantElementValue.u2typeNameIndex),
+ constantAdder.addConstant(clazz, enumConstantElementValue.u2constantNameIndex));
+
+ newEnumConstantElementValue.referencedClass = enumConstantElementValue.referencedClass;
+ newEnumConstantElementValue.referencedMethod = enumConstantElementValue.referencedMethod;
+
+ // TODO: Clone array.
+ newEnumConstantElementValue.referencedClasses = enumConstantElementValue.referencedClasses;
+
+ // Add it to the target.
+ addElementValue(newEnumConstantElementValue);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ // Create a copy of the element value.
+ ClassElementValue newClassElementValue =
+ new ClassElementValue(classElementValue.u2elementNameIndex == 0 ? 0 :
+ constantAdder.addConstant(clazz, classElementValue.u2elementNameIndex),
+ constantAdder.addConstant(clazz, classElementValue.u2classInfoIndex));
+
+ newClassElementValue.referencedClass = classElementValue.referencedClass;
+ newClassElementValue.referencedMethod = classElementValue.referencedMethod;
+
+ // TODO: Clone array.
+ newClassElementValue.referencedClasses = classElementValue.referencedClasses;
+
+ // Add it to the target.
+ addElementValue(newClassElementValue);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ // Create a copy of the element value.
+ AnnotationElementValue newAnnotationElementValue =
+ new AnnotationElementValue(annotationElementValue.u2elementNameIndex == 0 ? 0 :
+ constantAdder.addConstant(clazz, annotationElementValue.u2elementNameIndex),
+ new Annotation());
+
+ newAnnotationElementValue.referencedClass = annotationElementValue.referencedClass;
+ newAnnotationElementValue.referencedMethod = annotationElementValue.referencedMethod;
+
+ annotationElementValue.annotationAccept(clazz,
+ new AnnotationAdder(targetClass,
+ newAnnotationElementValue));
+
+ // Add it to the target.
+ addElementValue(newAnnotationElementValue);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ // Create a copy of the element value.
+ ArrayElementValue newArrayElementValue =
+ new ArrayElementValue(arrayElementValue.u2elementNameIndex == 0 ? 0 :
+ constantAdder.addConstant(clazz, arrayElementValue.u2elementNameIndex),
+ 0,
+ arrayElementValue.u2elementValuesCount > 0 ?
+ new ElementValue[arrayElementValue.u2elementValuesCount] :
+ EMPTY_ELEMENT_VALUES);
+
+ newArrayElementValue.referencedClass = arrayElementValue.referencedClass;
+ newArrayElementValue.referencedMethod = arrayElementValue.referencedMethod;
+
+ arrayElementValue.elementValuesAccept(clazz,
+ annotation,
+ new ElementValueAdder(targetClass,
+ newArrayElementValue,
+ false));
+
+ // Add it to the target.
+ addElementValue(newArrayElementValue);
+ }
+
+
+ // Small utility methods.
+
+ private void addElementValue(ElementValue newElementValue)
+ {
+ // What's the target?
+ if (targetAnnotationDefaultAttribute != null)
+ {
+ // Simply set the completed element value.
+ targetAnnotationDefaultAttribute.defaultValue = newElementValue;
+ }
+ else
+ {
+ // Add it to the target.
+ elementValuesEditor.addElementValue(newElementValue);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ElementValuesEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ElementValuesEditor.java
new file mode 100644
index 0000000000..4a4d0f7c07
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ElementValuesEditor.java
@@ -0,0 +1,238 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.ProgramClass;
+import proguard.classfile.attribute.annotation.*;
+
+/**
+ * This class can add and delete element values to and from a given target
+ * annotation default attribute, annotation, or array element value. Element
+ * values to be added must be filled out beforehand, including their references
+ * to the constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class ElementValuesEditor
+{
+ private final ProgramClass targetClass;
+ private final Annotation targetAnnotation;
+ private final ArrayElementValue targetArrayElementValue;
+ private final boolean replaceElementValues;
+
+
+ /**
+ * Creates a new ElementValuesEditor that will edit element values in the
+ * given target annotation.
+ */
+ public ElementValuesEditor(ProgramClass targetClass,
+ Annotation targetAnnotation,
+ boolean replaceElementValues)
+ {
+ this.targetClass = targetClass;
+ this.targetAnnotation = targetAnnotation;
+ this.targetArrayElementValue = null;
+ this.replaceElementValues = replaceElementValues;
+ }
+
+
+ /**
+ * Creates a new ElementValuesEditor that will edit element values in the
+ * given target array element value.
+ */
+ public ElementValuesEditor(ProgramClass targetClass,
+ ArrayElementValue targetArrayElementValue,
+ boolean replaceElementValues)
+ {
+ this.targetClass = targetClass;
+ this.targetAnnotation = null;
+ this.targetArrayElementValue = targetArrayElementValue;
+ this.replaceElementValues = replaceElementValues;
+ }
+
+
+ /**
+ * Adds the given elementValue to the target.
+ */
+ public void addElementValue(ElementValue elementValue)
+ {
+ // What's the target?
+ if (targetAnnotation != null)
+ {
+ // Try to replace an existing element value.
+ if (!replaceElementValues ||
+ !replaceElementValue(targetAnnotation.u2elementValuesCount,
+ targetAnnotation.elementValues,
+ elementValue))
+ {
+ // Otherwise append the element value.
+ targetAnnotation.elementValues =
+ addElementValue(targetAnnotation.u2elementValuesCount,
+ targetAnnotation.elementValues,
+ elementValue);
+
+ targetAnnotation.u2elementValuesCount++;
+ }
+ }
+ else
+ {
+ // Try to replace an existing element value.
+ if (!replaceElementValues ||
+ !replaceElementValue(targetArrayElementValue.u2elementValuesCount,
+ targetArrayElementValue.elementValues,
+ elementValue))
+ {
+ // Otherwise append the element value.
+ targetArrayElementValue.elementValues =
+ addElementValue(targetArrayElementValue.u2elementValuesCount,
+ targetArrayElementValue.elementValues,
+ elementValue);
+
+ targetArrayElementValue.u2elementValuesCount++;
+ }
+ }
+ }
+
+
+ /**
+ * Deletes the given elementValue to the target.
+ */
+ public void deleteElementValue(String elementValueMethodName)
+ {
+ // What's the target?
+ if (targetAnnotation != null)
+ {
+ // Delete the element value to the target annotation.
+ targetAnnotation.u2elementValuesCount =
+ deleteElementValue(targetAnnotation.u2elementValuesCount,
+ targetAnnotation.elementValues,
+ elementValueMethodName);
+ }
+ else
+ {
+ // Delete the element value to the target array element value.
+ targetArrayElementValue.u2elementValuesCount =
+ deleteElementValue(targetArrayElementValue.u2elementValuesCount,
+ targetArrayElementValue.elementValues,
+ elementValueMethodName);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Tries put the given element value in place of an existing element value
+ * of the same name, returning whether it was present.
+ */
+ private boolean replaceElementValue(int elementValuesCount,
+ ElementValue[] elementValues,
+ ElementValue elementValue)
+ {
+ // Find the element value with the same name.
+ int index = findElementValue(elementValuesCount,
+ elementValues,
+ elementValue.getMethodName(targetClass));
+ if (index < 0)
+ {
+ return false;
+ }
+
+ elementValues[index] = elementValue;
+
+ return true;
+ }
+
+
+ /**
+ * Appends the given element value to the given array of element values,
+ * creating a new array if necessary.
+ */
+ private ElementValue[] addElementValue(int elementValuesCount,
+ ElementValue[] elementValues,
+ ElementValue elementValue)
+ {
+ // Is the array too small to contain the additional elementValue?
+ if (elementValues.length <= elementValuesCount)
+ {
+ // Create a new array and copy the elementValues into it.
+ ElementValue[] newElementValues = new ElementValue[elementValuesCount + 1];
+ System.arraycopy(elementValues, 0,
+ newElementValues, 0,
+ elementValuesCount);
+ elementValues = newElementValues;
+ }
+
+ // Append the elementValue.
+ elementValues[elementValuesCount] = elementValue;
+
+ return elementValues;
+ }
+
+
+ /**
+ * Deletes the element values with the given name from the given array of
+ * element values, returning the new number of element values.
+ */
+ private int deleteElementValue(int elementValuesCount,
+ ElementValue[] elementValues,
+ String elementValueMethodName)
+ {
+ // Find the element value.
+ int index = findElementValue(elementValuesCount,
+ elementValues,
+ elementValueMethodName);
+ if (index < 0)
+ {
+ return elementValuesCount;
+ }
+
+ // Shift the other element values in the array.
+ System.arraycopy(elementValues, index + 1,
+ elementValues, index,
+ elementValuesCount - index - 1);
+
+ // Clear the last entry in the array.
+ elementValues[--elementValuesCount] = null;
+
+ return elementValuesCount;
+ }
+
+
+ /**
+ * Finds the index of the element value with the given name in the given
+ * array of element values.
+ */
+ private int findElementValue(int elementValuesCount,
+ ElementValue[] elementValues,
+ String elementValueName)
+ {
+ for (int index = 0; index < elementValuesCount; index++)
+ {
+ if (elementValues[index].getMethodName(targetClass).equals(elementValueName))
+ {
+ return index;
+ }
+ }
+
+ return -1;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionAdder.java
new file mode 100644
index 0000000000..74b6ca2d91
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionAdder.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.ExceptionsAttribute;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This ConstantVisitor adds all class constants that it visits to the given
+ * target exceptions attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionAdder
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final ConstantAdder constantAdder;
+ private final ExceptionsAttributeEditor exceptionsAttributeEditor;
+
+
+ /**
+ * Creates a new ExceptionAdder that will copy classes into the given
+ * target exceptions attribute.
+ */
+ public ExceptionAdder(ProgramClass targetClass,
+ ExceptionsAttribute targetExceptionsAttribute)
+ {
+ constantAdder = new ConstantAdder(targetClass);
+ exceptionsAttributeEditor = new ExceptionsAttributeEditor(targetExceptionsAttribute);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Add a class constant to the constant pool.
+ constantAdder.visitClassConstant(clazz, classConstant);
+
+ // Add the index of the class constant to the list of exceptions.
+ exceptionsAttributeEditor.addException(constantAdder.getConstantIndex());
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionInfoAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionInfoAdder.java
new file mode 100644
index 0000000000..2784bd3d0a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionInfoAdder.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.ExceptionInfoVisitor;
+
+/**
+ * This ExceptionInfoVisitor adds all exception information that it visits to
+ * the given target code attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionInfoAdder
+implements ExceptionInfoVisitor
+{
+ private final ConstantAdder constantAdder;
+ private final CodeAttributeComposer codeAttributeComposer;
+
+
+ /**
+ * Creates a new ExceptionAdder that will copy exceptions into the given
+ * target code attribute.
+ */
+ public ExceptionInfoAdder(ProgramClass targetClass,
+ CodeAttributeComposer targetComposer)
+ {
+ constantAdder = new ConstantAdder(targetClass);
+ codeAttributeComposer = targetComposer;
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ // Create a copy of the exception info.
+ ExceptionInfo newExceptionInfo =
+ new ExceptionInfo(exceptionInfo.u2startPC,
+ exceptionInfo.u2endPC,
+ exceptionInfo.u2handlerPC,
+ exceptionInfo.u2catchType == 0 ? 0 :
+ constantAdder.addConstant(clazz, exceptionInfo.u2catchType));
+
+ // Add the completed exception info.
+ codeAttributeComposer.appendException(newExceptionInfo);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionsAttributeEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionsAttributeEditor.java
new file mode 100644
index 0000000000..783f714caa
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ExceptionsAttributeEditor.java
@@ -0,0 +1,68 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.attribute.ExceptionsAttribute;
+
+/**
+ * This class can add exceptions to a given exceptions attribute.
+ * Exceptions to be added must have been added to the constant pool and filled
+ * out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionsAttributeEditor
+{
+ private ExceptionsAttribute targetExceptionsAttribute;
+
+
+ /**
+ * Creates a new ExceptionsAttributeEditor that will edit exceptions in the
+ * given exceptions attribute.
+ */
+ public ExceptionsAttributeEditor(ExceptionsAttribute targetExceptionsAttribute)
+ {
+ this.targetExceptionsAttribute = targetExceptionsAttribute;
+ }
+
+
+ /**
+ * Adds a given exception to the exceptions attribute.
+ */
+ public void addException(int exceptionIndex)
+ {
+ int exceptionIndexTableLength = targetExceptionsAttribute.u2exceptionIndexTableLength;
+ int[] exceptionIndexTable = targetExceptionsAttribute.u2exceptionIndexTable;
+
+ // Make sure there is enough space for the new exception.
+ if (exceptionIndexTable.length <= exceptionIndexTableLength)
+ {
+ targetExceptionsAttribute.u2exceptionIndexTable = new int[exceptionIndexTableLength+1];
+ System.arraycopy(exceptionIndexTable, 0,
+ targetExceptionsAttribute.u2exceptionIndexTable, 0,
+ exceptionIndexTableLength);
+ exceptionIndexTable = targetExceptionsAttribute.u2exceptionIndexTable;
+ }
+
+ // Add the exception.
+ exceptionIndexTable[targetExceptionsAttribute.u2exceptionIndexTableLength++] = exceptionIndex;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InnerClassesAccessFixer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InnerClassesAccessFixer.java
new file mode 100644
index 0000000000..29364cb18c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InnerClassesAccessFixer.java
@@ -0,0 +1,83 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.InnerClassesInfo;
+import proguard.classfile.attribute.visitor.InnerClassesInfoVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This InnerClassesInfoVisitor fixes the inner class access flags of the
+ * inner classes information that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class InnerClassesAccessFixer
+extends SimplifiedVisitor
+implements InnerClassesInfoVisitor,
+ ConstantVisitor,
+ ClassVisitor
+{
+ private int innerClassAccessFlags;
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ // The current access flags are the default.
+ innerClassAccessFlags = innerClassesInfo.u2innerClassAccessFlags;
+
+ // See if we can find new access flags.
+ innerClassesInfo.innerClassConstantAccept(clazz, this);
+
+ // Update the access flags.
+ innerClassesInfo.u2innerClassAccessFlags = innerClassAccessFlags;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ innerClassAccessFlags =
+ AccessUtil.replaceAccessFlags(innerClassAccessFlags,
+ programClass.u2accessFlags);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InstructionAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InstructionAdder.java
new file mode 100644
index 0000000000..5dae480b7d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InstructionAdder.java
@@ -0,0 +1,76 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor adds all instructions that it visits to the given
+ * target code attribute.
+ *
+ * @author Eric Lafortune
+ */
+public class InstructionAdder
+extends SimplifiedVisitor
+implements InstructionVisitor
+{
+ private final ConstantAdder constantAdder;
+ private final CodeAttributeComposer codeAttributeComposer;
+
+
+ /**
+ * Creates a new InstructionAdder that will copy classes into the given
+ * target code attribute.
+ */
+ public InstructionAdder(ProgramClass targetClass,
+ CodeAttributeComposer targetComposer)
+ {
+ constantAdder = new ConstantAdder(targetClass);
+ codeAttributeComposer = targetComposer;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ // Add the instruction.
+ codeAttributeComposer.appendInstruction(offset, instruction);
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ // Create a copy of the instruction.
+ Instruction newConstantInstruction =
+ new ConstantInstruction(constantInstruction.opcode,
+ constantAdder.addConstant(clazz, constantInstruction.constantIndex),
+ constantInstruction.constant);
+
+ // Add the instruction.
+ codeAttributeComposer.appendInstruction(offset, newConstantInstruction);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InstructionWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InstructionWriter.java
new file mode 100644
index 0000000000..c0174f3865
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InstructionWriter.java
@@ -0,0 +1,320 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor writes out the instructions that it visits,
+ * collecting instructions that have to be widened. As an AttributeVisitor,
+ * it then applies the collected changes. The process will be repeated
+ * recursively, if necessary. The caller still has to update the frame sizes.
+ *
+ * @author Eric Lafortune
+ */
+public class InstructionWriter
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ AttributeVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ public static boolean DEBUG = false;
+ //*/
+
+
+ private int codeLength;
+
+ private CodeAttributeEditor codeAttributeEditor;
+
+
+ /**
+ * Resets the accumulated code.
+ * @param codeLength the length of the code that will be edited next.
+ */
+ public void reset(int codeLength)
+ {
+ this.codeLength = codeLength;
+
+ if (codeAttributeEditor != null)
+ {
+ codeAttributeEditor.reset(codeLength);
+ }
+ }
+
+
+ /**
+ * Extends the size of the accumulated code.
+ * @param codeLength the length of the code that will be edited next.
+ */
+ public void extend(int codeLength)
+ {
+ this.codeLength = codeLength;
+
+ if (codeAttributeEditor != null)
+ {
+ codeAttributeEditor.extend(codeLength);
+ }
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ // Try to write out the instruction.
+ // Simple instructions should always fit.
+ simpleInstruction.write(codeAttribute, offset);
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ try
+ {
+ // Try to write out the instruction.
+ constantInstruction.write(codeAttribute, offset);
+ }
+ catch (IllegalArgumentException exception)
+ {
+ // Create a new constant instruction that will fit.
+ Instruction replacementInstruction =
+ new ConstantInstruction(constantInstruction.opcode,
+ constantInstruction.constantIndex,
+ constantInstruction.constant);
+
+ if (DEBUG)
+ {
+ System.out.println(" "+constantInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString());
+ }
+
+ replaceInstruction(offset, replacementInstruction);
+
+ // Write out a dummy constant instruction for now.
+ constantInstruction.constantIndex = 0;
+ constantInstruction.constant = 0;
+ constantInstruction.write(codeAttribute, offset);
+ }
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ try
+ {
+ // Try to write out the instruction.
+ variableInstruction.write(codeAttribute, offset);
+ }
+ catch (IllegalArgumentException exception)
+ {
+ // Create a new variable instruction that will fit.
+ Instruction replacementInstruction =
+ new VariableInstruction(variableInstruction.opcode,
+ variableInstruction.variableIndex,
+ variableInstruction.constant);
+
+ replaceInstruction(offset, replacementInstruction);
+
+ if (DEBUG)
+ {
+ System.out.println(" "+variableInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString());
+ }
+
+ // Write out a dummy variable instruction for now.
+ variableInstruction.variableIndex = 0;
+ variableInstruction.constant = 0;
+ variableInstruction.write(codeAttribute, offset);
+ }
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ try
+ {
+ // Try to write out the instruction.
+ branchInstruction.write(codeAttribute, offset);
+ }
+ catch (IllegalArgumentException exception)
+ {
+ // Create a new unconditional branch that will fit.
+ Instruction replacementInstruction =
+ new BranchInstruction(InstructionConstants.OP_GOTO_W,
+ branchInstruction.branchOffset);
+
+ // Create a new instruction that will fit.
+ switch (branchInstruction.opcode)
+ {
+ default:
+ {
+ // Create a new branch instruction that will fit.
+ replacementInstruction =
+ new BranchInstruction(branchInstruction.opcode,
+ branchInstruction.branchOffset);
+
+ break;
+ }
+
+ // Some special cases, for which a wide branch doesn't exist.
+ case InstructionConstants.OP_IFEQ:
+ case InstructionConstants.OP_IFNE:
+ case InstructionConstants.OP_IFLT:
+ case InstructionConstants.OP_IFGE:
+ case InstructionConstants.OP_IFGT:
+ case InstructionConstants.OP_IFLE:
+ case InstructionConstants.OP_IFICMPEQ:
+ case InstructionConstants.OP_IFICMPNE:
+ case InstructionConstants.OP_IFICMPLT:
+ case InstructionConstants.OP_IFICMPGE:
+ case InstructionConstants.OP_IFICMPGT:
+ case InstructionConstants.OP_IFICMPLE:
+ case InstructionConstants.OP_IFACMPEQ:
+ case InstructionConstants.OP_IFACMPNE:
+ {
+ // Insert the complementary conditional branch.
+ Instruction complementaryConditionalBranch =
+ new BranchInstruction((byte)(((branchInstruction.opcode+1) ^ 1) - 1),
+ (1+2) + (1+4));
+
+ insertBeforeInstruction(offset, complementaryConditionalBranch);
+
+ // Create a new unconditional branch that will fit.
+ break;
+ }
+
+ case InstructionConstants.OP_IFNULL:
+ case InstructionConstants.OP_IFNONNULL:
+ {
+ // Insert the complementary conditional branch.
+ Instruction complementaryConditionalBranch =
+ new BranchInstruction((byte)(branchInstruction.opcode ^ 1),
+ (1+2) + (1+4));
+
+ insertBeforeInstruction(offset, complementaryConditionalBranch);
+
+ // Create a new unconditional branch that will fit.
+ break;
+ }
+ }
+
+ if (DEBUG)
+ {
+ System.out.println(" "+branchInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString());
+ }
+
+ replaceInstruction(offset, replacementInstruction);
+
+ // Write out a dummy branch instruction for now.
+ branchInstruction.branchOffset = 0;
+ branchInstruction.write(codeAttribute, offset);
+ }
+ }
+
+
+ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ {
+ // Try to write out the instruction.
+ // Switch instructions should always fit.
+ switchInstruction.write(codeAttribute, offset);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Avoid doing any work if nothing is changing anyway.
+ if (codeAttributeEditor != null)
+ {
+ if (DEBUG)
+ {
+ System.out.println("InstructionWriter: widening instructions in "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ }
+
+ // Apply the collected expansions.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Don't keep the editor around. We're assuming it won't be needed
+ // very often, so we don't want to be resetting it all the time.
+ codeAttributeEditor = null;
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Remembers to place the given instruction right before the instruction
+ * at the given offset.
+ */
+ private void insertBeforeInstruction(int instructionOffset, Instruction instruction)
+ {
+ ensureCodeAttributeEditor();
+
+ // Replace the instruction.
+ codeAttributeEditor.insertBeforeInstruction(instructionOffset, instruction);
+ }
+
+
+ /**
+ * Remembers to replace the instruction at the given offset by the given
+ * instruction.
+ */
+ private void replaceInstruction(int instructionOffset, Instruction instruction)
+ {
+ ensureCodeAttributeEditor();
+
+ // Replace the instruction.
+ codeAttributeEditor.replaceInstruction(instructionOffset, instruction);
+ }
+
+
+ /**
+ * Remembers to place the given instruction right after the instruction
+ * at the given offset.
+ */
+ private void insertAfterInstruction(int instructionOffset, Instruction instruction)
+ {
+ ensureCodeAttributeEditor();
+
+ // Replace the instruction.
+ codeAttributeEditor.insertAfterInstruction(instructionOffset, instruction);
+ }
+
+
+ /**
+ * Makes sure there is a code attribute editor for the given code attribute.
+ */
+ private void ensureCodeAttributeEditor()
+ {
+ if (codeAttributeEditor == null)
+ {
+ codeAttributeEditor = new CodeAttributeEditor(false, true);
+ codeAttributeEditor.reset(codeLength);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceAdder.java
new file mode 100644
index 0000000000..7cc8de8735
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceAdder.java
@@ -0,0 +1,59 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This ConstantVisitor adds all interfaces that it visits to the given
+ * target class.
+ *
+ * @author Eric Lafortune
+ */
+public class InterfaceAdder
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final ConstantAdder constantAdder;
+ private final InterfacesEditor interfacesEditor;
+
+
+ /**
+ * Creates a new InterfaceAdder that will add interfaces to the given
+ * target class.
+ */
+ public InterfaceAdder(ProgramClass targetClass)
+ {
+ constantAdder = new ConstantAdder(targetClass);
+ interfacesEditor = new InterfacesEditor(targetClass);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ interfacesEditor.addInterface(constantAdder.addConstant(clazz, classConstant));
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceDeleter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceDeleter.java
new file mode 100644
index 0000000000..5cbf068fa5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceDeleter.java
@@ -0,0 +1,209 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.Utf8Constant;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.util.Arrays;
+
+/**
+ * This ClassVisitor removes specified interfaces from the classes and class
+ * signatures that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class InterfaceDeleter
+extends SimplifiedVisitor
+implements ClassVisitor,
+ AttributeVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ private final boolean[] delete;
+
+
+ /**
+ * Creates a new InterfaceDeleter to remove the specified interfaces.
+ * @param delete an array that corresponds to the interfaces of a class
+ * and that specifies the ones to be removed.
+ */
+ public InterfaceDeleter(boolean[] delete)
+ {
+ this.delete = delete;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ int[] interfaces = programClass.u2interfaces;
+ int interfacesCount = programClass.u2interfacesCount;
+
+ if (DEBUG)
+ {
+ System.out.println("InterfaceDeleter: "+programClass.getName()+" ("+interfacesCount+" interfaces)");
+ }
+
+ // Copy the interfaces that aren't deleted.
+ int newInterfacesCount = 0;
+ for (int index = 0; index < interfacesCount; index++)
+ {
+ if (DEBUG)
+ {
+ System.out.println("InterfaceDeleter: "+(delete[index]?"- ":"+ ")+programClass.getInterfaceName(index));
+ }
+
+ if (!delete[index])
+ {
+ interfaces[newInterfacesCount++] = interfaces[index];
+ }
+ }
+
+ // Update the signature.
+ if (newInterfacesCount < interfacesCount)
+ {
+ programClass.u2interfacesCount = newInterfacesCount;
+
+ programClass.attributesAccept(this);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ Clazz[] referencedClasses = signatureAttribute.referencedClasses;
+ if (referencedClasses != null)
+ {
+ // Process the generic definitions, superclass, and implemented
+ // interfaces.
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(signatureAttribute.getSignature(clazz));
+
+ // Recompose the signature types in a string buffer.
+ StringBuffer newSignatureBuffer = new StringBuffer();
+
+ // Also update the array with referenced classes.
+ int referencedClassIndex = 0;
+ int newReferencedClassIndex = 0;
+
+ // Copy the variable type declarations.
+ if (internalTypeEnumeration.hasFormalTypeParameters())
+ {
+ String type = internalTypeEnumeration.formalTypeParameters();
+
+ // Append the type.
+ newSignatureBuffer.append(type);
+
+ // Copy any referenced classes.
+ int classCount =
+ new DescriptorClassEnumeration(type).classCount();
+
+ for (int counter = 0; counter < classCount; counter++)
+ {
+ referencedClasses[newReferencedClassIndex++] =
+ referencedClasses[referencedClassIndex++];
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("InterfaceDeleter: type parameters = " + type);
+ }
+ }
+
+ // Copy the super class type.
+ if (internalTypeEnumeration.hasMoreTypes())
+ {
+ String type = internalTypeEnumeration.nextType();
+
+ // Append the type.
+ newSignatureBuffer.append(type);
+
+ // Copy any referenced classes.
+ int classCount =
+ new DescriptorClassEnumeration(type).classCount();
+
+ for (int counter = 0; counter < classCount; counter++)
+ {
+ referencedClasses[newReferencedClassIndex++] =
+ referencedClasses[referencedClassIndex++];
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("InterfaceDeleter: super class type = " + type);
+ }
+ }
+
+ // Copy the interface types.
+ int index = 0;
+ while (internalTypeEnumeration.hasMoreTypes())
+ {
+ String type = internalTypeEnumeration.nextType();
+
+ int classCount =
+ new DescriptorClassEnumeration(type).classCount();
+
+ if (DEBUG)
+ {
+ System.out.println("InterfaceDeleter: interface type " + (delete[index] ? "- " : "+ ") + type + " (" + classCount + " referenced classes)");
+ }
+
+ if (!delete[index++])
+ {
+ // Append the type.
+ newSignatureBuffer.append(type);
+
+ // Copy any referenced classes.
+ for (int counter = 0; counter < classCount; counter++)
+ {
+ referencedClasses[newReferencedClassIndex++] =
+ referencedClasses[referencedClassIndex++];
+ }
+ }
+ else
+ {
+ referencedClassIndex += classCount;
+ }
+ }
+
+ // Update the signature.
+ ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString());
+
+ // Clear the remaining referenced classes.
+ Arrays.fill(referencedClasses,
+ newReferencedClassIndex,
+ referencedClassIndex,
+ null);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceSorter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceSorter.java
new file mode 100644
index 0000000000..41cef213fe
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfaceSorter.java
@@ -0,0 +1,246 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.Utf8Constant;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.util.Arrays;
+
+/**
+ * This ClassVisitor sorts the interfaces of the program classes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class InterfaceSorter
+extends SimplifiedVisitor
+implements ClassVisitor,
+ AttributeVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ int[] interfaces = programClass.u2interfaces;
+ int interfacesCount = programClass.u2interfacesCount;
+
+ if (interfacesCount > 1)
+ {
+ // Sort the interfaces.
+ Arrays.sort(interfaces, 0, interfacesCount);
+
+ // Update the signature.
+ programClass.attributesAccept(this);
+
+ // Remove any duplicate entries.
+ boolean[] delete = null;
+ for (int index = 1; index < interfacesCount; index++)
+ {
+ if (interfaces[index] == interfaces[index - 1])
+ {
+ // Lazily create the array.
+ if (delete == null)
+ {
+ delete = new boolean[interfacesCount];
+ }
+
+ delete[index] = true;
+ }
+ }
+
+ if (delete != null)
+ {
+ new InterfaceDeleter(delete).visitProgramClass(programClass);
+ }
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ Clazz[] referencedClasses = signatureAttribute.referencedClasses;
+ Clazz[] newReferencedClasses = referencedClasses == null ? null :
+ new Clazz[referencedClasses.length];
+
+ // Recompose the signature types in a string buffer.
+ StringBuffer newSignatureBuffer = new StringBuffer();
+
+ // Also update the array with referenced classes.
+ int referencedClassIndex = 0;
+ int newReferencedClassIndex = 0;
+
+ // Process the generic definitions and superclass.
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(signatureAttribute.getSignature(clazz));
+
+ // Copy the variable type declarations.
+ if (internalTypeEnumeration.hasFormalTypeParameters())
+ {
+ String type = internalTypeEnumeration.formalTypeParameters();
+
+ // Append the type.
+ newSignatureBuffer.append(type);
+
+ // Copy any referenced classes.
+ if (newReferencedClasses != null)
+ {
+ int classCount =
+ new DescriptorClassEnumeration(type).classCount();
+
+ for (int counter = 0; counter < classCount; counter++)
+ {
+ newReferencedClasses[newReferencedClassIndex++] =
+ referencedClasses[referencedClassIndex++];
+ }
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("InterfaceDeleter: type parameters = " + type);
+ }
+ }
+
+ // Copy the super class type.
+ if (internalTypeEnumeration.hasMoreTypes())
+ {
+ String type = internalTypeEnumeration.nextType();
+
+ // Append the type.
+ newSignatureBuffer.append(type);
+
+ // Copy any referenced classes.
+ if (newReferencedClasses != null)
+ {
+ int classCount =
+ new DescriptorClassEnumeration(type).classCount();
+
+ for (int counter = 0; counter < classCount; counter++)
+ {
+ newReferencedClasses[newReferencedClassIndex++] =
+ referencedClasses[referencedClassIndex++];
+ }
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("InterfaceSorter: super class type = " + type);
+ }
+ }
+
+ int firstReferencedInterfaceIndex = referencedClassIndex;
+
+ // Copy the interface types, based on the sorted interface classes.
+ // This has the advantage that we will disregard any interface types
+ // that are not in the interface classes, like in some versions of
+ // the Scala runtime library.
+ for (int interfaceIndex = 0; interfaceIndex < clazz.getInterfaceCount(); interfaceIndex++)
+ {
+ // Consider the interface class name.
+ String interfaceName = clazz.getInterfaceName(interfaceIndex);
+
+ referencedClassIndex = firstReferencedInterfaceIndex;
+
+ // Find the corresponding interface type.
+ InternalTypeEnumeration internalInterfaceTypeEnumeration =
+ new InternalTypeEnumeration(signatureAttribute.getSignature(clazz));
+
+ // Skip the superclass type.
+ internalInterfaceTypeEnumeration.nextType();
+
+ while (internalInterfaceTypeEnumeration.hasMoreTypes())
+ {
+ String type = internalInterfaceTypeEnumeration.nextType();
+
+ DescriptorClassEnumeration classEnumeration =
+ new DescriptorClassEnumeration(type);
+
+ int classCount =
+ classEnumeration.classCount();
+
+ classEnumeration.nextFluff();
+
+ if (interfaceName.equals(classEnumeration.nextClassName()))
+ {
+ // Append the type.
+ newSignatureBuffer.append(type);
+
+ // Copy any referenced classes.
+ if (newReferencedClasses != null)
+ {
+ for (int counter = 0; counter < classCount; counter++)
+ {
+ newReferencedClasses[newReferencedClassIndex++] =
+ referencedClasses[referencedClassIndex++];
+ }
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("InterfaceSorter: interface type = " + type);
+ }
+ }
+ else
+ {
+ // Skip all referenced classes.
+ referencedClassIndex += classCount;
+ }
+ }
+ }
+
+ String newSignature = newSignatureBuffer.toString();
+
+ // Did the signature change?
+ if (!newSignature.equals(signatureAttribute.getSignature(clazz)))
+ {
+ // Update the signature.
+ ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString());
+
+ // Update the referenced classes.
+ signatureAttribute.referencedClasses = newReferencedClasses;
+
+ if (DEBUG)
+ {
+ System.out.println("InterfaceSorter: result = "+newSignature);
+ System.out.println("InterfaceSorter: referenced classes:");
+
+ if (newReferencedClasses != null)
+ {
+ for (int index = 0; index < newReferencedClasses.length; index++)
+ {
+ System.out.println(" #"+index+" "+newReferencedClasses[index]);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfacesEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfacesEditor.java
new file mode 100644
index 0000000000..7d0599b205
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/InterfacesEditor.java
@@ -0,0 +1,109 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.ProgramClass;
+import proguard.util.ArrayUtil;
+
+/**
+ * This class can add and delete interfaces to and from classes. References to
+ * the constant pool must be filled out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class InterfacesEditor
+{
+ private final ProgramClass targetClass;
+
+
+ /**
+ * Creates a new InterfacesEditor that will edit interfaces in the given
+ * target class.
+ */
+ public InterfacesEditor(ProgramClass targetClass)
+ {
+ this.targetClass = targetClass;
+ }
+
+
+ /**
+ * Adds the specified interface to the target class, if it isn't present yet.
+ */
+ public void addInterface(int interfaceConstantIndex)
+ {
+ // Is the interface not yet present?
+ if (findInterfaceIndex(interfaceConstantIndex) < 0)
+ {
+ // Append the interface.
+ targetClass.u2interfaces =
+ ArrayUtil.add(targetClass.u2interfaces,
+ targetClass.u2interfacesCount++,
+ interfaceConstantIndex);
+ }
+ }
+
+
+ /**
+ * Deletes the given interface from the target class, if it is present.
+ */
+ public void deleteInterface(int interfaceConstantIndex)
+ {
+ // Is the interface already present?
+ int interfaceIndex = findInterfaceIndex(interfaceConstantIndex);
+ if (interfaceIndex >= 0)
+ {
+ int interfacesCount = --targetClass.u2interfacesCount;
+ int[] interfaces = targetClass.u2interfaces;
+
+ // Shift the other interfaces in the array.
+ for (int index = interfaceIndex; index < interfacesCount; index++)
+ {
+ interfaces[index] = interfaces[index + 1];
+ }
+
+ // Clear the remaining entry in the array.
+ interfaces[interfacesCount] = 0;
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Finds the index of the specified interface in the list of interfaces of
+ * the target class.
+ */
+ private int findInterfaceIndex(int interfaceConstantIndex)
+ {
+ int interfacesCount = targetClass.u2interfacesCount;
+ int[] interfaces = targetClass.u2interfaces;
+
+ for (int index = 0; index < interfacesCount; index++)
+ {
+ if (interfaces[index] == interfaceConstantIndex)
+ {
+ return index;
+ }
+ }
+
+ return -1;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberInfoAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberInfoAdder.java
new file mode 100644
index 0000000000..f499d294f1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberInfoAdder.java
@@ -0,0 +1,91 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor adds the line numbers of all line number attributes
+ * that it visits to the given target line number attribute. It ensures that
+ * the sources of the line numbers are preserved or set.
+ */
+public class LineNumberInfoAdder
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ LineNumberInfoVisitor
+{
+ private final LineNumberTableAttributeEditor lineNumberTableAttributeEditor;
+
+ private String source;
+
+
+ /**
+ * Creates a new LineNumberInfoAdder that will copy line numbers into the
+ * given target line number table.
+ */
+ public LineNumberInfoAdder(LineNumberTableAttribute targetLineNumberTableAttribute)
+ {
+ this.lineNumberTableAttributeEditor = new LineNumberTableAttributeEditor(targetLineNumberTableAttribute);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ // Remember the source.
+ source =
+ clazz.getName() + '.' +
+ method.getName(clazz) +
+ method.getDescriptor(clazz) + ':' +
+ lineNumberTableAttribute.getLowestLineNumber() + ':' +
+ lineNumberTableAttribute.getHighestLineNumber();
+
+ // Copy all line numbers.
+ lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ // Implementations for LineNumberInfoVisitor.
+
+ public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
+ {
+ // Make sure we have a source.
+ String newSource = lineNumberInfo.getSource() != null ?
+ lineNumberInfo.getSource() :
+ source;
+
+ // Create a new line number.
+ LineNumberInfo newLineNumberInfo =
+ new ExtendedLineNumberInfo(lineNumberInfo.u2startPC,
+ lineNumberInfo.u2lineNumber,
+ newSource);
+
+ // Add it to the target.
+ lineNumberTableAttributeEditor.addLineNumberInfo(newLineNumberInfo);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java
new file mode 100644
index 0000000000..3eded4e929
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.attribute.*;
+
+/**
+ * This class can add line numbers to a given line number table attribute.
+ * Line numbers to be added must have been filled out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class LineNumberTableAttributeEditor
+{
+ private LineNumberTableAttribute targetLineNumberTableAttribute;
+
+
+ /**
+ * Creates a new LineNumberTableAttributeEditor that will edit line numbers
+ * in the given line number table attribute.
+ */
+ public LineNumberTableAttributeEditor(LineNumberTableAttribute targetLineNumberTableAttribute)
+ {
+ this.targetLineNumberTableAttribute = targetLineNumberTableAttribute;
+ }
+
+
+ /**
+ * Adds a given line number to the line number table attribute.
+ */
+ public void addLineNumberInfo(LineNumberInfo lineNumberInfo)
+ {
+ int lineNumberTableLength = targetLineNumberTableAttribute.u2lineNumberTableLength;
+ LineNumberInfo[] lineNumberTable = targetLineNumberTableAttribute.lineNumberTable;
+
+ // Make sure there is enough space for the new lineNumberInfo.
+ if (lineNumberTable.length <= lineNumberTableLength)
+ {
+ targetLineNumberTableAttribute.lineNumberTable = new LineNumberInfo[lineNumberTableLength+1];
+ System.arraycopy(lineNumberTable, 0,
+ targetLineNumberTableAttribute.lineNumberTable, 0,
+ lineNumberTableLength);
+ lineNumberTable = targetLineNumberTableAttribute.lineNumberTable;
+ }
+
+ // Add the lineNumberInfo.
+ lineNumberTable[targetLineNumberTableAttribute.u2lineNumberTableLength++] = lineNumberInfo;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberTableAttributeTrimmer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberTableAttributeTrimmer.java
new file mode 100644
index 0000000000..8d860c31ba
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LineNumberTableAttributeTrimmer.java
@@ -0,0 +1,78 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor trims the line number table attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class LineNumberTableAttributeTrimmer
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ LineNumberInfo[] lineNumberTable = lineNumberTableAttribute.lineNumberTable;
+ int lineNumberTableLength = lineNumberTableAttribute.u2lineNumberTableLength;
+
+ // Overwrite all empty line number entries.
+ int newIndex = 0;
+ for (int index = 0; index < lineNumberTableLength; index++)
+ {
+ LineNumberInfo lineNumberInfo = lineNumberTable[index];
+
+ int startPC = lineNumberInfo.u2startPC;
+ int lineNumber = lineNumberInfo.u2lineNumber;
+
+ // The offset must lie inside the code.
+ // The offset must be smaller than the next one.
+ // The line number should be different from the previous one.
+ if (startPC < codeAttribute.u4codeLength &&
+
+ (index == lineNumberTableLength - 1 ||
+ startPC < lineNumberTable[index + 1].u2startPC) &&
+
+ (index == 0 ||
+ lineNumber != lineNumberTable[index - 1].u2lineNumber))
+ {
+ lineNumberTable[newIndex++] = lineNumberInfo;
+ }
+ }
+
+ // Clear the unused array entries.
+ Arrays.fill(lineNumberTable, newIndex, lineNumberTableAttribute.u2lineNumberTableLength, null);
+
+ lineNumberTableAttribute.u2lineNumberTableLength = newIndex;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableInfoAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableInfoAdder.java
new file mode 100644
index 0000000000..909dc8f74a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableInfoAdder.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.LocalVariableInfoVisitor;
+
+/**
+ * This LocalVariableInfoVisitor adds all local variables that it visits to the
+ * given target local variable table attribute.
+ */
+public class LocalVariableInfoAdder
+implements LocalVariableInfoVisitor
+{
+ private final ConstantAdder constantAdder;
+ private final LocalVariableTableAttributeEditor localVariableTableAttributeEditor;
+
+
+ /**
+ * Creates a new LocalVariableInfoAdder that will copy local variables
+ * into the given target local variable table.
+ */
+ public LocalVariableInfoAdder(ProgramClass targetClass,
+ LocalVariableTableAttribute targetLocalVariableTableAttribute)
+ {
+ this.constantAdder = new ConstantAdder(targetClass);
+ this.localVariableTableAttributeEditor = new LocalVariableTableAttributeEditor(targetLocalVariableTableAttribute);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Create a new local variable.
+ LocalVariableInfo newLocalVariableInfo =
+ new LocalVariableInfo(localVariableInfo.u2startPC,
+ localVariableInfo.u2length,
+ constantAdder.addConstant(clazz, localVariableInfo.u2nameIndex),
+ constantAdder.addConstant(clazz, localVariableInfo.u2descriptorIndex),
+ localVariableInfo.u2index);
+
+ newLocalVariableInfo.referencedClass = localVariableInfo.referencedClass;
+
+ // Add it to the target.
+ localVariableTableAttributeEditor.addLocalVariableInfo(newLocalVariableInfo);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java
new file mode 100644
index 0000000000..360d485f15
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java
@@ -0,0 +1,57 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.attribute.*;
+import proguard.util.ArrayUtil;
+
+/**
+ * This class can add local variables to a given local variable table attribute.
+ * Local variables to be added must have been filled out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTableAttributeEditor
+{
+ private final LocalVariableTableAttribute targetLocalVariableTableAttribute;
+
+
+ /**
+ * Creates a new LocalVariableTableAttributeEditor that will edit local
+ * variables in the given local variable table attribute.
+ */
+ public LocalVariableTableAttributeEditor(LocalVariableTableAttribute targetLocalVariableTableAttribute)
+ {
+ this.targetLocalVariableTableAttribute = targetLocalVariableTableAttribute;
+ }
+
+
+ /**
+ * Adds a given line number to the line number table attribute.
+ */
+ public void addLocalVariableInfo(LocalVariableInfo localVariableInfo)
+ {
+ targetLocalVariableTableAttribute.localVariableTable =
+ (LocalVariableInfo[])ArrayUtil.add(targetLocalVariableTableAttribute.localVariableTable,
+ targetLocalVariableTableAttribute.u2localVariableTableLength++,
+ localVariableInfo);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java
new file mode 100644
index 0000000000..eec3c024cf
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java
@@ -0,0 +1,68 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.LocalVariableTypeInfoVisitor;
+
+/**
+ * This LocalVariableTypeInfoVisitor adds all local variable types that it
+ * visits to the given target local variable type attribute.
+ */
+public class LocalVariableTypeInfoAdder
+implements LocalVariableTypeInfoVisitor
+{
+ private final ConstantAdder constantAdder;
+ private final LocalVariableTypeTableAttributeEditor localVariableTypeTableAttributeEditor;
+
+
+ /**
+ * Creates a new LocalVariableTypeInfoAdder that will copy local variable
+ * types into the given target local variable type table.
+ */
+ public LocalVariableTypeInfoAdder(ProgramClass targetClass,
+ LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute)
+ {
+ this.constantAdder = new ConstantAdder(targetClass);
+ this.localVariableTypeTableAttributeEditor = new LocalVariableTypeTableAttributeEditor(targetLocalVariableTypeTableAttribute);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Create a new local variable type.
+ LocalVariableTypeInfo newLocalVariableTypeInfo =
+ new LocalVariableTypeInfo(localVariableTypeInfo.u2startPC,
+ localVariableTypeInfo.u2length,
+ constantAdder.addConstant(clazz, localVariableTypeInfo.u2nameIndex),
+ constantAdder.addConstant(clazz, localVariableTypeInfo.u2signatureIndex),
+ localVariableTypeInfo.u2index);
+
+ // TODO: Clone array.
+ newLocalVariableTypeInfo.referencedClasses = localVariableTypeInfo.referencedClasses;
+
+ // Add it to the target.
+ localVariableTypeTableAttributeEditor.addLocalVariableTypeInfo(newLocalVariableTypeInfo);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java
new file mode 100644
index 0000000000..5e4d6e0e75
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java
@@ -0,0 +1,58 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.attribute.*;
+import proguard.util.ArrayUtil;
+
+/**
+ * This class can add local variables to a given local variable type table
+ * attribute.
+ * Local variable types to be added must have been filled out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTypeTableAttributeEditor
+{
+ private final LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute;
+
+
+ /**
+ * Creates a new LocalVariableTypeTableAttributeEditor that will edit local
+ * variable types in the given local variable type table attribute.
+ */
+ public LocalVariableTypeTableAttributeEditor(LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute)
+ {
+ this.targetLocalVariableTypeTableAttribute = targetLocalVariableTypeTableAttribute;
+ }
+
+
+ /**
+ * Adds a given local variable type to the local variable type table attribute.
+ */
+ public void addLocalVariableTypeInfo(LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ targetLocalVariableTypeTableAttribute.localVariableTypeTable =
+ (LocalVariableTypeInfo[])ArrayUtil.add(targetLocalVariableTypeTableAttribute.localVariableTypeTable,
+ targetLocalVariableTypeTableAttribute.u2localVariableTypeTableLength++,
+ localVariableTypeInfo);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MemberAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MemberAdder.java
new file mode 100644
index 0000000000..2bd953d7d6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MemberAdder.java
@@ -0,0 +1,294 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor copies all class members that it visits to the given
+ * target class. Their visitor info is set to the class members from which they
+ * were copied.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberAdder
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = true;
+ //*/
+
+
+ private static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0];
+
+
+ private final ProgramClass targetClass;
+// private final boolean addFields;
+ private final MemberVisitor extraMemberVisitor;
+
+ private final ConstantAdder constantAdder;
+ private final ClassEditor classEditor;
+ private final ConstantPoolEditor constantPoolEditor;
+
+
+ /**
+ * Creates a new MemberAdder that will copy methods into the given target
+ * class.
+ * @param targetClass the class to which all visited class members will be
+ * added.
+ */
+ public MemberAdder(ProgramClass targetClass)
+ {
+ this(targetClass, null);
+ }
+
+
+ /**
+ * Creates a new MemberAdder that will copy methods into the given target
+ * class.
+ * @param targetClass the class to which all visited class members
+ * will be added.
+ * @param extraMemberVisitor an optional member visitor that visits each
+ * new member right after it has been added. This
+ * allows changing the visitor info, for instance.
+ */
+// * @param addFields specifies whether fields should be added, or fused
+// * with the present fields.
+ public MemberAdder(ProgramClass targetClass,
+// boolean addFields,
+ MemberVisitor extraMemberVisitor)
+ {
+ this.targetClass = targetClass;
+// this.addFields = addFields;
+ this.extraMemberVisitor = extraMemberVisitor;
+
+ constantAdder = new ConstantAdder(targetClass);
+ classEditor = new ClassEditor(targetClass);
+ constantPoolEditor = new ConstantPoolEditor(targetClass);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ //String name = programField.getName(programClass);
+ //String descriptor = programField.getDescriptor(programClass);
+ int accessFlags = programField.getAccessFlags();
+
+ // TODO: Handle field with the same name and descriptor in the target class.
+ // We currently avoid this case, since renaming the identical field
+ // still causes confused field references.
+ //// Does the target class already have such a field?
+ //ProgramField targetField = (ProgramField)targetClass.findField(name, descriptor);
+ //if (targetField != null)
+ //{
+ // // Is the field private or static?
+ // int targetAccessFlags = targetField.getAccessFlags();
+ // if ((targetAccessFlags &
+ // (ClassConstants.ACC_PRIVATE |
+ // ClassConstants.ACC_STATIC)) != 0)
+ // {
+ // if (DEBUG)
+ // {
+ // System.out.println("MemberAdder: renaming field ["+targetClass+"."+targetField.getName(targetClass)+" "+targetField.getDescriptor(targetClass)+"]");
+ // }
+ //
+ // // Rename the private or static field.
+ // targetField.u2nameIndex =
+ // constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, targetClass.getName()));
+ // }
+ // else
+ // {
+ // // Keep the non-private and non-static field, but update its
+ // // contents, in order to keep any references to it valid.
+ // if (DEBUG)
+ // {
+ // System.out.println("MemberAdder: updating field ["+programClass+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
+ // }
+ //
+ // // Combine the access flags.
+ // targetField.u2accessFlags = accessFlags | targetAccessFlags;
+ //
+ // // Add and replace any attributes.
+ // programField.attributesAccept(programClass,
+ // new AttributeAdder(targetClass,
+ // targetField,
+ // true));
+ //
+ // // Don't add a new field.
+ // return;
+ // }
+ //}
+
+ if (DEBUG)
+ {
+ System.out.println("MemberAdder: copying field ["+programClass+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
+ }
+
+ // Create a copy of the field.
+ ProgramField newProgramField =
+ new ProgramField(accessFlags,
+ constantAdder.addConstant(programClass, programField.u2nameIndex),
+ constantAdder.addConstant(programClass, programField.u2descriptorIndex),
+ 0,
+ programField.u2attributesCount > 0 ?
+ new Attribute[programField.u2attributesCount] :
+ EMPTY_ATTRIBUTES,
+ programField.referencedClass);
+
+ // Link to its visitor info.
+ newProgramField.setVisitorInfo(programField);
+
+ // Copy its attributes.
+ programField.attributesAccept(programClass,
+ new AttributeAdder(targetClass,
+ newProgramField,
+ false));
+
+ // Add the completed field.
+ classEditor.addField(newProgramField);
+
+ // Visit the newly added field, if necessary.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramField(targetClass, newProgramField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ String name = programMethod.getName(programClass);
+ String descriptor = programMethod.getDescriptor(programClass);
+ int accessFlags = programMethod.getAccessFlags();
+
+ // Does the target class already have such a method?
+ ProgramMethod targetMethod = (ProgramMethod)targetClass.findMethod(name, descriptor);
+ if (targetMethod != null)
+ {
+ // is this source method abstract?
+ if ((accessFlags & ClassConstants.ACC_ABSTRACT) != 0)
+ {
+ // Keep the target method.
+ if (DEBUG)
+ {
+ System.out.println("MemberAdder: skipping abstract method ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
+ }
+
+ // Don't add a new method.
+ return;
+ }
+
+ // Is the target method abstract?
+ int targetAccessFlags = targetMethod.getAccessFlags();
+ if ((targetAccessFlags & ClassConstants.ACC_ABSTRACT) != 0)
+ {
+ // Keep the abstract method, but update its contents, in order
+ // to keep any references to it valid.
+ if (DEBUG)
+ {
+ System.out.println("MemberAdder: updating method ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
+ }
+
+ // Replace the access flags.
+ targetMethod.u2accessFlags =
+ accessFlags & ~ClassConstants.ACC_FINAL;
+
+ // Add and replace the attributes.
+ programMethod.attributesAccept(programClass,
+ new AttributeAdder(targetClass,
+ targetMethod,
+ true));
+
+ // Don't add a new method.
+ return;
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("MemberAdder: renaming method ["+targetClass.getName()+"."+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]");
+ }
+
+ // TODO: Handle non-abstract method with the same name and descriptor in the target class.
+ // We currently avoid this case, since renaming the identical method
+ // still causes confused method references.
+ //// Rename the private (non-abstract) or static method.
+ //targetMethod.u2nameIndex =
+ // constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, descriptor));
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("MemberAdder: copying method ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
+ }
+
+ // Create a copy of the method.
+ ProgramMethod newProgramMethod =
+ new ProgramMethod(accessFlags & ~ClassConstants.ACC_FINAL,
+ constantAdder.addConstant(programClass, programMethod.u2nameIndex),
+ constantAdder.addConstant(programClass, programMethod.u2descriptorIndex),
+ 0,
+ programMethod.u2attributesCount > 0 ?
+ new Attribute[programMethod.u2attributesCount] :
+ EMPTY_ATTRIBUTES,
+ programMethod.referencedClasses != null ?
+ (Clazz[])programMethod.referencedClasses.clone() :
+ null);
+
+ // Link to its visitor info.
+ newProgramMethod.setVisitorInfo(programMethod);
+
+ // Copy its attributes.
+ programMethod.attributesAccept(programClass,
+ new AttributeAdder(targetClass,
+ newProgramMethod,
+ false));
+
+ // Add the completed method.
+ classEditor.addMethod(newProgramMethod);
+
+ // Visit the newly added method, if necessary.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramMethod(targetClass, newProgramMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns a unique class member name, based on the given name and descriptor.
+ */
+ private String newUniqueMemberName(String name, String descriptor)
+ {
+ return name.equals(ClassConstants.METHOD_NAME_INIT) ?
+ ClassConstants.METHOD_NAME_INIT :
+ name + ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode()));
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MemberReferenceFixer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MemberReferenceFixer.java
new file mode 100644
index 0000000000..107205c572
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MemberReferenceFixer.java
@@ -0,0 +1,447 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor fixes constant pool field and method references to fields
+ * and methods whose names or descriptors have changed.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberReferenceFixer
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor,
+ MemberVisitor,
+ AttributeVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ private final StackSizeUpdater stackSizeUpdater = new StackSizeUpdater();
+
+ // Parameter for the visitor methods.
+ private int constantIndex;
+
+ // Return values for the visitor methods.
+ private boolean isInterfaceMethod;
+ private boolean stackSizesMayHaveChanged;
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ stackSizesMayHaveChanged = false;
+
+ // Fix the constant pool entries.
+ for (int index = 1; index < programClass.u2constantPoolCount; index++)
+ {
+ Constant constant = programClass.constantPool[index];
+ if (constant != null)
+ {
+ // Fix the entry, replacing it entirely if needed.
+ this.constantIndex = index;
+
+ constant.accept(programClass, this);
+ }
+ }
+
+ // Fix the class members.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ // Fix the attributes.
+ programClass.attributesAccept(this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Does the string refer to a class member, due to a
+ // Class.get[Declared]{Field,Method} construct?
+ Member referencedMember = stringConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ Clazz referencedClass = stringConstant.referencedClass;
+
+ // Does it have a new name?
+ String newName = referencedMember.getName(referencedClass);
+
+ if (!stringConstant.getString(clazz).equals(newName))
+ {
+ if (DEBUG)
+ {
+ debug(clazz, stringConstant, referencedClass, referencedMember);
+ }
+
+ // Update the name.
+ stringConstant.u2stringIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newName);
+ }
+ }
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ // Do we know the referenced field?
+ Member referencedMember = fieldrefConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ Clazz referencedClass = fieldrefConstant.referencedClass;
+
+ // Does it have a new name or type?
+ String newName = referencedMember.getName(referencedClass);
+ String newType = referencedMember.getDescriptor(referencedClass);
+
+ if (!fieldrefConstant.getName(clazz).equals(newName) ||
+ !fieldrefConstant.getType(clazz).equals(newType))
+ {
+ if (DEBUG)
+ {
+ debug(clazz, fieldrefConstant, referencedClass, referencedMember);
+ }
+
+ // Update the name and type index.
+ fieldrefConstant.u2nameAndTypeIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(newName, newType);
+ }
+ }
+ }
+
+
+ public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
+ {
+ // Do we know the referenced interface method?
+ Member referencedMember = interfaceMethodrefConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ Clazz referencedClass = interfaceMethodrefConstant.referencedClass;
+
+ // Does it have a new name or type?
+ String newName = referencedMember.getName(referencedClass);
+ String newType = referencedMember.getDescriptor(referencedClass);
+
+ if (!interfaceMethodrefConstant.getName(clazz).equals(newName) ||
+ !interfaceMethodrefConstant.getType(clazz).equals(newType))
+ {
+ if (DEBUG)
+ {
+ debug(clazz, interfaceMethodrefConstant, referencedClass, referencedMember);
+ }
+
+ // Update the name and type index.
+ interfaceMethodrefConstant.u2nameAndTypeIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(newName, newType);
+
+ // Remember that the stack sizes of the methods in this class
+ // may have changed.
+ stackSizesMayHaveChanged = true;
+ }
+
+ // Check if this is an interface method.
+ isInterfaceMethod = true;
+ clazz.constantPoolEntryAccept(interfaceMethodrefConstant.u2classIndex, this);
+
+ // Has the method become a non-interface method?
+ if (!isInterfaceMethod)
+ {
+ if (DEBUG)
+ {
+ System.out.println("MemberReferenceFixer:");
+ System.out.println(" Class file = "+clazz.getName());
+ System.out.println(" Ref class = "+referencedClass.getName());
+ System.out.println(" Ref method = "+interfaceMethodrefConstant.getName(clazz)+interfaceMethodrefConstant.getType(clazz));
+ System.out.println(" -> ordinary method");
+ }
+
+ // Replace the interface method reference by a method reference.
+ ((ProgramClass)clazz).constantPool[this.constantIndex] =
+ new MethodrefConstant(interfaceMethodrefConstant.u2classIndex,
+ interfaceMethodrefConstant.u2nameAndTypeIndex,
+ referencedClass,
+ referencedMember);
+ }
+ }
+ }
+
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ // Do we know the referenced method?
+ Member referencedMember = methodrefConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ Clazz referencedClass = methodrefConstant.referencedClass;
+
+ // Does it have a new name or type?
+ String newName = referencedMember.getName(referencedClass);
+ String newType = referencedMember.getDescriptor(referencedClass);
+
+ if (!methodrefConstant.getName(clazz).equals(newName) ||
+ !methodrefConstant.getType(clazz).equals(newType))
+ {
+ if (DEBUG)
+ {
+ debug(clazz, methodrefConstant, referencedClass, referencedMember);
+ }
+
+ // Update the name and type index.
+ methodrefConstant.u2nameAndTypeIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(newName, newType);
+
+ // Remember that the stack sizes of the methods in this class
+ // may have changed.
+ stackSizesMayHaveChanged = true;
+ }
+
+ // Check if this is an interface method.
+ isInterfaceMethod = false;
+ clazz.constantPoolEntryAccept(methodrefConstant.u2classIndex, this);
+
+ // Has the method become an interface method?
+ if (isInterfaceMethod)
+ {
+ if (DEBUG)
+ {
+ System.out.println("MemberReferenceFixer:");
+ System.out.println(" Class file = "+clazz.getName());
+ System.out.println(" Ref class = "+referencedClass.getName());
+ System.out.println(" Ref method = "+methodrefConstant.getName(clazz)+methodrefConstant.getType(clazz));
+ System.out.println(" -> interface method");
+ }
+
+ // Replace the method reference by an interface method reference.
+ ((ProgramClass)clazz).constantPool[this.constantIndex] =
+ new InterfaceMethodrefConstant(methodrefConstant.u2classIndex,
+ methodrefConstant.u2nameAndTypeIndex,
+ referencedClass,
+ referencedMember);
+ }
+ }
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Check if this class entry is an array type.
+ if (ClassUtil.isInternalArrayType(classConstant.getName(clazz)))
+ {
+ isInterfaceMethod = false;
+ }
+ else
+ {
+ // Check if this class entry refers to an interface class.
+ Clazz referencedClass = classConstant.referencedClass;
+ if (referencedClass != null)
+ {
+ isInterfaceMethod = (referencedClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) != 0;
+ }
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ // Fix the attributes.
+ programMember.attributesAccept(programClass, this);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ Member referencedMember = enclosingMethodAttribute.referencedMethod;
+ if (referencedMember != null)
+ {
+ Clazz referencedClass = enclosingMethodAttribute.referencedClass;
+
+ // Does it have a new name or type?
+ String newName = referencedMember.getName(referencedClass);
+ String newType = referencedMember.getDescriptor(referencedClass);
+
+ if (!enclosingMethodAttribute.getName(clazz).equals(newName) ||
+ !enclosingMethodAttribute.getType(clazz).equals(newType))
+ {
+ // Update the name and type index.
+ enclosingMethodAttribute.u2nameAndTypeIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(newName,
+ newType);
+ }
+ }
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Recompute the maximum stack size if necessary.
+ if (stackSizesMayHaveChanged)
+ {
+ stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+ // Fix the nested attributes.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ // Fix the annotations.
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Fix the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Fix the annotation.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ // Fix the element values.
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ fixElementValue(clazz, annotation, constantElementValue);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ fixElementValue(clazz, annotation, enumConstantElementValue);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ fixElementValue(clazz, annotation, classElementValue);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ fixElementValue(clazz, annotation, annotationElementValue);
+
+ // Fix the annotation.
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ fixElementValue(clazz, annotation, arrayElementValue);
+
+ // Fix the element values.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Fixes the method reference of the element value, if any.
+ */
+ private void fixElementValue(Clazz clazz,
+ Annotation annotation,
+ ElementValue elementValue)
+ {
+ // Do we know the referenced method?
+ Member referencedMember = elementValue.referencedMethod;
+ if (referencedMember != null)
+ {
+ // Does it have a new name or type?
+ String methodName = elementValue.getMethodName(clazz);
+ String newMethodName = referencedMember.getName(elementValue.referencedClass);
+
+ if (!methodName.equals(newMethodName))
+ {
+ // Update the element name index.
+ elementValue.u2elementNameIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newMethodName);
+ }
+ }
+ }
+
+
+ private void debug(Clazz clazz,
+ StringConstant stringConstant,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ System.out.println("MemberReferenceFixer:");
+ System.out.println(" ["+clazz.getName()+"]: String ["+
+ stringConstant.getString(clazz)+"] -> ["+
+ referencedClass.getName()+"."+referencedMember.getName(referencedClass)+" "+referencedMember.getDescriptor(referencedClass)+"]");
+ }
+
+
+ private void debug(Clazz clazz,
+ RefConstant refConstant,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ System.out.println("MemberReferenceFixer:");
+ System.out.println(" ["+clazz.getName()+"]: ["+
+ refConstant.getClassName(clazz)+"."+refConstant.getName(clazz)+" "+refConstant.getType(clazz)+"] -> ["+
+ referencedClass.getName()+"."+referencedMember.getName(referencedClass)+" "+referencedMember.getDescriptor(referencedClass)+"]");
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MethodInvocationFixer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MethodInvocationFixer.java
new file mode 100644
index 0000000000..29fb9441c9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/MethodInvocationFixer.java
@@ -0,0 +1,242 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+
+/**
+ * This AttributeVisitor fixes all inappropriate special/virtual/static/interface
+ * invocations of the code attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodInvocationFixer
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ConstantVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
+
+ // Return values for the visitor methods.
+ private Clazz referencedClass;
+ private Clazz referencedMethodClass;
+ private Member referencedMethod;
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Reset the code attribute editor.
+ codeAttributeEditor.reset(codeAttribute.u4codeLength);
+
+ // Remap the variables of the instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
+
+ // Apply the code atribute editor.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ int constantIndex = constantInstruction.constantIndex;
+
+ // Get information on the called class and method, if present.
+ referencedMethod = null;
+
+ clazz.constantPoolEntryAccept(constantIndex, this);
+
+ // Did we find the called class and method?
+ if (referencedClass != null &&
+ referencedMethod != null)
+ {
+ // Do we need to update the opcode?
+ byte opcode = constantInstruction.opcode;
+
+ // Is the method static?
+ if ((referencedMethod.getAccessFlags() & ClassConstants.ACC_STATIC) != 0)
+ {
+ // But is it not a static invocation?
+ if (opcode != InstructionConstants.OP_INVOKESTATIC)
+ {
+ // Replace the invocation by an invokestatic instruction.
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC,
+ constantIndex);
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
+
+ if (DEBUG)
+ {
+ debug(clazz, method, offset, constantInstruction, replacementInstruction);
+ }
+ }
+ }
+
+ // Is the method private, or an instance initializer?
+ else if ((referencedMethod.getAccessFlags() & ClassConstants.ACC_PRIVATE) != 0 ||
+ referencedMethod.getName(referencedMethodClass).equals(ClassConstants.METHOD_NAME_INIT))
+ {
+ // But is it not a special invocation?
+ if (opcode != InstructionConstants.OP_INVOKESPECIAL)
+ {
+ // Replace the invocation by an invokespecial instruction.
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL,
+ constantIndex);
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
+
+ if (DEBUG)
+ {
+ debug(clazz, method, offset, constantInstruction, replacementInstruction);
+ }
+ }
+ }
+
+ // Is the method an interface method?
+ else if ((referencedClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) != 0)
+ {
+ int invokeinterfaceConstant =
+ (ClassUtil.internalMethodParameterSize(referencedMethod.getDescriptor(referencedMethodClass), false)) << 8;
+
+ if (opcode == InstructionConstants.OP_INVOKESPECIAL &&
+ (referencedMethod.getAccessFlags() & ClassConstants.ACC_ABSTRACT) == 0)
+ {
+ // Explicit calls to default interface methods *must* be preserved.
+ }
+ // But is it not an interface invocation, or is the parameter
+ // size incorrect?
+ else if (opcode != InstructionConstants.OP_INVOKEINTERFACE ||
+ constantInstruction.constant != invokeinterfaceConstant)
+ {
+ // Fix the parameter size of the interface invocation.
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_INVOKEINTERFACE,
+ constantIndex,
+ invokeinterfaceConstant);
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
+
+ if (DEBUG)
+ {
+ debug(clazz, method, offset, constantInstruction, replacementInstruction);
+ }
+ }
+ }
+
+ // The method is not static, private, an instance initializer, or
+ // an interface method.
+ else
+ {
+ // But is it not a virtual invocation?
+ if (opcode != InstructionConstants.OP_INVOKEVIRTUAL &&
+ (// Replace any non-invokespecial.
+ opcode != InstructionConstants.OP_INVOKESPECIAL ||
+ // For invokespecial, replace invocations from the same
+ // class, and invocations to non-superclasses.
+ clazz.equals(referencedClass) ||
+ !clazz.extends_(referencedClass)))
+ {
+ // Replace the invocation by an invokevirtual instruction.
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL,
+ constantIndex);
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
+
+ if (DEBUG)
+ {
+ debug(clazz, method, offset, constantInstruction, replacementInstruction);
+ }
+ }
+ }
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Remember the referenced class. Note that we're interested in the
+ // class of the method reference, not in the class in which the
+ // method was actually found, unless it is an array type.
+ if (ClassUtil.isInternalArrayType(refConstant.getClassName(clazz)))
+ {
+ // For an array type, the class will be java.lang.Object.
+ referencedClass = refConstant.referencedClass;
+ }
+ else
+ {
+ clazz.constantPoolEntryAccept(refConstant.u2classIndex, this);
+ }
+
+ // Remember the referenced method.
+ referencedMethodClass = refConstant.referencedClass;
+ referencedMethod = refConstant.referencedMember;
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Remember the referenced class.
+ referencedClass = classConstant.referencedClass;
+ }
+
+
+ // Small utility methods.
+
+ private void debug(Clazz clazz,
+ Method method,
+ int offset,
+ ConstantInstruction constantInstruction,
+ Instruction replacementInstruction)
+ {
+ System.out.println("MethodInvocationFixer ["+clazz.getName()+"."+
+ method.getName(clazz)+method.getDescriptor(clazz)+"] "+
+ constantInstruction.toString(offset)+" -> "+
+ replacementInstruction.toString(offset));
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/NameAndTypeShrinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/NameAndTypeShrinker.java
new file mode 100644
index 0000000000..6a21e0770c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/NameAndTypeShrinker.java
@@ -0,0 +1,195 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.util.Arrays;
+
+
+/**
+ * This ClassVisitor removes NameAndType constant pool entries that are not
+ * used.
+ *
+ * @author Eric Lafortune
+ */
+public class NameAndTypeShrinker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor,
+ AttributeVisitor
+{
+ // A visitor info flag to indicate the NameAndType constant pool entry is being used.
+ private static final Object USED = new Object();
+
+ private int[] constantIndexMap;
+ private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Mark the NameAndType entries referenced by all other constant pool
+ // entries.
+ programClass.constantPoolEntriesAccept(this);
+
+ // Mark the NameAndType entries referenced by all EnclosingMethod
+ // attributes.
+ programClass.attributesAccept(this);
+
+ // Shift the used constant pool entries together, filling out the
+ // index map.
+ int newConstantPoolCount =
+ shrinkConstantPool(programClass.constantPool,
+ programClass.u2constantPoolCount);
+
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
+
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ markNameAndTypeConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ markNameAndTypeConstant(clazz, refConstant.u2nameAndTypeIndex);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
+ {
+ markNameAndTypeConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given UTF-8 constant pool entry of the given class.
+ */
+ private void markNameAndTypeConstant(Clazz clazz, int index)
+ {
+ markAsUsed((NameAndTypeConstant)((ProgramClass)clazz).getConstant(index));
+ }
+
+
+ /**
+ * Marks the given VisitorAccepter as being used.
+ * In this context, the VisitorAccepter will be a NameAndTypeConstant object.
+ */
+ private void markAsUsed(VisitorAccepter visitorAccepter)
+ {
+ visitorAccepter.setVisitorInfo(USED);
+ }
+
+
+ /**
+ * Returns whether the given VisitorAccepter has been marked as being used.
+ * In this context, the VisitorAccepter will be a NameAndTypeConstant object.
+ */
+ private boolean isUsed(VisitorAccepter visitorAccepter)
+ {
+ return visitorAccepter.getVisitorInfo() == USED;
+ }
+
+
+ /**
+ * Removes all NameAndType entries that are not marked as being used
+ * from the given constant pool.
+ * @return the new number of entries.
+ */
+ private int shrinkConstantPool(Constant[] constantPool, int length)
+ {
+ // Create a new index map, if necessary.
+ if (constantIndexMap == null ||
+ constantIndexMap.length < length)
+ {
+ constantIndexMap = new int[length];
+ }
+
+ int counter = 1;
+ boolean isUsed = false;
+
+ // Shift the used constant pool entries together.
+ for (int index = 1; index < length; index++)
+ {
+ Constant constant = constantPool[index];
+
+ // Is the constant being used? Don't update the flag if this is the
+ // second half of a long entry.
+ if (constant != null)
+ {
+ isUsed = constant.getTag() != ClassConstants.CONSTANT_NameAndType ||
+ isUsed(constant);
+ }
+
+ if (isUsed)
+ {
+ // Remember the new index.
+ constantIndexMap[index] = counter;
+
+ // Shift the constant pool entry.
+ constantPool[counter++] = constant;
+ }
+ else
+ {
+ // Remember an invalid index.
+ constantIndexMap[index] = -1;
+ }
+ }
+
+ // Clear the remaining constant pool elements.
+ Arrays.fill(constantPool, counter, length, null);
+
+ return counter;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/NamedAttributeDeleter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/NamedAttributeDeleter.java
new file mode 100644
index 0000000000..90b617201e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/NamedAttributeDeleter.java
@@ -0,0 +1,82 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+
+/**
+ * This ClassVisitor deletes attributes with a given name in the program
+ * classes, fields, methods, or code attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class NamedAttributeDeleter
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor
+{
+ private final String attributeName;
+
+
+ public NamedAttributeDeleter(String attributeName)
+ {
+ this.attributeName = attributeName;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ new AttributesEditor(programClass, false).deleteAttribute(attributeName);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) {}
+
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ new AttributesEditor(programClass, programMember, false).deleteAttribute(attributeName);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ new AttributesEditor((ProgramClass)clazz, (ProgramMember)method, codeAttribute, false).deleteAttribute(attributeName);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java
new file mode 100644
index 0000000000..6dabf96e82
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java
@@ -0,0 +1,56 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.attribute.annotation.*;
+import proguard.util.ArrayUtil;
+
+/**
+ * This class can add annotations to a given parameter annotations attribute.
+ * Annotations to be added must have been filled out beforehand.
+ *
+ * @author Eric Lafortune
+ */
+public class ParameterAnnotationsAttributeEditor
+{
+ private ParameterAnnotationsAttribute targetParameterAnnotationsAttribute;
+
+
+ /**
+ * Creates a new ParameterAnnotationsAttributeEditor that will edit
+ * annotations in the given parameter annotations attribute.
+ */
+ public ParameterAnnotationsAttributeEditor(ParameterAnnotationsAttribute targetParameterAnnotationsAttribute)
+ {
+ this.targetParameterAnnotationsAttribute = targetParameterAnnotationsAttribute;
+ }
+
+
+ /**
+ * Adds a given annotation to the annotations attribute.
+ */
+ public void addAnnotation(int parameterIndex, Annotation annotation)
+ {
+ ArrayUtil.add(targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex],
+ targetParameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]++,
+ annotation);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ParameterInfoAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ParameterInfoAdder.java
new file mode 100644
index 0000000000..dd729239ef
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/ParameterInfoAdder.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.ParameterInfoVisitor;
+
+/**
+ * This ParameterInfoVisitor adds all parameter information that it visits to
+ * the given target method parameters attribute.
+ */
+public class ParameterInfoAdder
+implements ParameterInfoVisitor
+{
+ private final ConstantAdder constantAdder;
+ private final MethodParametersAttribute targetMethodParametersAttribute;
+
+
+ /**
+ * Creates a new ParameterInfoAdder that will copy parameter information
+ * into the given target method parameters attribute.
+ */
+ public ParameterInfoAdder(ProgramClass targetClass,
+ MethodParametersAttribute targetMethodParametersAttribute)
+ {
+ this.constantAdder = new ConstantAdder(targetClass);
+ this.targetMethodParametersAttribute = targetMethodParametersAttribute;
+ }
+
+
+ // Implementations for ParameterInfoVisitor.
+
+ public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
+ {
+ // Create a new parameter.
+ ParameterInfo newParameterInfo =
+ new ParameterInfo(constantAdder.addConstant(clazz, parameterInfo.u2nameIndex),
+ parameterInfo.u2accessFlags);
+
+ // Add it to the target.
+ targetMethodParametersAttribute.parameters[parameterIndex] = newParameterInfo;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/StackSizeUpdater.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/StackSizeUpdater.java
new file mode 100644
index 0000000000..625c533236
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/StackSizeUpdater.java
@@ -0,0 +1,54 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor computes and updates the maximum stack size of the
+ * code attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class StackSizeUpdater
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final StackSizeComputer stackSizeComputer = new StackSizeComputer();
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Compute the stack sizes.
+ stackSizeComputer.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Update the maximum stack size.
+ codeAttribute.u2maxStack = stackSizeComputer.getMaxStackSize();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/SubclassAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/SubclassAdder.java
new file mode 100644
index 0000000000..e1de014ba3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/SubclassAdder.java
@@ -0,0 +1,59 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor adds the given class to the list of subclasses of the
+ * classes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class SubclassAdder
+implements ClassVisitor
+{
+ private final Clazz subclass;
+
+
+ /**
+ * Creates a new SubclassAdder that will add the given subclass.
+ */
+ public SubclassAdder(Clazz subclass)
+ {
+ this.subclass = subclass;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.addSubClass(subclass);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ libraryClass.addSubClass(subclass);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/SubclassToAdder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/SubclassToAdder.java
new file mode 100644
index 0000000000..0fa599e2ee
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/SubclassToAdder.java
@@ -0,0 +1,60 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor adds all classes that it visits to the list of subclasses
+ * of the given target class.
+ *
+ * @author Eric Lafortune
+ */
+public class SubclassToAdder
+implements ClassVisitor
+{
+ private final Clazz targetClass;
+
+
+ /**
+ * Creates a new SubclassAdder that will add subclasses to the given
+ * target class.
+ */
+ public SubclassToAdder(Clazz targetClass)
+ {
+ this.targetClass = targetClass;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ targetClass.addSubClass(programClass);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ targetClass.addSubClass(libraryClass);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/Utf8Shrinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/Utf8Shrinker.java
new file mode 100644
index 0000000000..1f563d5d2e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/Utf8Shrinker.java
@@ -0,0 +1,483 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+import java.util.Arrays;
+
+
+/**
+ * This ClassVisitor removes UTF-8 constant pool entries that are not used.
+ *
+ * @author Eric Lafortune
+ */
+public class Utf8Shrinker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ ConstantVisitor,
+ AttributeVisitor,
+ InnerClassesInfoVisitor,
+ ParameterInfoVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor
+{
+ // A visitor info flag to indicate the UTF-8 constant pool entry is being used.
+ private static final Object USED = new Object();
+
+ private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
+ private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Mark the UTF-8 entries referenced by the other constant pool entries.
+ programClass.constantPoolEntriesAccept(this);
+
+ // Mark the UTF-8 entries referenced by the fields and methods.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ // Mark the UTF-8 entries referenced by the attributes.
+ programClass.attributesAccept(this);
+
+ // Shift the used constant pool entries together, filling out the
+ // index map.
+ int newConstantPoolCount =
+ shrinkConstantPool(programClass.constantPool,
+ programClass.u2constantPoolCount);
+
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
+
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ // Mark the name and descriptor UTF-8 entries.
+ markCpUtf8Entry(programClass, programMember.u2nameIndex);
+ markCpUtf8Entry(programClass, programMember.u2descriptorIndex);
+
+ // Mark the UTF-8 entries referenced by the attributes.
+ programMember.attributesAccept(programClass, this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ markCpUtf8Entry(clazz, stringConstant.u2stringIndex);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ markCpUtf8Entry(clazz, classConstant.u2nameIndex);
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ markCpUtf8Entry(clazz, nameAndTypeConstant.u2nameIndex);
+ markCpUtf8Entry(clazz, nameAndTypeConstant.u2descriptorIndex);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ // This is the best we can do for unknown attributes.
+ markCpUtf8Entry(clazz, unknownAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ markCpUtf8Entry(clazz, sourceFileAttribute.u2attributeNameIndex);
+
+ markCpUtf8Entry(clazz, sourceFileAttribute.u2sourceFileIndex);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ markCpUtf8Entry(clazz, sourceDirAttribute.u2attributeNameIndex);
+
+ markCpUtf8Entry(clazz, sourceDirAttribute.u2sourceDirIndex);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ markCpUtf8Entry(clazz, innerClassesAttribute.u2attributeNameIndex);
+
+ // Mark the UTF-8 entries referenced by the inner classes.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ markCpUtf8Entry(clazz, enclosingMethodAttribute.u2attributeNameIndex);
+
+ // These entries have already been marked in the constant pool.
+ //clazz.constantPoolEntryAccept(this, enclosingMethodAttribute.u2classIndex);
+ //clazz.constantPoolEntryAccept(this, enclosingMethodAttribute.u2nameAndTypeIndex);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ markCpUtf8Entry(clazz, deprecatedAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ markCpUtf8Entry(clazz, syntheticAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ markCpUtf8Entry(clazz, signatureAttribute.u2attributeNameIndex);
+
+ markCpUtf8Entry(clazz, signatureAttribute.u2signatureIndex);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ markCpUtf8Entry(clazz, constantValueAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ markCpUtf8Entry(clazz, methodParametersAttribute.u2attributeNameIndex);
+
+ // Mark the UTF-8 entries referenced by the parameter information.
+ methodParametersAttribute.parametersAccept(clazz, method, this);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ markCpUtf8Entry(clazz, exceptionsAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ markCpUtf8Entry(clazz, codeAttribute.u2attributeNameIndex);
+
+ // Mark the UTF-8 entries referenced by the attributes.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ markCpUtf8Entry(clazz, stackMapAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ markCpUtf8Entry(clazz, stackMapTableAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ markCpUtf8Entry(clazz, lineNumberTableAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ markCpUtf8Entry(clazz, localVariableTableAttribute.u2attributeNameIndex);
+
+ // Mark the UTF-8 entries referenced by the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ markCpUtf8Entry(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
+
+ // Mark the UTF-8 entries referenced by the local variable types.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ markCpUtf8Entry(clazz, annotationsAttribute.u2attributeNameIndex);
+
+ // Mark the UTF-8 entries referenced by the annotations.
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ markCpUtf8Entry(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
+
+ // Mark the UTF-8 entries referenced by the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ markCpUtf8Entry(clazz, annotationDefaultAttribute.u2attributeNameIndex);
+
+ // Mark the UTF-8 entries referenced by the element value.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ if (innerClassesInfo.u2innerNameIndex != 0)
+ {
+ markCpUtf8Entry(clazz, innerClassesInfo.u2innerNameIndex);
+ }
+ }
+
+
+ // Implementations for ParameterInfoVisitor.
+
+ public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
+ {
+ if (parameterInfo.u2nameIndex != 0)
+ {
+ markCpUtf8Entry(clazz, parameterInfo.u2nameIndex);
+ }
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ markCpUtf8Entry(clazz, localVariableInfo.u2nameIndex);
+ markCpUtf8Entry(clazz, localVariableInfo.u2descriptorIndex);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ markCpUtf8Entry(clazz, localVariableTypeInfo.u2nameIndex);
+ markCpUtf8Entry(clazz, localVariableTypeInfo.u2signatureIndex);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ markCpUtf8Entry(clazz, annotation.u2typeIndex);
+
+ // Mark the UTF-8 entries referenced by the element values.
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ if (constantElementValue.u2elementNameIndex != 0)
+ {
+ markCpUtf8Entry(clazz, constantElementValue.u2elementNameIndex);
+ }
+
+ // Only the string constant element value refers to a UTF-8 entry.
+ if (constantElementValue.u1tag == ClassConstants.ELEMENT_VALUE_STRING_CONSTANT)
+ {
+ markCpUtf8Entry(clazz, constantElementValue.u2constantValueIndex);
+ }
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ if (enumConstantElementValue.u2elementNameIndex != 0)
+ {
+ markCpUtf8Entry(clazz, enumConstantElementValue.u2elementNameIndex);
+ }
+
+ markCpUtf8Entry(clazz, enumConstantElementValue.u2typeNameIndex);
+ markCpUtf8Entry(clazz, enumConstantElementValue.u2constantNameIndex);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ if (classElementValue.u2elementNameIndex != 0)
+ {
+ markCpUtf8Entry(clazz, classElementValue.u2elementNameIndex);
+ }
+
+ markCpUtf8Entry(clazz, classElementValue.u2classInfoIndex);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ if (annotationElementValue.u2elementNameIndex != 0)
+ {
+ markCpUtf8Entry(clazz, annotationElementValue.u2elementNameIndex);
+ }
+
+ // Mark the UTF-8 entries referenced by the annotation.
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ if (arrayElementValue.u2elementNameIndex != 0)
+ {
+ markCpUtf8Entry(clazz, arrayElementValue.u2elementNameIndex);
+ }
+
+ // Mark the UTF-8 entries referenced by the element values.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given UTF-8 constant pool entry of the given class.
+ */
+ private void markCpUtf8Entry(Clazz clazz, int index)
+ {
+ markAsUsed((Utf8Constant)((ProgramClass)clazz).getConstant(index));
+ }
+
+
+ /**
+ * Marks the given VisitorAccepter as being used.
+ * In this context, the VisitorAccepter will be a Utf8Constant object.
+ */
+ private void markAsUsed(VisitorAccepter visitorAccepter)
+ {
+ visitorAccepter.setVisitorInfo(USED);
+ }
+
+
+ /**
+ * Returns whether the given VisitorAccepter has been marked as being used.
+ * In this context, the VisitorAccepter will be a Utf8Constant object.
+ */
+ private boolean isUsed(VisitorAccepter visitorAccepter)
+ {
+ return visitorAccepter.getVisitorInfo() == USED;
+ }
+
+
+ /**
+ * Removes all UTF-8 entries that are not marked as being used
+ * from the given constant pool.
+ * @return the new number of entries.
+ */
+ private int shrinkConstantPool(Constant[] constantPool, int length)
+ {
+ // Create a new index map, if necessary.
+ if (constantIndexMap.length < length)
+ {
+ constantIndexMap = new int[length];
+ }
+
+ int counter = 1;
+ boolean isUsed = false;
+
+ // Shift the used constant pool entries together.
+ for (int index = 1; index < length; index++)
+ {
+ Constant constant = constantPool[index];
+
+ // Is the constant being used? Don't update the flag if this is the
+ // second half of a long entry.
+ if (constant != null)
+ {
+ isUsed = constant.getTag() != ClassConstants.CONSTANT_Utf8 ||
+ isUsed(constant);
+ }
+
+ if (isUsed)
+ {
+ // Remember the new index.
+ constantIndexMap[index] = counter;
+
+ // Shift the constant pool entry.
+ constantPool[counter++] = constant;
+ }
+ else
+ {
+ // Remember an invalid index.
+ constantIndexMap[index] = -1;
+ }
+ }
+
+ // Clear the remaining constant pool elements.
+ Arrays.fill(constantPool, counter, length, null);
+
+ return counter;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableCleaner.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableCleaner.java
new file mode 100644
index 0000000000..991beb5cf8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableCleaner.java
@@ -0,0 +1,271 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor cleans up variable tables in all code attributes that
+ * it visits. It trims overlapping local variables. It removes empty local
+ * variables and empty local variable tables.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableCleaner
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private boolean deleteLocalVariableTableAttribute;
+ private boolean deleteLocalVariableTypeTableAttribute;
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ deleteLocalVariableTableAttribute = false;
+ deleteLocalVariableTypeTableAttribute = false;
+
+ // Trim the local variable table and the local variable type table.
+ codeAttribute.attributesAccept(clazz, method, this);
+
+ // Delete the local variable table if it ended up empty.
+ if (deleteLocalVariableTableAttribute)
+ {
+ AttributesEditor editor =
+ new AttributesEditor((ProgramClass)clazz,
+ (ProgramMember)method,
+ codeAttribute,
+ true);
+
+ editor.deleteAttribute(ClassConstants.ATTR_LocalVariableTable);
+ }
+
+ // Delete the local variable type table if it ended up empty.
+ if (deleteLocalVariableTypeTableAttribute)
+ {
+ AttributesEditor editor =
+ new AttributesEditor((ProgramClass)clazz,
+ (ProgramMember)method,
+ codeAttribute,
+ true);
+
+ editor.deleteAttribute(ClassConstants.ATTR_LocalVariableTypeTable);
+ }
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Clean up local variables that aren't used.
+ localVariableTableAttribute.u2localVariableTableLength =
+ removeUnusedLocalVariables(localVariableTableAttribute.localVariableTable,
+ localVariableTableAttribute.u2localVariableTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Trim the code blocks of the local variables.
+ trimLocalVariables(localVariableTableAttribute.localVariableTable,
+ localVariableTableAttribute.u2localVariableTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Delete the attribute in a moment, if it is empty.
+ if (localVariableTableAttribute.u2localVariableTableLength == 0)
+ {
+ deleteLocalVariableTableAttribute = true;
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Clean up local variables that aren't used.
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength =
+ removeUnusedLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Trim the code blocks of the local variables.
+ trimLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength,
+ codeAttribute.u2maxLocals);
+
+ // Delete the attribute in a moment, if it is empty.
+ if (localVariableTypeTableAttribute.u2localVariableTypeTableLength == 0)
+ {
+ deleteLocalVariableTypeTableAttribute = true;
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the given list of local variables, without the ones that aren't
+ * used.
+ */
+ private int removeUnusedLocalVariables(LocalVariableInfo[] localVariableInfos,
+ int localVariableInfoCount,
+ int maxLocals)
+ {
+ // Overwrite all empty local variable entries.
+ // Do keep parameter entries.
+ int newIndex = 0;
+ for (int index = 0; index < localVariableInfoCount; index++)
+ {
+ LocalVariableInfo localVariableInfo = localVariableInfos[index];
+
+ if (localVariableInfo.u2index >= 0 &&
+ localVariableInfo.u2index < maxLocals &&
+ (localVariableInfo.u2startPC == 0 ||
+ localVariableInfo.u2length > 0))
+ {
+ localVariableInfos[newIndex++] = localVariableInfos[index];
+ }
+ }
+
+ // Clean up any remaining array elements.
+ Arrays.fill(localVariableInfos, newIndex, localVariableInfoCount, null);
+
+ return newIndex;
+ }
+
+
+ /**
+ * Returns the given list of local variable types, without the ones that
+ * aren't used.
+ */
+ private int removeUnusedLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
+ int localVariableTypeInfoCount,
+ int maxLocals)
+ {
+ // Overwrite all empty local variable type entries.
+ // Do keep parameter entries.
+ int newIndex = 0;
+ for (int index = 0; index < localVariableTypeInfoCount; index++)
+ {
+ LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
+
+ if (localVariableTypeInfo.u2index >= 0 &&
+ localVariableTypeInfo.u2index < maxLocals &&
+ (localVariableTypeInfo.u2startPC == 0 ||
+ localVariableTypeInfo.u2length > 0))
+ {
+ localVariableTypeInfos[newIndex++] = localVariableTypeInfos[index];
+ }
+ }
+
+ // Clean up any remaining array elements.
+ Arrays.fill(localVariableTypeInfos, newIndex, localVariableTypeInfoCount, null);
+
+ return newIndex;
+ }
+
+
+ /**
+ * Sorts the given list of local variables and trims their code blocks
+ * when necessary. The block is trimmed at the end, which is a bit
+ * arbitrary.
+ */
+ private void trimLocalVariables(LocalVariableInfo[] localVariableInfos,
+ int localVariableInfoCount,
+ int maxLocals)
+ {
+ // Sort the local variable entries.
+ Arrays.sort(localVariableInfos, 0, localVariableInfoCount);
+
+ int[] startPCs = createMaxArray(maxLocals);
+
+ // Trim the local variable entries, starting at the last one.
+ for (int index = localVariableInfoCount-1; index >= 0; index--)
+ {
+ LocalVariableInfo localVariableInfo = localVariableInfos[index];
+
+ // Make sure the variable's code block doesn't overlap with the
+ // next one for the same variable.
+ int maxLength = startPCs[localVariableInfo.u2index] -
+ localVariableInfo.u2startPC;
+
+ if (localVariableInfo.u2length > maxLength)
+ {
+ localVariableInfo.u2length = maxLength;
+ }
+
+ startPCs[localVariableInfo.u2index] = localVariableInfo.u2startPC;
+ }
+ }
+
+
+ /**
+ * Sorts the given list of local variable types and trims their code blocks
+ * when necessary. The block is trimmed at the end, which is a bit
+ * arbitrary.
+ */
+ private void trimLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
+ int localVariableTypeInfoCount,
+ int maxLocals)
+ {
+ // Sort the local variable entries.
+ Arrays.sort(localVariableTypeInfos, 0, localVariableTypeInfoCount);
+
+ int[] startPCs = createMaxArray(maxLocals);
+
+ // Trim the local variable entries, starting at the last one.
+ for (int index = localVariableTypeInfoCount-1; index >= 0; index--)
+ {
+ LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
+
+ // Make sure the variable's code block doesn't overlap with the
+ // next one for the same variable.
+ int maxLength = startPCs[localVariableTypeInfo.u2index] -
+ localVariableTypeInfo.u2startPC;
+
+ if (localVariableTypeInfo.u2length > maxLength)
+ {
+ localVariableTypeInfo.u2length = maxLength;
+ }
+
+ startPCs[localVariableTypeInfo.u2index] = localVariableTypeInfo.u2startPC;
+ }
+ }
+
+
+ /**
+ * Creates an integer array of the given length, initialized with
+ * Integer.MAX_VALUE.
+ */
+ private int[] createMaxArray(int length)
+ {
+ int[] startPCs = new int[length];
+ for (int index = 0; index < length; index++)
+ {
+ startPCs[index] = Integer.MAX_VALUE;
+ }
+ return startPCs;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableEditor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableEditor.java
new file mode 100644
index 0000000000..0126be2ee9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableEditor.java
@@ -0,0 +1,130 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor accumulates specified changes to local variables, and
+ * then applies these accumulated changes to the code attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableEditor
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private boolean modified;
+
+ private boolean[] deleted = new boolean[ClassConstants.TYPICAL_VARIABLES_SIZE];
+ private int[] variableMap = new int[ClassConstants.TYPICAL_VARIABLES_SIZE];
+
+ private final VariableRemapper variableRemapper = new VariableRemapper();
+
+
+ /**
+ * Resets the accumulated code changes.
+ * @param maxLocals the length of the local variable frame that will be
+ * edited next.
+ */
+ public void reset(int maxLocals)
+ {
+ // Try to reuse the previous array.
+ if (deleted.length < maxLocals)
+ {
+ // Create a new array.
+ deleted = new boolean[maxLocals];
+ }
+ else
+ {
+ // Reset the array.
+ Arrays.fill(deleted, 0, maxLocals, false);
+ }
+
+ modified = false;
+ }
+
+
+ /**
+ * Remembers to delete the given variable.
+ * @param variableIndex the index of the variable to be deleted.
+ */
+ public void deleteVariable(int variableIndex)
+ {
+ deleted[variableIndex] = true;
+
+ modified = true;
+ }
+
+
+ /**
+ * Returns whether the given variable at the given offset will be deleted.
+ */
+ public boolean isDeleted(int instructionOffset)
+ {
+ return deleted[instructionOffset];
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Avoid doing any work if nothing is changing anyway.
+ if (!modified)
+ {
+ return;
+ }
+
+ int oldMaxLocals = codeAttribute.u2maxLocals;
+
+ // Make sure there is a sufficiently large variable map.
+ if (variableMap.length < oldMaxLocals)
+ {
+ variableMap = new int[oldMaxLocals];
+ }
+
+ // Fill out the variable map.
+ int newVariableIndex = 0;
+ for (int oldVariableIndex = 0; oldVariableIndex < oldMaxLocals; oldVariableIndex++)
+ {
+ variableMap[oldVariableIndex] = deleted[oldVariableIndex] ?
+ -1 : newVariableIndex++;
+ }
+
+ // Set the map.
+ variableRemapper.setVariableMap(variableMap);
+
+ // Remap the variables.
+ variableRemapper.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Update the length of local variable frame.
+ codeAttribute.u2maxLocals = newVariableIndex;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableRemapper.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableRemapper.java
new file mode 100644
index 0000000000..dd6febdeae
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableRemapper.java
@@ -0,0 +1,218 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.target.*;
+import proguard.classfile.attribute.annotation.target.visitor.*;
+import proguard.classfile.attribute.annotation.visitor.TypeAnnotationVisitor;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor remaps variable indexes in all attributes that it
+ * visits, based on a given index map.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableRemapper
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ TypeAnnotationVisitor,
+ TargetInfoVisitor,
+ LocalVariableTargetElementVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("vr") != null;
+ //*/
+
+
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
+
+ private int[] variableMap;
+
+
+ /**
+ * Sets the given mapping of old variable indexes to their new indexes.
+ * Variables that should disappear can be mapped to -1.
+ */
+ public void setVariableMap(int[] variableMap)
+ {
+ this.variableMap = variableMap;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ // Reorder the array with parameter information.
+ ParameterInfo[] oldParameters = methodParametersAttribute.parameters;
+ ParameterInfo[] newParameters =
+ new ParameterInfo[methodParametersAttribute.u1parametersCount];
+
+ for (int index = 0; index < methodParametersAttribute.u1parametersCount; index++)
+ {
+ newParameters[remapVariable(index)] = oldParameters[index];
+ }
+
+ methodParametersAttribute.parameters = newParameters;
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (DEBUG)
+ {
+ System.out.println("VariableRemapper: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ for (int index= 0; index < codeAttribute.u2maxLocals; index++)
+ {
+ System.out.println(" v"+index+" -> "+variableMap[index]);
+ }
+ }
+
+ // Remap the variables of the attributes, before editing the code and
+ // cleaning up its local variable frame.
+ codeAttribute.attributesAccept(clazz, method, this);
+
+ // Initially, the code attribute editor doesn't contain any changes.
+ codeAttributeEditor.reset(codeAttribute.u4codeLength);
+
+ // Remap the variables of the instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
+
+ // Apply the code atribute editor.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Remap the variable references of the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Remap the variable references of the local variables.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute)
+ {
+ // Remap the variable references of local variable type annotations.
+ typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ localVariableInfo.u2index =
+ remapVariable(localVariableInfo.u2index);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ localVariableTypeInfo.u2index =
+ remapVariable(localVariableTypeInfo.u2index);
+ }
+
+
+ // Implementations for TypeAnnotationVisitor.
+
+ public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)
+ {
+ typeAnnotation.targetInfoAccept(clazz, this);
+ }
+
+
+ // Implementations for TargetInfoVisitor.
+
+ public void visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo) {}
+
+
+ public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)
+ {
+ localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this);
+ }
+
+
+ // Implementations for LocalVariableTargetElementVisitor.
+
+ public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)
+ {
+ localVariableTargetElement.u2index =
+ remapVariable(localVariableTargetElement.u2index);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ // Is the new variable index different from the original one?
+ int oldVariableIndex = variableInstruction.variableIndex;
+ int newVariableIndex = remapVariable(oldVariableIndex);
+ if (newVariableIndex != oldVariableIndex)
+ {
+ // Replace the instruction.
+ Instruction replacementInstruction =
+ new VariableInstruction(variableInstruction.opcode,
+ newVariableIndex,
+ variableInstruction.constant);
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the new variable index of the given variable.
+ */
+ private int remapVariable(int variableIndex)
+ {
+ return variableMap[variableIndex];
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableSizeUpdater.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableSizeUpdater.java
new file mode 100644
index 0000000000..d88077ed94
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/VariableSizeUpdater.java
@@ -0,0 +1,105 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+
+/**
+ * This AttributeVisitor computes and updates the maximum local variable frame
+ * size of the code attributes that it visits. It also cleans up the local
+ * variable tables.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableSizeUpdater
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = true;
+ //*/
+
+
+ private VariableCleaner variableCleaner = new VariableCleaner();
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ // The minimum variable size is determined by the arguments.
+ codeAttribute.u2maxLocals =
+ ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz),
+ method.getAccessFlags());
+
+ if (DEBUG)
+ {
+ System.out.println("VariableSizeUpdater: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ System.out.println(" Max locals: "+codeAttribute.u2maxLocals+" <- parameters");
+ }
+
+ // Go over all instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
+
+ // Remove the unused variables of the attributes.
+ variableCleaner.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ int variableSize = variableInstruction.variableIndex + 1;
+ if (variableInstruction.isCategory2())
+ {
+ variableSize++;
+ }
+
+ if (codeAttribute.u2maxLocals < variableSize)
+ {
+ codeAttribute.u2maxLocals = variableSize;
+
+ if (DEBUG)
+ {
+ System.out.println(" Max locals: "+codeAttribute.u2maxLocals+" <- "+variableInstruction.toString(offset));
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/package.html
new file mode 100644
index 0000000000..d37f541f7c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/editor/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains visitors to edit byte code.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/BranchInstruction.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/BranchInstruction.java
new file mode 100644
index 0000000000..937fe7ebe2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/BranchInstruction.java
@@ -0,0 +1,180 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+
+/**
+ * This interface describes an instruction that branches to a given offset in
+ * the code.
+ *
+ * @author Eric Lafortune
+ */
+public class BranchInstruction extends Instruction
+{
+ public int branchOffset;
+
+
+ /**
+ * Creates an uninitialized BranchInstruction.
+ */
+ public BranchInstruction() {}
+
+
+ public BranchInstruction(byte opcode, int branchOffset)
+ {
+ this.opcode = opcode;
+ this.branchOffset = branchOffset;
+ }
+
+
+ /**
+ * Copies the given instruction into this instruction.
+ * @param branchInstruction the instruction to be copied.
+ * @return this instruction.
+ */
+ public BranchInstruction copy(BranchInstruction branchInstruction)
+ {
+ this.opcode = branchInstruction.opcode;
+ this.branchOffset = branchInstruction.branchOffset;
+
+ return this;
+ }
+
+
+ // Implementations for Instruction.
+
+ public byte canonicalOpcode()
+ {
+ // Remove the _w extension, if any.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_GOTO_W: return InstructionConstants.OP_GOTO;
+
+ case InstructionConstants.OP_JSR_W: return InstructionConstants.OP_JSR;
+
+ default: return opcode;
+ }
+ }
+
+ public Instruction shrink()
+ {
+ // Do we need an ordinary branch or a wide branch?
+ if (requiredBranchOffsetSize() == 2)
+ {
+ // Can we replace the wide branch by an ordinary branch?
+ if (opcode == InstructionConstants.OP_GOTO_W)
+ {
+ opcode = InstructionConstants.OP_GOTO;
+ }
+ else if (opcode == InstructionConstants.OP_JSR_W)
+ {
+ opcode = InstructionConstants.OP_JSR;
+ }
+ }
+ else
+ {
+ // Can we provide a wide branch?
+ if (opcode == InstructionConstants.OP_GOTO ||
+ opcode == InstructionConstants.OP_GOTO_W)
+ {
+ opcode = InstructionConstants.OP_GOTO_W;
+ }
+ else if (opcode == InstructionConstants.OP_JSR)
+ {
+ opcode = InstructionConstants.OP_JSR_W;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Branch instruction can't be widened ("+this.toString()+")");
+ }
+ }
+
+ return this;
+ }
+
+ protected void readInfo(byte[] code, int offset)
+ {
+ branchOffset = readSignedValue(code, offset, branchOffsetSize());
+ }
+
+
+ protected void writeInfo(byte[] code, int offset)
+ {
+ if (requiredBranchOffsetSize() > branchOffsetSize())
+ {
+ throw new IllegalArgumentException("Instruction has invalid branch offset size ("+this.toString(offset)+")");
+ }
+
+ writeSignedValue(code, offset, branchOffset, branchOffsetSize());
+ }
+
+
+ public int length(int offset)
+ {
+ return 1 + branchOffsetSize();
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
+ {
+ instructionVisitor.visitBranchInstruction(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public String toString(int offset)
+ {
+ return "["+offset+"] "+toString()+" (target="+(offset+branchOffset)+")";
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return getName()+" "+(branchOffset >= 0 ? "+" : "")+branchOffset;
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the branch offset size for this instruction.
+ */
+ private int branchOffsetSize()
+ {
+ return opcode == InstructionConstants.OP_GOTO_W ||
+ opcode == InstructionConstants.OP_JSR_W ? 4 :
+ 2;
+ }
+
+
+ /**
+ * Computes the required branch offset size for this instruction's branch
+ * offset.
+ */
+ private int requiredBranchOffsetSize()
+ {
+ return (short)branchOffset == branchOffset ? 2 : 4;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/ConstantInstruction.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/ConstantInstruction.java
new file mode 100644
index 0000000000..0c6d5c5594
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/ConstantInstruction.java
@@ -0,0 +1,309 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.ClassUtil;
+
+/**
+ * This Instruction represents an instruction that refers to an entry in the
+ * constant pool.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantInstruction extends Instruction
+implements ConstantVisitor
+{
+ public int constantIndex;
+ public int constant;
+
+
+ // Fields acting as return parameters for the ConstantVisitor methods.
+ private int parameterStackDelta;
+ private int typeStackDelta;
+
+
+ /**
+ * Creates an uninitialized ConstantInstruction.
+ */
+ public ConstantInstruction() {}
+
+
+ /**
+ * Creates a new ConstantInstruction with the given opcode and constant pool
+ * index.
+ */
+ public ConstantInstruction(byte opcode, int constantIndex)
+ {
+ this(opcode, constantIndex, 0);
+ }
+
+
+ /**
+ * Creates a new ConstantInstruction with the given opcode, constant pool
+ * index, and constant.
+ */
+ public ConstantInstruction(byte opcode, int constantIndex, int constant)
+ {
+ this.opcode = opcode;
+ this.constantIndex = constantIndex;
+ this.constant = constant;
+ }
+
+
+ /**
+ * Copies the given instruction into this instruction.
+ * @param constantInstruction the instruction to be copied.
+ * @return this instruction.
+ */
+ public ConstantInstruction copy(ConstantInstruction constantInstruction)
+ {
+ this.opcode = constantInstruction.opcode;
+ this.constantIndex = constantInstruction.constantIndex;
+ this.constant = constantInstruction.constant;
+
+ return this;
+ }
+
+
+ // Implementations for Instruction.
+
+ public byte canonicalOpcode()
+ {
+ // Remove the _w extension, if any.
+ return
+ opcode == InstructionConstants.OP_LDC_W ? InstructionConstants.OP_LDC :
+ opcode;
+ }
+
+ public Instruction shrink()
+ {
+ // Do we need a short index or a long index?
+ if (requiredConstantIndexSize() == 1)
+ {
+ // Can we replace the long instruction by a short instruction?
+ if (opcode == InstructionConstants.OP_LDC_W)
+ {
+ opcode = InstructionConstants.OP_LDC;
+ }
+ }
+ else
+ {
+ // Should we replace the short instruction by a long instruction?
+ if (opcode == InstructionConstants.OP_LDC)
+ {
+ opcode = InstructionConstants.OP_LDC_W;
+ }
+ }
+
+ return this;
+ }
+
+ protected void readInfo(byte[] code, int offset)
+ {
+ int constantIndexSize = constantIndexSize();
+ int constantSize = constantSize();
+
+ constantIndex = readValue(code, offset, constantIndexSize); offset += constantIndexSize;
+ constant = readValue(code, offset, constantSize);
+ }
+
+
+ protected void writeInfo(byte[] code, int offset)
+ {
+ int constantIndexSize = constantIndexSize();
+ int constantSize = constantSize();
+
+ if (requiredConstantIndexSize() > constantIndexSize)
+ {
+ throw new IllegalArgumentException("Instruction has invalid constant index size ("+this.toString(offset)+")");
+ }
+
+ writeValue(code, offset, constantIndex, constantIndexSize); offset += constantIndexSize;
+ writeValue(code, offset, constant, constantSize);
+ }
+
+
+ public int length(int offset)
+ {
+ return 1 + constantIndexSize() + constantSize();
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
+ {
+ instructionVisitor.visitConstantInstruction(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public int stackPopCount(Clazz clazz)
+ {
+ int stackPopCount = super.stackPopCount(clazz);
+
+ // Some special cases.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_MULTIANEWARRAY:
+ // For each dimension, an integer size is popped from the stack.
+ stackPopCount += constant;
+ break;
+
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_PUTFIELD:
+ // The field value is be popped from the stack.
+ clazz.constantPoolEntryAccept(constantIndex, this);
+ stackPopCount += typeStackDelta;
+ break;
+
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ // Some parameters may be popped from the stack.
+ clazz.constantPoolEntryAccept(constantIndex, this);
+ stackPopCount += parameterStackDelta;
+ break;
+ }
+
+ return stackPopCount;
+ }
+
+
+ public int stackPushCount(Clazz clazz)
+ {
+ int stackPushCount = super.stackPushCount(clazz);
+
+ // Some special cases.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_GETFIELD:
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ // The field value or a return value may be pushed onto the stack.
+ clazz.constantPoolEntryAccept(constantIndex, this);
+ stackPushCount += typeStackDelta;
+ break;
+ }
+
+ return stackPushCount;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant) {}
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant) {}
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant) {}
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) {}
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant) {}
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) {}
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) {}
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant) {}
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) {}
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ String type = fieldrefConstant.getType(clazz);
+
+ typeStackDelta = ClassUtil.internalTypeSize(ClassUtil.internalMethodReturnType(type));
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this);
+ }
+
+
+ public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
+ {
+ clazz.constantPoolEntryAccept(interfaceMethodrefConstant.u2nameAndTypeIndex, this);
+ }
+
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ clazz.constantPoolEntryAccept(methodrefConstant.u2nameAndTypeIndex, this);
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ String type = nameAndTypeConstant.getType(clazz);
+
+ parameterStackDelta = ClassUtil.internalMethodParameterSize(type);
+ typeStackDelta = ClassUtil.internalTypeSize(ClassUtil.internalMethodReturnType(type));
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return getName()+" #"+constantIndex+(constantSize() == 0 ? "" : ", "+constant);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the constant pool index size for this instruction.
+ */
+ private int constantIndexSize()
+ {
+ return opcode == InstructionConstants.OP_LDC ? 1 :
+ 2;
+ }
+
+
+ /**
+ * Returns the constant size for this instruction.
+ */
+ private int constantSize()
+ {
+ return opcode == InstructionConstants.OP_MULTIANEWARRAY ? 1 :
+ opcode == InstructionConstants.OP_INVOKEDYNAMIC ||
+ opcode == InstructionConstants.OP_INVOKEINTERFACE ? 2 :
+ 0;
+ }
+
+
+ /**
+ * Computes the required constant pool index size for this instruction's
+ * constant pool index.
+ */
+ private int requiredConstantIndexSize()
+ {
+ return (constantIndex & 0xff) == constantIndex ? 1 :
+ (constantIndex & 0xffff) == constantIndex ? 2 :
+ 4;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/Instruction.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/Instruction.java
new file mode 100644
index 0000000000..5fe0bba612
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/Instruction.java
@@ -0,0 +1,1137 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+
+/**
+ * Base class for representing instructions.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class Instruction
+{
+ // An array for marking instructions that may throw exceptions.
+ private static final boolean[] MAY_THROW_EXCEPTIONS = new boolean[]
+ {
+ false, // nop
+ false, // aconst_null
+ false, // iconst_m1
+ false, // iconst_0
+ false, // iconst_1
+ false, // iconst_2
+ false, // iconst_3
+ false, // iconst_4
+ false, // iconst_5
+ false, // lconst_0
+ false, // lconst_1
+ false, // fconst_0
+ false, // fconst_1
+ false, // fconst_2
+ false, // dconst_0
+ false, // dconst_1
+ false, // bipush
+ false, // sipush
+ false, // ldc
+ false, // ldc_w
+ false, // ldc2_w
+ false, // iload
+ false, // lload
+ false, // fload
+ false, // dload
+ false, // aload
+ false, // iload_0
+ false, // iload_1
+ false, // iload_2
+ false, // iload_3
+ false, // lload_0
+ false, // lload_1
+ false, // lload_2
+ false, // lload_3
+ false, // fload_0
+ false, // fload_1
+ false, // fload_2
+ false, // fload_3
+ false, // dload_0
+ false, // dload_1
+ false, // dload_2
+ false, // dload_3
+ false, // aload_0
+ false, // aload_1
+ false, // aload_2
+ false, // aload_3
+ true, // iaload
+ true, // laload
+ true, // faload
+ true, // daload
+ true, // aaload
+ true, // baload
+ true, // caload
+ true, // saload
+ false, // istore
+ false, // lstore
+ false, // fstore
+ false, // dstore
+ false, // astore
+ false, // istore_0
+ false, // istore_1
+ false, // istore_2
+ false, // istore_3
+ false, // lstore_0
+ false, // lstore_1
+ false, // lstore_2
+ false, // lstore_3
+ false, // fstore_0
+ false, // fstore_1
+ false, // fstore_2
+ false, // fstore_3
+ false, // dstore_0
+ false, // dstore_1
+ false, // dstore_2
+ false, // dstore_3
+ false, // astore_0
+ false, // astore_1
+ false, // astore_2
+ false, // astore_3
+ true, // iastore
+ true, // lastore
+ true, // fastore
+ true, // dastore
+ true, // aastore
+ true, // bastore
+ true, // castore
+ true, // sastore
+ false, // pop
+ false, // pop2
+ false, // dup
+ false, // dup_x1
+ false, // dup_x2
+ false, // dup2
+ false, // dup2_x1
+ false, // dup2_x2
+ false, // swap
+ false, // iadd
+ false, // ladd
+ false, // fadd
+ false, // dadd
+ false, // isub
+ false, // lsub
+ false, // fsub
+ false, // dsub
+ false, // imul
+ false, // lmul
+ false, // fmul
+ false, // dmul
+ true, // idiv
+ true, // ldiv
+ false, // fdiv
+ false, // ddiv
+ true, // irem
+ true, // lrem
+ false, // frem
+ false, // drem
+ false, // ineg
+ false, // lneg
+ false, // fneg
+ false, // dneg
+ false, // ishl
+ false, // lshl
+ false, // ishr
+ false, // lshr
+ false, // iushr
+ false, // lushr
+ false, // iand
+ false, // land
+ false, // ior
+ false, // lor
+ false, // ixor
+ false, // lxor
+ false, // iinc
+ false, // i2l
+ false, // i2f
+ false, // i2d
+ false, // l2i
+ false, // l2f
+ false, // l2d
+ false, // f2i
+ false, // f2l
+ false, // f2d
+ false, // d2i
+ false, // d2l
+ false, // d2f
+ false, // i2b
+ false, // i2c
+ false, // i2s
+ false, // lcmp
+ false, // fcmpl
+ false, // fcmpg
+ false, // dcmpl
+ false, // dcmpg
+ false, // ifeq
+ false, // ifne
+ false, // iflt
+ false, // ifge
+ false, // ifgt
+ false, // ifle
+ false, // ificmpeq
+ false, // ificmpne
+ false, // ificmplt
+ false, // ificmpge
+ false, // ificmpgt
+ false, // ificmple
+ false, // ifacmpeq
+ false, // ifacmpne
+ false, // goto
+ false, // jsr
+ false, // ret
+ false, // tableswitch
+ false, // lookupswitch
+ false, // ireturn
+ false, // lreturn
+ false, // freturn
+ false, // dreturn
+ false, // areturn
+ false, // return
+ true, // getstatic
+ true, // putstatic
+ true, // getfield
+ true, // putfield
+ true, // invokevirtual
+ true, // invokespecial
+ true, // invokestatic
+ true, // invokeinterface
+ true, // invokedynamic
+ true, // new
+ true, // newarray
+ true, // anewarray
+ true, // arraylength
+ true, // athrow
+ true, // checkcast
+ false, // instanceof
+ true, // monitorenter
+ true, // monitorexit
+ false, // wide
+ true, // multianewarray
+ false, // ifnull
+ false, // ifnonnull
+ false, // goto_w
+ false, // jsr_w
+ };
+
+
+ // An array for marking Category 2 instructions.
+ private static final boolean[] IS_CATEGORY2 = new boolean[]
+ {
+ false, // nop
+ false, // aconst_null
+ false, // iconst_m1
+ false, // iconst_0
+ false, // iconst_1
+ false, // iconst_2
+ false, // iconst_3
+ false, // iconst_4
+ false, // iconst_5
+ true, // lconst_0
+ true, // lconst_1
+ false, // fconst_0
+ false, // fconst_1
+ false, // fconst_2
+ true, // dconst_0
+ true, // dconst_1
+ false, // bipush
+ false, // sipush
+ false, // ldc
+ false, // ldc_w
+ true, // ldc2_w
+ false, // iload
+ true, // lload
+ false, // fload
+ true, // dload
+ false, // aload
+ false, // iload_0
+ false, // iload_1
+ false, // iload_2
+ false, // iload_3
+ true, // lload_0
+ true, // lload_1
+ true, // lload_2
+ true, // lload_3
+ false, // fload_0
+ false, // fload_1
+ false, // fload_2
+ false, // fload_3
+ true, // dload_0
+ true, // dload_1
+ true, // dload_2
+ true, // dload_3
+ false, // aload_0
+ false, // aload_1
+ false, // aload_2
+ false, // aload_3
+ false, // iaload
+ true, // laload
+ false, // faload
+ true, // daload
+ false, // aaload
+ false, // baload
+ false, // caload
+ false, // saload
+ false, // istore
+ true, // lstore
+ false, // fstore
+ true, // dstore
+ false, // astore
+ false, // istore_0
+ false, // istore_1
+ false, // istore_2
+ false, // istore_3
+ true, // lstore_0
+ true, // lstore_1
+ true, // lstore_2
+ true, // lstore_3
+ false, // fstore_0
+ false, // fstore_1
+ false, // fstore_2
+ false, // fstore_3
+ true, // dstore_0
+ true, // dstore_1
+ true, // dstore_2
+ true, // dstore_3
+ false, // astore_0
+ false, // astore_1
+ false, // astore_2
+ false, // astore_3
+ false, // iastore
+ true, // lastore
+ false, // fastore
+ true, // dastore
+ false, // aastore
+ false, // bastore
+ false, // castore
+ false, // sastore
+ false, // pop
+ true, // pop2
+ false, // dup
+ false, // dup_x1
+ false, // dup_x2
+ true, // dup2
+ true, // dup2_x1
+ true, // dup2_x2
+ false, // swap
+ false, // iadd
+ true, // ladd
+ false, // fadd
+ true, // dadd
+ false, // isub
+ true, // lsub
+ false, // fsub
+ true, // dsub
+ false, // imul
+ true, // lmul
+ false, // fmul
+ true, // dmul
+ false, // idiv
+ true, // ldiv
+ false, // fdiv
+ true, // ddiv
+ false, // irem
+ true, // lrem
+ false, // frem
+ true, // drem
+ false, // ineg
+ true, // lneg
+ false, // fneg
+ true, // dneg
+ false, // ishl
+ true, // lshl
+ false, // ishr
+ true, // lshr
+ false, // iushr
+ true, // lushr
+ false, // iand
+ true, // land
+ false, // ior
+ true, // lor
+ false, // ixor
+ true, // lxor
+ false, // iinc
+ false, // i2l
+ false, // i2f
+ false, // i2d
+ true, // l2i
+ true, // l2f
+ true, // l2d
+ false, // f2i
+ false, // f2l
+ false, // f2d
+ true, // d2i
+ true, // d2l
+ true, // d2f
+ false, // i2b
+ false, // i2c
+ false, // i2s
+ true, // lcmp
+ false, // fcmpl
+ false, // fcmpg
+ true, // dcmpl
+ true, // dcmpg
+ false, // ifeq
+ false, // ifne
+ false, // iflt
+ false, // ifge
+ false, // ifgt
+ false, // ifle
+ false, // ificmpeq
+ false, // ificmpne
+ false, // ificmplt
+ false, // ificmpge
+ false, // ificmpgt
+ false, // ificmple
+ false, // ifacmpeq
+ false, // ifacmpne
+ false, // goto
+ false, // jsr
+ false, // ret
+ false, // tableswitch
+ false, // lookupswitch
+ false, // ireturn
+ true, // lreturn
+ false, // freturn
+ true, // dreturn
+ false, // areturn
+ false, // return
+ false, // getstatic
+ false, // putstatic
+ false, // getfield
+ false, // putfield
+ false, // invokevirtual
+ false, // invokespecial
+ false, // invokestatic
+ false, // invokeinterface
+ false, // invokedynamic
+ false, // new
+ false, // newarray
+ false, // anewarray
+ false, // arraylength
+ false, // athrow
+ false, // checkcast
+ false, // instanceof
+ false, // monitorenter
+ false, // monitorexit
+ false, // wide
+ false, // multianewarray
+ false, // ifnull
+ false, // ifnonnull
+ false, // goto_w
+ false, // jsr_w
+ };
+
+
+ // An array containing the fixed number of entries popped from the stack,
+ // for all instructions.
+ private static final int[] STACK_POP_COUNTS = new int[]
+ {
+ 0, // nop
+ 0, // aconst_null
+ 0, // iconst_m1
+ 0, // iconst_0
+ 0, // iconst_1
+ 0, // iconst_2
+ 0, // iconst_3
+ 0, // iconst_4
+ 0, // iconst_5
+ 0, // lconst_0
+ 0, // lconst_1
+ 0, // fconst_0
+ 0, // fconst_1
+ 0, // fconst_2
+ 0, // dconst_0
+ 0, // dconst_1
+ 0, // bipush
+ 0, // sipush
+ 0, // ldc
+ 0, // ldc_w
+ 0, // ldc2_w
+ 0, // iload
+ 0, // lload
+ 0, // fload
+ 0, // dload
+ 0, // aload
+ 0, // iload_0
+ 0, // iload_1
+ 0, // iload_2
+ 0, // iload_3
+ 0, // lload_0
+ 0, // lload_1
+ 0, // lload_2
+ 0, // lload_3
+ 0, // fload_0
+ 0, // fload_1
+ 0, // fload_2
+ 0, // fload_3
+ 0, // dload_0
+ 0, // dload_1
+ 0, // dload_2
+ 0, // dload_3
+ 0, // aload_0
+ 0, // aload_1
+ 0, // aload_2
+ 0, // aload_3
+ 2, // iaload
+ 2, // laload
+ 2, // faload
+ 2, // daload
+ 2, // aaload
+ 2, // baload
+ 2, // caload
+ 2, // saload
+ 1, // istore
+ 2, // lstore
+ 1, // fstore
+ 2, // dstore
+ 1, // astore
+ 1, // istore_0
+ 1, // istore_1
+ 1, // istore_2
+ 1, // istore_3
+ 2, // lstore_0
+ 2, // lstore_1
+ 2, // lstore_2
+ 2, // lstore_3
+ 1, // fstore_0
+ 1, // fstore_1
+ 1, // fstore_2
+ 1, // fstore_3
+ 2, // dstore_0
+ 2, // dstore_1
+ 2, // dstore_2
+ 2, // dstore_3
+ 1, // astore_0
+ 1, // astore_1
+ 1, // astore_2
+ 1, // astore_3
+ 3, // iastore
+ 4, // lastore
+ 3, // fastore
+ 4, // dastore
+ 3, // aastore
+ 3, // bastore
+ 3, // castore
+ 3, // sastore
+ 1, // pop
+ 2, // pop2
+ 1, // dup
+ 2, // dup_x1
+ 3, // dup_x2
+ 2, // dup2
+ 3, // dup2_x1
+ 4, // dup2_x2
+ 2, // swap
+ 2, // iadd
+ 4, // ladd
+ 2, // fadd
+ 4, // dadd
+ 2, // isub
+ 4, // lsub
+ 2, // fsub
+ 4, // dsub
+ 2, // imul
+ 4, // lmul
+ 2, // fmul
+ 4, // dmul
+ 2, // idiv
+ 4, // ldiv
+ 2, // fdiv
+ 4, // ddiv
+ 2, // irem
+ 4, // lrem
+ 2, // frem
+ 4, // drem
+ 1, // ineg
+ 2, // lneg
+ 1, // fneg
+ 2, // dneg
+ 2, // ishl
+ 3, // lshl
+ 2, // ishr
+ 3, // lshr
+ 2, // iushr
+ 3, // lushr
+ 2, // iand
+ 4, // land
+ 2, // ior
+ 4, // lor
+ 2, // ixor
+ 4, // lxor
+ 0, // iinc
+ 1, // i2l
+ 1, // i2f
+ 1, // i2d
+ 2, // l2i
+ 2, // l2f
+ 2, // l2d
+ 1, // f2i
+ 1, // f2l
+ 1, // f2d
+ 2, // d2i
+ 2, // d2l
+ 2, // d2f
+ 1, // i2b
+ 1, // i2c
+ 1, // i2s
+ 4, // lcmp
+ 2, // fcmpl
+ 2, // fcmpg
+ 4, // dcmpl
+ 4, // dcmpg
+ 1, // ifeq
+ 1, // ifne
+ 1, // iflt
+ 1, // ifge
+ 1, // ifgt
+ 1, // ifle
+ 2, // ificmpeq
+ 2, // ificmpne
+ 2, // ificmplt
+ 2, // ificmpge
+ 2, // ificmpgt
+ 2, // ificmple
+ 2, // ifacmpeq
+ 2, // ifacmpne
+ 0, // goto
+ 0, // jsr
+ 0, // ret
+ 1, // tableswitch
+ 1, // lookupswitch
+ 1, // ireturn
+ 2, // lreturn
+ 1, // freturn
+ 2, // dreturn
+ 1, // areturn
+ 0, // return
+ 0, // getstatic
+ 0, // putstatic
+ 1, // getfield
+ 1, // putfield
+ 1, // invokevirtual
+ 1, // invokespecial
+ 0, // invokestatic
+ 1, // invokeinterface
+ 0, // invokedynamic
+ 0, // new
+ 1, // newarray
+ 1, // anewarray
+ 1, // arraylength
+ 1, // athrow
+ 1, // checkcast
+ 1, // instanceof
+ 1, // monitorenter
+ 1, // monitorexit
+ 0, // wide
+ 0, // multianewarray
+ 1, // ifnull
+ 1, // ifnonnull
+ 0, // goto_w
+ 0, // jsr_w
+ };
+
+
+ // An array containing the fixed number of entries pushed onto the stack,
+ // for all instructions.
+ private static final int[] STACK_PUSH_COUNTS = new int[]
+ {
+ 0, // nop
+ 1, // aconst_null
+ 1, // iconst_m1
+ 1, // iconst_0
+ 1, // iconst_1
+ 1, // iconst_2
+ 1, // iconst_3
+ 1, // iconst_4
+ 1, // iconst_5
+ 2, // lconst_0
+ 2, // lconst_1
+ 1, // fconst_0
+ 1, // fconst_1
+ 1, // fconst_2
+ 2, // dconst_0
+ 2, // dconst_1
+ 1, // bipush
+ 1, // sipush
+ 1, // ldc
+ 1, // ldc_w
+ 2, // ldc2_w
+ 1, // iload
+ 2, // lload
+ 1, // fload
+ 2, // dload
+ 1, // aload
+ 1, // iload_0
+ 1, // iload_1
+ 1, // iload_2
+ 1, // iload_3
+ 2, // lload_0
+ 2, // lload_1
+ 2, // lload_2
+ 2, // lload_3
+ 1, // fload_0
+ 1, // fload_1
+ 1, // fload_2
+ 1, // fload_3
+ 2, // dload_0
+ 2, // dload_1
+ 2, // dload_2
+ 2, // dload_3
+ 1, // aload_0
+ 1, // aload_1
+ 1, // aload_2
+ 1, // aload_3
+ 1, // iaload
+ 2, // laload
+ 1, // faload
+ 2, // daload
+ 1, // aaload
+ 1, // baload
+ 1, // caload
+ 1, // saload
+ 0, // istore
+ 0, // lstore
+ 0, // fstore
+ 0, // dstore
+ 0, // astore
+ 0, // istore_0
+ 0, // istore_1
+ 0, // istore_2
+ 0, // istore_3
+ 0, // lstore_0
+ 0, // lstore_1
+ 0, // lstore_2
+ 0, // lstore_3
+ 0, // fstore_0
+ 0, // fstore_1
+ 0, // fstore_2
+ 0, // fstore_3
+ 0, // dstore_0
+ 0, // dstore_1
+ 0, // dstore_2
+ 0, // dstore_3
+ 0, // astore_0
+ 0, // astore_1
+ 0, // astore_2
+ 0, // astore_3
+ 0, // iastore
+ 0, // lastore
+ 0, // fastore
+ 0, // dastore
+ 0, // aastore
+ 0, // bastore
+ 0, // castore
+ 0, // sastore
+ 0, // pop
+ 0, // pop2
+ 2, // dup
+ 3, // dup_x1
+ 4, // dup_x2
+ 4, // dup2
+ 5, // dup2_x1
+ 6, // dup2_x2
+ 2, // swap
+ 1, // iadd
+ 2, // ladd
+ 1, // fadd
+ 2, // dadd
+ 1, // isub
+ 2, // lsub
+ 1, // fsub
+ 2, // dsub
+ 1, // imul
+ 2, // lmul
+ 1, // fmul
+ 2, // dmul
+ 1, // idiv
+ 2, // ldiv
+ 1, // fdiv
+ 2, // ddiv
+ 1, // irem
+ 2, // lrem
+ 1, // frem
+ 2, // drem
+ 1, // ineg
+ 2, // lneg
+ 1, // fneg
+ 2, // dneg
+ 1, // ishl
+ 2, // lshl
+ 1, // ishr
+ 2, // lshr
+ 1, // iushr
+ 2, // lushr
+ 1, // iand
+ 2, // land
+ 1, // ior
+ 2, // lor
+ 1, // ixor
+ 2, // lxor
+ 0, // iinc
+ 2, // i2l
+ 1, // i2f
+ 2, // i2d
+ 1, // l2i
+ 1, // l2f
+ 2, // l2d
+ 1, // f2i
+ 2, // f2l
+ 2, // f2d
+ 1, // d2i
+ 2, // d2l
+ 1, // d2f
+ 1, // i2b
+ 1, // i2c
+ 1, // i2s
+ 1, // lcmp
+ 1, // fcmpl
+ 1, // fcmpg
+ 1, // dcmpl
+ 1, // dcmpg
+ 0, // ifeq
+ 0, // ifne
+ 0, // iflt
+ 0, // ifge
+ 0, // ifgt
+ 0, // ifle
+ 0, // ificmpeq
+ 0, // ificmpne
+ 0, // ificmplt
+ 0, // ificmpge
+ 0, // ificmpgt
+ 0, // ificmple
+ 0, // ifacmpeq
+ 0, // ifacmpne
+ 0, // goto
+ 1, // jsr
+ 0, // ret
+ 0, // tableswitch
+ 0, // lookupswitch
+ 0, // ireturn
+ 0, // lreturn
+ 0, // freturn
+ 0, // dreturn
+ 0, // areturn
+ 0, // return
+ 0, // getstatic
+ 0, // putstatic
+ 0, // getfield
+ 0, // putfield
+ 0, // invokevirtual
+ 0, // invokespecial
+ 0, // invokestatic
+ 0, // invokeinterface
+ 0, // invokedynamic
+ 1, // new
+ 1, // newarray
+ 1, // anewarray
+ 1, // arraylength
+ 0, // athrow
+ 1, // checkcast
+ 1, // instanceof
+ 0, // monitorenter
+ 0, // monitorexit
+ 0, // wide
+ 1, // multianewarray
+ 0, // ifnull
+ 0, // ifnonnull
+ 0, // goto_w
+ 1, // jsr_w
+ };
+
+
+ public byte opcode;
+
+
+ /**
+ * Returns the canonical opcode of this instruction, i.e. typically the
+ * opcode whose extension has been removed.
+ */
+ public byte canonicalOpcode()
+ {
+ return opcode;
+ }
+
+
+ /**
+ * Shrinks this instruction to its shortest possible form.
+ * @return this instruction.
+ */
+ public abstract Instruction shrink();
+
+
+
+ /**
+ * Writes the Instruction at the given offset in the given code attribute.
+ */
+ public final void write(CodeAttribute codeAttribute, int offset)
+ {
+ write(codeAttribute.code, offset);
+ }
+
+
+ /**
+ * Writes the Instruction at the given offset in the given code array.
+ */
+ public void write(byte[] code, int offset)
+ {
+ // Write the wide opcode, if necessary.
+ if (isWide())
+ {
+ code[offset++] = InstructionConstants.OP_WIDE;
+ }
+
+ // Write the opcode.
+ code[offset++] = opcode;
+
+ // Write any additional arguments.
+ writeInfo(code, offset);
+ }
+
+
+ /**
+ * Returns whether the instruction is wide, i.e. preceded by a wide opcode.
+ * With the current specifications, only variable instructions can be wide.
+ */
+ protected boolean isWide()
+ {
+ return false;
+ }
+
+
+ /**
+ * Reads the data following the instruction opcode.
+ */
+ protected abstract void readInfo(byte[] code, int offset);
+
+
+ /**
+ * Writes data following the instruction opcode.
+ */
+ protected abstract void writeInfo(byte[] code, int offset);
+
+
+ /**
+ * Returns the length in bytes of the instruction.
+ */
+ public abstract int length(int offset);
+
+
+ /**
+ * Accepts the given visitor.
+ */
+ public abstract void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor);
+
+
+ /**
+ * Returns a description of the instruction, at the given offset.
+ */
+ public String toString(int offset)
+ {
+ return "["+offset+"] "+ this.toString();
+ }
+
+
+ /**
+ * Returns the name of the instruction.
+ */
+ public String getName()
+ {
+ return InstructionConstants.NAMES[opcode & 0xff];
+ }
+
+
+ /**
+ * Returns whether the instruction may throw exceptions.
+ */
+ public boolean mayThrowExceptions()
+ {
+ return MAY_THROW_EXCEPTIONS[opcode & 0xff];
+ }
+
+
+ /**
+ * Returns whether the instruction is a Category 2 instruction. This means
+ * that it operates on long or double arguments.
+ */
+ public boolean isCategory2()
+ {
+ return IS_CATEGORY2[opcode & 0xff];
+ }
+
+
+ /**
+ * Returns the number of entries popped from the stack during the execution
+ * of the instruction.
+ */
+ public int stackPopCount(Clazz clazz)
+ {
+ return STACK_POP_COUNTS[opcode & 0xff];
+ }
+
+
+ /**
+ * Returns the number of entries pushed onto the stack during the execution
+ * of the instruction.
+ */
+ public int stackPushCount(Clazz clazz)
+ {
+ return STACK_PUSH_COUNTS[opcode & 0xff];
+ }
+
+
+ // Small utility methods.
+
+ protected static int readByte(byte[] code, int offset)
+ {
+ return code[offset] & 0xff;
+ }
+
+ protected static int readShort(byte[] code, int offset)
+ {
+ return ((code[offset++] & 0xff) << 8) |
+ ( code[offset ] & 0xff );
+ }
+
+ protected static int readInt(byte[] code, int offset)
+ {
+ return ( code[offset++] << 24) |
+ ((code[offset++] & 0xff) << 16) |
+ ((code[offset++] & 0xff) << 8) |
+ ( code[offset ] & 0xff );
+ }
+
+ protected static int readValue(byte[] code, int offset, int valueSize)
+ {
+ switch (valueSize)
+ {
+ case 0: return 0;
+ case 1: return readByte( code, offset);
+ case 2: return readShort(code, offset);
+ case 4: return readInt( code, offset);
+ default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
+ }
+ }
+
+ protected static int readSignedByte(byte[] code, int offset)
+ {
+ return code[offset];
+ }
+
+ protected static int readSignedShort(byte[] code, int offset)
+ {
+ return (code[offset++] << 8) |
+ (code[offset ] & 0xff);
+ }
+
+ protected static int readSignedValue(byte[] code, int offset, int valueSize)
+ {
+ switch (valueSize)
+ {
+ case 0: return 0;
+ case 1: return readSignedByte( code, offset);
+ case 2: return readSignedShort(code, offset);
+ case 4: return readInt( code, offset);
+ default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
+ }
+ }
+
+ protected static void writeByte(byte[] code, int offset, int value)
+ {
+ if (value > 0xff)
+ {
+ throw new IllegalArgumentException("Unsigned byte value larger than 0xff ["+value+"]");
+ }
+
+ code[offset] = (byte)value;
+ }
+
+ protected static void writeShort(byte[] code, int offset, int value)
+ {
+ if (value > 0xffff)
+ {
+ throw new IllegalArgumentException("Unsigned short value larger than 0xffff ["+value+"]");
+ }
+
+ code[offset++] = (byte)(value >> 8);
+ code[offset ] = (byte)(value );
+ }
+
+ protected static void writeInt(byte[] code, int offset, int value)
+ {
+ code[offset++] = (byte)(value >> 24);
+ code[offset++] = (byte)(value >> 16);
+ code[offset++] = (byte)(value >> 8);
+ code[offset ] = (byte)(value );
+ }
+
+ protected static void writeValue(byte[] code, int offset, int value, int valueSize)
+ {
+ switch (valueSize)
+ {
+ case 0: break;
+ case 1: writeByte( code, offset, value); break;
+ case 2: writeShort(code, offset, value); break;
+ case 4: writeInt( code, offset, value); break;
+ default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
+ }
+ }
+
+ protected static void writeSignedByte(byte[] code, int offset, int value)
+ {
+ if ((byte)value != value)
+ {
+ throw new IllegalArgumentException("Signed byte value out of range ["+value+"]");
+ }
+
+ code[offset] = (byte)value;
+ }
+
+ protected static void writeSignedShort(byte[] code, int offset, int value)
+ {
+ if ((short)value != value)
+ {
+ throw new IllegalArgumentException("Signed short value out of range ["+value+"]");
+ }
+
+ code[offset++] = (byte)(value >> 8);
+ code[offset ] = (byte)(value );
+ }
+
+ protected static void writeSignedValue(byte[] code, int offset, int value, int valueSize)
+ {
+ switch (valueSize)
+ {
+ case 0: break;
+ case 1: writeSignedByte( code, offset, value); break;
+ case 2: writeSignedShort(code, offset, value); break;
+ case 4: writeInt( code, offset, value); break;
+ default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionConstants.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionConstants.java
new file mode 100644
index 0000000000..27676877a4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionConstants.java
@@ -0,0 +1,449 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction;
+
+/**
+ * Representation of an instruction.
+ *
+ * @author Eric Lafortune
+ */
+public interface InstructionConstants
+{
+ public static final byte OP_NOP = 0;
+ public static final byte OP_ACONST_NULL = 1;
+ public static final byte OP_ICONST_M1 = 2;
+ public static final byte OP_ICONST_0 = 3;
+ public static final byte OP_ICONST_1 = 4;
+ public static final byte OP_ICONST_2 = 5;
+ public static final byte OP_ICONST_3 = 6;
+ public static final byte OP_ICONST_4 = 7;
+ public static final byte OP_ICONST_5 = 8;
+ public static final byte OP_LCONST_0 = 9;
+ public static final byte OP_LCONST_1 = 10;
+ public static final byte OP_FCONST_0 = 11;
+ public static final byte OP_FCONST_1 = 12;
+ public static final byte OP_FCONST_2 = 13;
+ public static final byte OP_DCONST_0 = 14;
+ public static final byte OP_DCONST_1 = 15;
+ public static final byte OP_BIPUSH = 16;
+ public static final byte OP_SIPUSH = 17;
+ public static final byte OP_LDC = 18;
+ public static final byte OP_LDC_W = 19;
+ public static final byte OP_LDC2_W = 20;
+ public static final byte OP_ILOAD = 21;
+ public static final byte OP_LLOAD = 22;
+ public static final byte OP_FLOAD = 23;
+ public static final byte OP_DLOAD = 24;
+ public static final byte OP_ALOAD = 25;
+ public static final byte OP_ILOAD_0 = 26;
+ public static final byte OP_ILOAD_1 = 27;
+ public static final byte OP_ILOAD_2 = 28;
+ public static final byte OP_ILOAD_3 = 29;
+ public static final byte OP_LLOAD_0 = 30;
+ public static final byte OP_LLOAD_1 = 31;
+ public static final byte OP_LLOAD_2 = 32;
+ public static final byte OP_LLOAD_3 = 33;
+ public static final byte OP_FLOAD_0 = 34;
+ public static final byte OP_FLOAD_1 = 35;
+ public static final byte OP_FLOAD_2 = 36;
+ public static final byte OP_FLOAD_3 = 37;
+ public static final byte OP_DLOAD_0 = 38;
+ public static final byte OP_DLOAD_1 = 39;
+ public static final byte OP_DLOAD_2 = 40;
+ public static final byte OP_DLOAD_3 = 41;
+ public static final byte OP_ALOAD_0 = 42;
+ public static final byte OP_ALOAD_1 = 43;
+ public static final byte OP_ALOAD_2 = 44;
+ public static final byte OP_ALOAD_3 = 45;
+ public static final byte OP_IALOAD = 46;
+ public static final byte OP_LALOAD = 47;
+ public static final byte OP_FALOAD = 48;
+ public static final byte OP_DALOAD = 49;
+ public static final byte OP_AALOAD = 50;
+ public static final byte OP_BALOAD = 51;
+ public static final byte OP_CALOAD = 52;
+ public static final byte OP_SALOAD = 53;
+ public static final byte OP_ISTORE = 54;
+ public static final byte OP_LSTORE = 55;
+ public static final byte OP_FSTORE = 56;
+ public static final byte OP_DSTORE = 57;
+ public static final byte OP_ASTORE = 58;
+ public static final byte OP_ISTORE_0 = 59;
+ public static final byte OP_ISTORE_1 = 60;
+ public static final byte OP_ISTORE_2 = 61;
+ public static final byte OP_ISTORE_3 = 62;
+ public static final byte OP_LSTORE_0 = 63;
+ public static final byte OP_LSTORE_1 = 64;
+ public static final byte OP_LSTORE_2 = 65;
+ public static final byte OP_LSTORE_3 = 66;
+ public static final byte OP_FSTORE_0 = 67;
+ public static final byte OP_FSTORE_1 = 68;
+ public static final byte OP_FSTORE_2 = 69;
+ public static final byte OP_FSTORE_3 = 70;
+ public static final byte OP_DSTORE_0 = 71;
+ public static final byte OP_DSTORE_1 = 72;
+ public static final byte OP_DSTORE_2 = 73;
+ public static final byte OP_DSTORE_3 = 74;
+ public static final byte OP_ASTORE_0 = 75;
+ public static final byte OP_ASTORE_1 = 76;
+ public static final byte OP_ASTORE_2 = 77;
+ public static final byte OP_ASTORE_3 = 78;
+ public static final byte OP_IASTORE = 79;
+ public static final byte OP_LASTORE = 80;
+ public static final byte OP_FASTORE = 81;
+ public static final byte OP_DASTORE = 82;
+ public static final byte OP_AASTORE = 83;
+ public static final byte OP_BASTORE = 84;
+ public static final byte OP_CASTORE = 85;
+ public static final byte OP_SASTORE = 86;
+ public static final byte OP_POP = 87;
+ public static final byte OP_POP2 = 88;
+ public static final byte OP_DUP = 89;
+ public static final byte OP_DUP_X1 = 90;
+ public static final byte OP_DUP_X2 = 91;
+ public static final byte OP_DUP2 = 92;
+ public static final byte OP_DUP2_X1 = 93;
+ public static final byte OP_DUP2_X2 = 94;
+ public static final byte OP_SWAP = 95;
+ public static final byte OP_IADD = 96;
+ public static final byte OP_LADD = 97;
+ public static final byte OP_FADD = 98;
+ public static final byte OP_DADD = 99;
+ public static final byte OP_ISUB = 100;
+ public static final byte OP_LSUB = 101;
+ public static final byte OP_FSUB = 102;
+ public static final byte OP_DSUB = 103;
+ public static final byte OP_IMUL = 104;
+ public static final byte OP_LMUL = 105;
+ public static final byte OP_FMUL = 106;
+ public static final byte OP_DMUL = 107;
+ public static final byte OP_IDIV = 108;
+ public static final byte OP_LDIV = 109;
+ public static final byte OP_FDIV = 110;
+ public static final byte OP_DDIV = 111;
+ public static final byte OP_IREM = 112;
+ public static final byte OP_LREM = 113;
+ public static final byte OP_FREM = 114;
+ public static final byte OP_DREM = 115;
+ public static final byte OP_INEG = 116;
+ public static final byte OP_LNEG = 117;
+ public static final byte OP_FNEG = 118;
+ public static final byte OP_DNEG = 119;
+ public static final byte OP_ISHL = 120;
+ public static final byte OP_LSHL = 121;
+ public static final byte OP_ISHR = 122;
+ public static final byte OP_LSHR = 123;
+ public static final byte OP_IUSHR = 124;
+ public static final byte OP_LUSHR = 125;
+ public static final byte OP_IAND = 126;
+ public static final byte OP_LAND = 127;
+ public static final byte OP_IOR = -128;
+ public static final byte OP_LOR = -127;
+ public static final byte OP_IXOR = -126;
+ public static final byte OP_LXOR = -125;
+ public static final byte OP_IINC = -124;
+ public static final byte OP_I2L = -123;
+ public static final byte OP_I2F = -122;
+ public static final byte OP_I2D = -121;
+ public static final byte OP_L2I = -120;
+ public static final byte OP_L2F = -119;
+ public static final byte OP_L2D = -118;
+ public static final byte OP_F2I = -117;
+ public static final byte OP_F2L = -116;
+ public static final byte OP_F2D = -115;
+ public static final byte OP_D2I = -114;
+ public static final byte OP_D2L = -113;
+ public static final byte OP_D2F = -112;
+ public static final byte OP_I2B = -111;
+ public static final byte OP_I2C = -110;
+ public static final byte OP_I2S = -109;
+ public static final byte OP_LCMP = -108;
+ public static final byte OP_FCMPL = -107;
+ public static final byte OP_FCMPG = -106;
+ public static final byte OP_DCMPL = -105;
+ public static final byte OP_DCMPG = -104;
+ public static final byte OP_IFEQ = -103;
+ public static final byte OP_IFNE = -102;
+ public static final byte OP_IFLT = -101;
+ public static final byte OP_IFGE = -100;
+ public static final byte OP_IFGT = -99;
+ public static final byte OP_IFLE = -98;
+ public static final byte OP_IFICMPEQ = -97;
+ public static final byte OP_IFICMPNE = -96;
+ public static final byte OP_IFICMPLT = -95;
+ public static final byte OP_IFICMPGE = -94;
+ public static final byte OP_IFICMPGT = -93;
+ public static final byte OP_IFICMPLE = -92;
+ public static final byte OP_IFACMPEQ = -91;
+ public static final byte OP_IFACMPNE = -90;
+ public static final byte OP_GOTO = -89;
+ public static final byte OP_JSR = -88;
+ public static final byte OP_RET = -87;
+ public static final byte OP_TABLESWITCH = -86;
+ public static final byte OP_LOOKUPSWITCH = -85;
+ public static final byte OP_IRETURN = -84;
+ public static final byte OP_LRETURN = -83;
+ public static final byte OP_FRETURN = -82;
+ public static final byte OP_DRETURN = -81;
+ public static final byte OP_ARETURN = -80;
+ public static final byte OP_RETURN = -79;
+ public static final byte OP_GETSTATIC = -78;
+ public static final byte OP_PUTSTATIC = -77;
+ public static final byte OP_GETFIELD = -76;
+ public static final byte OP_PUTFIELD = -75;
+ public static final byte OP_INVOKEVIRTUAL = -74;
+ public static final byte OP_INVOKESPECIAL = -73;
+ public static final byte OP_INVOKESTATIC = -72;
+ public static final byte OP_INVOKEINTERFACE = -71;
+ public static final byte OP_INVOKEDYNAMIC = -70;
+ public static final byte OP_NEW = -69;
+ public static final byte OP_NEWARRAY = -68;
+ public static final byte OP_ANEWARRAY = -67;
+ public static final byte OP_ARRAYLENGTH = -66;
+ public static final byte OP_ATHROW = -65;
+ public static final byte OP_CHECKCAST = -64;
+ public static final byte OP_INSTANCEOF = -63;
+ public static final byte OP_MONITORENTER = -62;
+ public static final byte OP_MONITOREXIT = -61;
+ public static final byte OP_WIDE = -60;
+ public static final byte OP_MULTIANEWARRAY = -59;
+ public static final byte OP_IFNULL = -58;
+ public static final byte OP_IFNONNULL = -57;
+ public static final byte OP_GOTO_W = -56;
+ public static final byte OP_JSR_W = -55;
+
+
+ public static final String[] NAMES =
+ {
+ "nop",
+ "aconst_null",
+ "iconst_m1",
+ "iconst_0",
+ "iconst_1",
+ "iconst_2",
+ "iconst_3",
+ "iconst_4",
+ "iconst_5",
+ "lconst_0",
+ "lconst_1",
+ "fconst_0",
+ "fconst_1",
+ "fconst_2",
+ "dconst_0",
+ "dconst_1",
+ "bipush",
+ "sipush",
+ "ldc",
+ "ldc_w",
+ "ldc2_w",
+ "iload",
+ "lload",
+ "fload",
+ "dload",
+ "aload",
+ "iload_0",
+ "iload_1",
+ "iload_2",
+ "iload_3",
+ "lload_0",
+ "lload_1",
+ "lload_2",
+ "lload_3",
+ "fload_0",
+ "fload_1",
+ "fload_2",
+ "fload_3",
+ "dload_0",
+ "dload_1",
+ "dload_2",
+ "dload_3",
+ "aload_0",
+ "aload_1",
+ "aload_2",
+ "aload_3",
+ "iaload",
+ "laload",
+ "faload",
+ "daload",
+ "aaload",
+ "baload",
+ "caload",
+ "saload",
+ "istore",
+ "lstore",
+ "fstore",
+ "dstore",
+ "astore",
+ "istore_0",
+ "istore_1",
+ "istore_2",
+ "istore_3",
+ "lstore_0",
+ "lstore_1",
+ "lstore_2",
+ "lstore_3",
+ "fstore_0",
+ "fstore_1",
+ "fstore_2",
+ "fstore_3",
+ "dstore_0",
+ "dstore_1",
+ "dstore_2",
+ "dstore_3",
+ "astore_0",
+ "astore_1",
+ "astore_2",
+ "astore_3",
+ "iastore",
+ "lastore",
+ "fastore",
+ "dastore",
+ "aastore",
+ "bastore",
+ "castore",
+ "sastore",
+ "pop",
+ "pop2",
+ "dup",
+ "dup_x1",
+ "dup_x2",
+ "dup2",
+ "dup2_x1",
+ "dup2_x2",
+ "swap",
+ "iadd",
+ "ladd",
+ "fadd",
+ "dadd",
+ "isub",
+ "lsub",
+ "fsub",
+ "dsub",
+ "imul",
+ "lmul",
+ "fmul",
+ "dmul",
+ "idiv",
+ "ldiv",
+ "fdiv",
+ "ddiv",
+ "irem",
+ "lrem",
+ "frem",
+ "drem",
+ "ineg",
+ "lneg",
+ "fneg",
+ "dneg",
+ "ishl",
+ "lshl",
+ "ishr",
+ "lshr",
+ "iushr",
+ "lushr",
+ "iand",
+ "land",
+ "ior",
+ "lor",
+ "ixor",
+ "lxor",
+ "iinc",
+ "i2l",
+ "i2f",
+ "i2d",
+ "l2i",
+ "l2f",
+ "l2d",
+ "f2i",
+ "f2l",
+ "f2d",
+ "d2i",
+ "d2l",
+ "d2f",
+ "i2b",
+ "i2c",
+ "i2s",
+ "lcmp",
+ "fcmpl",
+ "fcmpg",
+ "dcmpl",
+ "dcmpg",
+ "ifeq",
+ "ifne",
+ "iflt",
+ "ifge",
+ "ifgt",
+ "ifle",
+ "ificmpeq",
+ "ificmpne",
+ "ificmplt",
+ "ificmpge",
+ "ificmpgt",
+ "ificmple",
+ "ifacmpeq",
+ "ifacmpne",
+ "goto",
+ "jsr",
+ "ret",
+ "tableswitch",
+ "lookupswitch",
+ "ireturn",
+ "lreturn",
+ "freturn",
+ "dreturn",
+ "areturn",
+ "return",
+ "getstatic",
+ "putstatic",
+ "getfield",
+ "putfield",
+ "invokevirtual",
+ "invokespecial",
+ "invokestatic",
+ "invokeinterface",
+ "invokedynamic",
+ "new",
+ "newarray",
+ "anewarray",
+ "arraylength",
+ "athrow",
+ "checkcast",
+ "instanceof",
+ "monitorenter",
+ "monitorexit",
+ "wide",
+ "multianewarray",
+ "ifnull",
+ "ifnonnull",
+ "goto_w",
+ "jsr_w",
+ };
+
+
+ public static final byte ARRAY_T_BOOLEAN = 4;
+ public static final byte ARRAY_T_CHAR = 5;
+ public static final byte ARRAY_T_FLOAT = 6;
+ public static final byte ARRAY_T_DOUBLE = 7;
+ public static final byte ARRAY_T_BYTE = 8;
+ public static final byte ARRAY_T_SHORT = 9;
+ public static final byte ARRAY_T_INT = 10;
+ public static final byte ARRAY_T_LONG = 11;
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionFactory.java
new file mode 100644
index 0000000000..75291d16fa
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionFactory.java
@@ -0,0 +1,300 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction;
+
+/**
+ * This class provides methods to create and reuse Instruction objects.
+ *
+ * @author Eric Lafortune
+ */
+public class InstructionFactory
+{
+ /**
+ * Creates a new Instruction from the data in the byte array, starting
+ * at the given index.
+ */
+ public static Instruction create(byte[] code, int offset)
+ {
+ Instruction instruction;
+
+ int index = offset;
+ byte opcode = code[index++];
+
+ boolean wide = false;
+ if (opcode == InstructionConstants.OP_WIDE)
+ {
+ opcode = code[index++];
+ wide = true;
+ }
+
+ switch (opcode)
+ {
+ // Simple instructions.
+ case InstructionConstants.OP_NOP:
+ case InstructionConstants.OP_ACONST_NULL:
+ case InstructionConstants.OP_ICONST_M1:
+ case InstructionConstants.OP_ICONST_0:
+ case InstructionConstants.OP_ICONST_1:
+ case InstructionConstants.OP_ICONST_2:
+ case InstructionConstants.OP_ICONST_3:
+ case InstructionConstants.OP_ICONST_4:
+ case InstructionConstants.OP_ICONST_5:
+ case InstructionConstants.OP_LCONST_0:
+ case InstructionConstants.OP_LCONST_1:
+ case InstructionConstants.OP_FCONST_0:
+ case InstructionConstants.OP_FCONST_1:
+ case InstructionConstants.OP_FCONST_2:
+ case InstructionConstants.OP_DCONST_0:
+ case InstructionConstants.OP_DCONST_1:
+
+ case InstructionConstants.OP_BIPUSH:
+ case InstructionConstants.OP_SIPUSH:
+
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_LALOAD:
+ case InstructionConstants.OP_FALOAD:
+ case InstructionConstants.OP_DALOAD:
+ case InstructionConstants.OP_AALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+
+ case InstructionConstants.OP_IASTORE:
+ case InstructionConstants.OP_LASTORE:
+ case InstructionConstants.OP_FASTORE:
+ case InstructionConstants.OP_DASTORE:
+ case InstructionConstants.OP_AASTORE:
+ case InstructionConstants.OP_BASTORE:
+ case InstructionConstants.OP_CASTORE:
+ case InstructionConstants.OP_SASTORE:
+ case InstructionConstants.OP_POP:
+ case InstructionConstants.OP_POP2:
+ case InstructionConstants.OP_DUP:
+ case InstructionConstants.OP_DUP_X1:
+ case InstructionConstants.OP_DUP_X2:
+ case InstructionConstants.OP_DUP2:
+ case InstructionConstants.OP_DUP2_X1:
+ case InstructionConstants.OP_DUP2_X2:
+ case InstructionConstants.OP_SWAP:
+ case InstructionConstants.OP_IADD:
+ case InstructionConstants.OP_LADD:
+ case InstructionConstants.OP_FADD:
+ case InstructionConstants.OP_DADD:
+ case InstructionConstants.OP_ISUB:
+ case InstructionConstants.OP_LSUB:
+ case InstructionConstants.OP_FSUB:
+ case InstructionConstants.OP_DSUB:
+ case InstructionConstants.OP_IMUL:
+ case InstructionConstants.OP_LMUL:
+ case InstructionConstants.OP_FMUL:
+ case InstructionConstants.OP_DMUL:
+ case InstructionConstants.OP_IDIV:
+ case InstructionConstants.OP_LDIV:
+ case InstructionConstants.OP_FDIV:
+ case InstructionConstants.OP_DDIV:
+ case InstructionConstants.OP_IREM:
+ case InstructionConstants.OP_LREM:
+ case InstructionConstants.OP_FREM:
+ case InstructionConstants.OP_DREM:
+ case InstructionConstants.OP_INEG:
+ case InstructionConstants.OP_LNEG:
+ case InstructionConstants.OP_FNEG:
+ case InstructionConstants.OP_DNEG:
+ case InstructionConstants.OP_ISHL:
+ case InstructionConstants.OP_LSHL:
+ case InstructionConstants.OP_ISHR:
+ case InstructionConstants.OP_LSHR:
+ case InstructionConstants.OP_IUSHR:
+ case InstructionConstants.OP_LUSHR:
+ case InstructionConstants.OP_IAND:
+ case InstructionConstants.OP_LAND:
+ case InstructionConstants.OP_IOR:
+ case InstructionConstants.OP_LOR:
+ case InstructionConstants.OP_IXOR:
+ case InstructionConstants.OP_LXOR:
+
+ case InstructionConstants.OP_I2L:
+ case InstructionConstants.OP_I2F:
+ case InstructionConstants.OP_I2D:
+ case InstructionConstants.OP_L2I:
+ case InstructionConstants.OP_L2F:
+ case InstructionConstants.OP_L2D:
+ case InstructionConstants.OP_F2I:
+ case InstructionConstants.OP_F2L:
+ case InstructionConstants.OP_F2D:
+ case InstructionConstants.OP_D2I:
+ case InstructionConstants.OP_D2L:
+ case InstructionConstants.OP_D2F:
+ case InstructionConstants.OP_I2B:
+ case InstructionConstants.OP_I2C:
+ case InstructionConstants.OP_I2S:
+ case InstructionConstants.OP_LCMP:
+ case InstructionConstants.OP_FCMPL:
+ case InstructionConstants.OP_FCMPG:
+ case InstructionConstants.OP_DCMPL:
+ case InstructionConstants.OP_DCMPG:
+
+ case InstructionConstants.OP_IRETURN:
+ case InstructionConstants.OP_LRETURN:
+ case InstructionConstants.OP_FRETURN:
+ case InstructionConstants.OP_DRETURN:
+ case InstructionConstants.OP_ARETURN:
+ case InstructionConstants.OP_RETURN:
+
+ case InstructionConstants.OP_NEWARRAY:
+ case InstructionConstants.OP_ARRAYLENGTH:
+ case InstructionConstants.OP_ATHROW:
+
+ case InstructionConstants.OP_MONITORENTER:
+ case InstructionConstants.OP_MONITOREXIT:
+ instruction = new SimpleInstruction();
+ break;
+
+ // Instructions with a contant pool index.
+ case InstructionConstants.OP_LDC:
+ case InstructionConstants.OP_LDC_W:
+ case InstructionConstants.OP_LDC2_W:
+
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_GETFIELD:
+ case InstructionConstants.OP_PUTFIELD:
+
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+
+ case InstructionConstants.OP_NEW:
+ case InstructionConstants.OP_ANEWARRAY:
+ case InstructionConstants.OP_CHECKCAST:
+ case InstructionConstants.OP_INSTANCEOF:
+ case InstructionConstants.OP_MULTIANEWARRAY:
+ instruction = new ConstantInstruction();
+ break;
+
+ // Instructions with a local variable index.
+ case InstructionConstants.OP_ILOAD:
+ case InstructionConstants.OP_LLOAD:
+ case InstructionConstants.OP_FLOAD:
+ case InstructionConstants.OP_DLOAD:
+ case InstructionConstants.OP_ALOAD:
+ case InstructionConstants.OP_ILOAD_0:
+ case InstructionConstants.OP_ILOAD_1:
+ case InstructionConstants.OP_ILOAD_2:
+ case InstructionConstants.OP_ILOAD_3:
+ case InstructionConstants.OP_LLOAD_0:
+ case InstructionConstants.OP_LLOAD_1:
+ case InstructionConstants.OP_LLOAD_2:
+ case InstructionConstants.OP_LLOAD_3:
+ case InstructionConstants.OP_FLOAD_0:
+ case InstructionConstants.OP_FLOAD_1:
+ case InstructionConstants.OP_FLOAD_2:
+ case InstructionConstants.OP_FLOAD_3:
+ case InstructionConstants.OP_DLOAD_0:
+ case InstructionConstants.OP_DLOAD_1:
+ case InstructionConstants.OP_DLOAD_2:
+ case InstructionConstants.OP_DLOAD_3:
+ case InstructionConstants.OP_ALOAD_0:
+ case InstructionConstants.OP_ALOAD_1:
+ case InstructionConstants.OP_ALOAD_2:
+ case InstructionConstants.OP_ALOAD_3:
+
+ case InstructionConstants.OP_ISTORE:
+ case InstructionConstants.OP_LSTORE:
+ case InstructionConstants.OP_FSTORE:
+ case InstructionConstants.OP_DSTORE:
+ case InstructionConstants.OP_ASTORE:
+ case InstructionConstants.OP_ISTORE_0:
+ case InstructionConstants.OP_ISTORE_1:
+ case InstructionConstants.OP_ISTORE_2:
+ case InstructionConstants.OP_ISTORE_3:
+ case InstructionConstants.OP_LSTORE_0:
+ case InstructionConstants.OP_LSTORE_1:
+ case InstructionConstants.OP_LSTORE_2:
+ case InstructionConstants.OP_LSTORE_3:
+ case InstructionConstants.OP_FSTORE_0:
+ case InstructionConstants.OP_FSTORE_1:
+ case InstructionConstants.OP_FSTORE_2:
+ case InstructionConstants.OP_FSTORE_3:
+ case InstructionConstants.OP_DSTORE_0:
+ case InstructionConstants.OP_DSTORE_1:
+ case InstructionConstants.OP_DSTORE_2:
+ case InstructionConstants.OP_DSTORE_3:
+ case InstructionConstants.OP_ASTORE_0:
+ case InstructionConstants.OP_ASTORE_1:
+ case InstructionConstants.OP_ASTORE_2:
+ case InstructionConstants.OP_ASTORE_3:
+
+ case InstructionConstants.OP_IINC:
+
+ case InstructionConstants.OP_RET:
+ instruction = new VariableInstruction(wide);
+ break;
+
+ // Instructions with a branch offset operand.
+ case InstructionConstants.OP_IFEQ:
+ case InstructionConstants.OP_IFNE:
+ case InstructionConstants.OP_IFLT:
+ case InstructionConstants.OP_IFGE:
+ case InstructionConstants.OP_IFGT:
+ case InstructionConstants.OP_IFLE:
+ case InstructionConstants.OP_IFICMPEQ:
+ case InstructionConstants.OP_IFICMPNE:
+ case InstructionConstants.OP_IFICMPLT:
+ case InstructionConstants.OP_IFICMPGE:
+ case InstructionConstants.OP_IFICMPGT:
+ case InstructionConstants.OP_IFICMPLE:
+ case InstructionConstants.OP_IFACMPEQ:
+ case InstructionConstants.OP_IFACMPNE:
+ case InstructionConstants.OP_GOTO:
+ case InstructionConstants.OP_JSR:
+
+ case InstructionConstants.OP_IFNULL:
+ case InstructionConstants.OP_IFNONNULL:
+
+ case InstructionConstants.OP_GOTO_W:
+ case InstructionConstants.OP_JSR_W:
+ instruction = new BranchInstruction();
+ break;
+
+ // The tableswitch instruction.
+ case InstructionConstants.OP_TABLESWITCH:
+ instruction = new TableSwitchInstruction();
+ break;
+
+ // The lookupswitch instruction.
+ case InstructionConstants.OP_LOOKUPSWITCH:
+ instruction = new LookUpSwitchInstruction();
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown instruction opcode ["+opcode+"] at offset "+offset);
+ }
+
+ instruction.opcode = opcode;
+
+ instruction.readInfo(code, index);
+
+ return instruction;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionUtil.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionUtil.java
new file mode 100644
index 0000000000..96962d3e66
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/InstructionUtil.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction;
+
+import proguard.classfile.ClassConstants;
+
+/**
+ * Utility methods for converting between representations of names and
+ * descriptions.
+ *
+ * @author Eric Lafortune
+ */
+public class InstructionUtil
+{
+ /**
+ * Returns the internal type corresponding to the given 'newarray' type.
+ * @param arrayType <code>InstructionConstants.ARRAY_T_BOOLEAN</code>,
+ * <code>InstructionConstants.ARRAY_T_BYTE</code>,
+ * <code>InstructionConstants.ARRAY_T_CHAR</code>,
+ * <code>InstructionConstants.ARRAY_T_SHORT</code>,
+ * <code>InstructionConstants.ARRAY_T_INT</code>,
+ * <code>InstructionConstants.ARRAY_T_LONG</code>,
+ * <code>InstructionConstants.ARRAY_T_FLOAT</code>, or
+ * <code>InstructionConstants.ARRAY_T_DOUBLE</code>.
+ * @return <code>ClassConstants.TYPE_BOOLEAN</code>,
+ * <code>ClassConstants.TYPE_BYTE</code>,
+ * <code>ClassConstants.TYPE_CHAR</code>,
+ * <code>ClassConstants.TYPE_SHORT</code>,
+ * <code>ClassConstants.TYPE_INT</code>,
+ * <code>ClassConstants.TYPE_LONG</code>,
+ * <code>ClassConstants.TYPE_FLOAT</code>, or
+ * <code>ClassConstants.TYPE_DOUBLE</code>.
+ */
+ public static char internalTypeFromArrayType(byte arrayType)
+ {
+ switch (arrayType)
+ {
+ case InstructionConstants.ARRAY_T_BOOLEAN: return ClassConstants.TYPE_BOOLEAN;
+ case InstructionConstants.ARRAY_T_CHAR: return ClassConstants.TYPE_CHAR;
+ case InstructionConstants.ARRAY_T_FLOAT: return ClassConstants.TYPE_FLOAT;
+ case InstructionConstants.ARRAY_T_DOUBLE: return ClassConstants.TYPE_DOUBLE;
+ case InstructionConstants.ARRAY_T_BYTE: return ClassConstants.TYPE_BYTE;
+ case InstructionConstants.ARRAY_T_SHORT: return ClassConstants.TYPE_SHORT;
+ case InstructionConstants.ARRAY_T_INT: return ClassConstants.TYPE_INT;
+ case InstructionConstants.ARRAY_T_LONG: return ClassConstants.TYPE_LONG;
+ default: throw new IllegalArgumentException("Unknown array type ["+arrayType+"]");
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/LookUpSwitchInstruction.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/LookUpSwitchInstruction.java
new file mode 100644
index 0000000000..0533b08b0d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/LookUpSwitchInstruction.java
@@ -0,0 +1,135 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+
+/**
+ * This Instruction represents a simple instruction without variable arguments
+ * or constant pool references.
+ *
+ * @author Eric Lafortune
+ */
+public class LookUpSwitchInstruction extends SwitchInstruction
+{
+ public int[] cases;
+
+
+ /**
+ * Creates an uninitialized LookUpSwitchInstruction.
+ */
+ public LookUpSwitchInstruction() {}
+
+
+ /**
+ * Creates a new LookUpSwitchInstruction with the given arguments.
+ */
+ public LookUpSwitchInstruction(byte opcode,
+ int defaultOffset,
+ int[] cases,
+ int[] jumpOffsets)
+ {
+ this.opcode = opcode;
+ this.defaultOffset = defaultOffset;
+ this.cases = cases;
+ this.jumpOffsets = jumpOffsets;
+ }
+
+
+ /**
+ * Copies the given instruction into this instruction.
+ * @param lookUpSwitchInstruction the instruction to be copied.
+ * @return this instruction.
+ */
+ public LookUpSwitchInstruction copy(LookUpSwitchInstruction lookUpSwitchInstruction)
+ {
+ this.opcode = lookUpSwitchInstruction.opcode;
+ this.defaultOffset = lookUpSwitchInstruction.defaultOffset;
+ this.cases = lookUpSwitchInstruction.cases;
+ this.jumpOffsets = lookUpSwitchInstruction.jumpOffsets;
+
+ return this;
+ }
+
+
+ // Implementations for Instruction.
+
+ public Instruction shrink()
+ {
+ // There aren't any ways to shrink this instruction.
+ return this;
+ }
+
+ protected void readInfo(byte[] code, int offset)
+ {
+ // Skip up to three padding bytes.
+ offset += -offset & 3;
+
+ // Read the two 32-bit arguments.
+ defaultOffset = readInt(code, offset); offset += 4;
+ int jumpOffsetCount = readInt(code, offset); offset += 4;
+
+ // Read the matches-offset pairs.
+ cases = new int[jumpOffsetCount];
+ jumpOffsets = new int[jumpOffsetCount];
+
+ for (int index = 0; index < jumpOffsetCount; index++)
+ {
+ cases[index] = readInt(code, offset); offset += 4;
+ jumpOffsets[index] = readInt(code, offset); offset += 4;
+ }
+ }
+
+
+ protected void writeInfo(byte[] code, int offset)
+ {
+ // Write up to three padding bytes.
+ while ((offset & 3) != 0)
+ {
+ writeByte(code, offset++, 0);
+ }
+
+ // Write the two 32-bit arguments.
+ writeInt(code, offset, defaultOffset); offset += 4;
+ writeInt(code, offset, cases.length); offset += 4;
+
+ // Write the matches-offset pairs.
+ for (int index = 0; index < cases.length; index++)
+ {
+ writeInt(code, offset, cases[index]); offset += 4;
+ writeInt(code, offset, jumpOffsets[index]); offset += 4;
+ }
+ }
+
+
+ public int length(int offset)
+ {
+ return 1 + (-(offset+1) & 3) + 8 + cases.length * 8;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
+ {
+ instructionVisitor.visitLookUpSwitchInstruction(clazz, method, codeAttribute, offset, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/SimpleInstruction.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/SimpleInstruction.java
new file mode 100644
index 0000000000..1f3932f811
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/SimpleInstruction.java
@@ -0,0 +1,255 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+
+/**
+ * This Instruction represents a simple instruction without variable arguments
+ * or constant pool references.
+ *
+ * @author Eric Lafortune
+ */
+public class SimpleInstruction extends Instruction
+{
+ public int constant;
+
+
+ /**
+ * Creates an uninitialized SimpleInstruction.
+ */
+ public SimpleInstruction() {}
+
+
+ /**
+ * Creates a new SimpleInstruction with the given opcode.
+ */
+ public SimpleInstruction(byte opcode)
+ {
+ this(opcode, embeddedConstant(opcode));
+ }
+
+
+ /**
+ * Creates a new SimpleInstruction with the given opcode and constant.
+ */
+ public SimpleInstruction(byte opcode, int constant)
+ {
+ this.opcode = opcode;
+ this.constant = constant;
+ }
+
+
+ /**
+ * Copies the given instruction into this instruction.
+ * @param simpleInstruction the instruction to be copied.
+ * @return this instruction.
+ */
+ public SimpleInstruction copy(SimpleInstruction simpleInstruction)
+ {
+ this.opcode = simpleInstruction.opcode;
+ this.constant = simpleInstruction.constant;
+
+ return this;
+ }
+
+
+ /**
+ * Return the embedded constant of the given opcode, or 0 if the opcode
+ * doesn't have one.
+ */
+ private static int embeddedConstant(byte opcode)
+ {
+ switch (opcode)
+ {
+ case InstructionConstants.OP_ICONST_M1: return -1;
+
+ case InstructionConstants.OP_ICONST_1:
+ case InstructionConstants.OP_LCONST_1:
+ case InstructionConstants.OP_FCONST_1:
+ case InstructionConstants.OP_DCONST_1: return 1;
+
+ case InstructionConstants.OP_ICONST_2:
+ case InstructionConstants.OP_FCONST_2: return 2;
+
+ case InstructionConstants.OP_ICONST_3: return 3;
+
+ case InstructionConstants.OP_ICONST_4: return 4;
+
+ case InstructionConstants.OP_ICONST_5: return 5;
+
+ default: return 0;
+ }
+ }
+
+
+ // Implementations for Instruction.
+
+ public byte canonicalOpcode()
+ {
+ // Replace any _1, _2, _3,... extension by _0.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_ICONST_M1:
+ case InstructionConstants.OP_ICONST_0:
+ case InstructionConstants.OP_ICONST_1:
+ case InstructionConstants.OP_ICONST_2:
+ case InstructionConstants.OP_ICONST_3:
+ case InstructionConstants.OP_ICONST_4:
+ case InstructionConstants.OP_ICONST_5:
+ case InstructionConstants.OP_BIPUSH:
+ case InstructionConstants.OP_SIPUSH: return InstructionConstants.OP_ICONST_0;
+
+ case InstructionConstants.OP_LCONST_0:
+ case InstructionConstants.OP_LCONST_1: return InstructionConstants.OP_LCONST_0;
+
+ case InstructionConstants.OP_FCONST_0:
+ case InstructionConstants.OP_FCONST_1:
+ case InstructionConstants.OP_FCONST_2: return InstructionConstants.OP_FCONST_0;
+
+ case InstructionConstants.OP_DCONST_0:
+ case InstructionConstants.OP_DCONST_1: return InstructionConstants.OP_DCONST_0;
+
+ default: return opcode;
+ }
+ }
+
+ public Instruction shrink()
+ {
+ // Reconstruct the opcode of the shortest instruction, if there are
+ // any alternatives.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_ICONST_M1:
+ case InstructionConstants.OP_ICONST_0:
+ case InstructionConstants.OP_ICONST_1:
+ case InstructionConstants.OP_ICONST_2:
+ case InstructionConstants.OP_ICONST_3:
+ case InstructionConstants.OP_ICONST_4:
+ case InstructionConstants.OP_ICONST_5:
+ case InstructionConstants.OP_BIPUSH:
+ case InstructionConstants.OP_SIPUSH:
+ switch (requiredConstantSize())
+ {
+ case 0:
+ opcode = (byte)(InstructionConstants.OP_ICONST_0 + constant);
+ break;
+ case 1:
+ opcode = InstructionConstants.OP_BIPUSH;
+ break;
+ case 2:
+ opcode = InstructionConstants.OP_SIPUSH;
+ break;
+ }
+ break;
+
+ case InstructionConstants.OP_LCONST_0:
+ case InstructionConstants.OP_LCONST_1:
+ opcode = (byte)(InstructionConstants.OP_LCONST_0 + constant);
+ break;
+
+ case InstructionConstants.OP_FCONST_0:
+ case InstructionConstants.OP_FCONST_1:
+ case InstructionConstants.OP_FCONST_2:
+ opcode = (byte)(InstructionConstants.OP_FCONST_0 + constant);
+ break;
+
+ case InstructionConstants.OP_DCONST_0:
+ case InstructionConstants.OP_DCONST_1:
+ opcode = (byte)(InstructionConstants.OP_DCONST_0 + constant);
+ break;
+ }
+
+ return this;
+ }
+
+ protected void readInfo(byte[] code, int offset)
+ {
+ int constantSize = constantSize();
+
+ // Also initialize embedded constants that are different from 0.
+ constant = constantSize == 0 ?
+ embeddedConstant(opcode) :
+ readSignedValue(code, offset, constantSize);
+ }
+
+
+ protected void writeInfo(byte[] code, int offset)
+ {
+ int constantSize = constantSize();
+
+ if (requiredConstantSize() > constantSize)
+ {
+ throw new IllegalArgumentException("Instruction has invalid constant size ("+this.toString(offset)+")");
+ }
+
+ writeSignedValue(code, offset, constant, constantSize);
+ }
+
+
+ public int length(int offset)
+ {
+ return 1 + constantSize();
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
+ {
+ instructionVisitor.visitSimpleInstruction(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return getName() +
+ (constantSize() > 0 ? " "+constant : "");
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the constant size for this instruction.
+ */
+ private int constantSize()
+ {
+ return opcode == InstructionConstants.OP_BIPUSH ||
+ opcode == InstructionConstants.OP_NEWARRAY ? 1 :
+ opcode == InstructionConstants.OP_SIPUSH ? 2 :
+ 0;
+ }
+
+
+ /**
+ * Computes the required constant size for this instruction.
+ */
+ private int requiredConstantSize()
+ {
+ return constant >= -1 && constant <= 5 ? 0 :
+ (byte)constant == constant ? 1 :
+ (short)constant == constant ? 2 :
+ 4;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/SwitchInstruction.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/SwitchInstruction.java
new file mode 100644
index 0000000000..d2a138c892
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/SwitchInstruction.java
@@ -0,0 +1,83 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction;
+
+/**
+ * This Instruction represents a simple instruction without variable arguments
+ * or constant pool references.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class SwitchInstruction extends Instruction
+{
+ public int defaultOffset;
+ public int[] jumpOffsets;
+
+
+ /**
+ * Creates an uninitialized SwitchInstruction.
+ */
+ public SwitchInstruction() {}
+
+
+ /**
+ * Creates a new SwitchInstruction with the given arguments.
+ */
+ public SwitchInstruction(byte opcode,
+ int defaultOffset,
+ int[] jumpOffsets)
+ {
+ this.opcode = opcode;
+ this.defaultOffset = defaultOffset;
+ this.jumpOffsets = jumpOffsets;
+ }
+
+
+ /**
+ * Copies the given instruction into this instruction.
+ * @param switchInstruction the instruction to be copied.
+ * @return this instruction.
+ */
+ public SwitchInstruction copy(SwitchInstruction switchInstruction)
+ {
+ this.opcode = switchInstruction.opcode;
+ this.defaultOffset = switchInstruction.defaultOffset;
+ this.jumpOffsets = switchInstruction.jumpOffsets;
+
+ return this;
+ }
+
+
+ // Implementations for Instruction.
+
+ public String toString(int offset)
+ {
+ return "["+offset+"] "+toString()+" (target="+(offset+defaultOffset)+")";
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return getName()+" ("+jumpOffsets.length+" offsets, default="+defaultOffset+")";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/TableSwitchInstruction.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/TableSwitchInstruction.java
new file mode 100644
index 0000000000..1231fe8935
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/TableSwitchInstruction.java
@@ -0,0 +1,139 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+
+/**
+ * This Instruction represents a simple instruction without variable arguments
+ * or constant pool references.
+ *
+ * @author Eric Lafortune
+ */
+public class TableSwitchInstruction extends SwitchInstruction
+{
+ public int lowCase;
+ public int highCase;
+
+
+ /**
+ * Creates an uninitialized TableSwitchInstruction.
+ */
+ public TableSwitchInstruction() {}
+
+
+ /**
+ * Creates a new TableSwitchInstruction with the given arguments.
+ */
+ public TableSwitchInstruction(byte opcode,
+ int defaultOffset,
+ int lowCase,
+ int highCase,
+ int[] jumpOffsets)
+ {
+ this.opcode = opcode;
+ this.defaultOffset = defaultOffset;
+ this.lowCase = lowCase;
+ this.highCase = highCase;
+ this.jumpOffsets = jumpOffsets;
+ }
+
+
+ /**
+ * Copies the given instruction into this instruction.
+ * @param tableSwitchInstruction the instruction to be copied.
+ * @return this instruction.
+ */
+ public TableSwitchInstruction copy(TableSwitchInstruction tableSwitchInstruction)
+ {
+ this.opcode = tableSwitchInstruction.opcode;
+ this.defaultOffset = tableSwitchInstruction.defaultOffset;
+ this.lowCase = tableSwitchInstruction.lowCase;
+ this.highCase = tableSwitchInstruction.highCase;
+ this.jumpOffsets = tableSwitchInstruction.jumpOffsets;
+
+ return this;
+ }
+
+
+ // Implementations for Instruction.
+
+ public Instruction shrink()
+ {
+ // There aren't any ways to shrink this instruction.
+ return this;
+ }
+
+ protected void readInfo(byte[] code, int offset)
+ {
+ // Skip up to three padding bytes.
+ offset += -offset & 3;
+
+ // Read the three 32-bit arguments.
+ defaultOffset = readInt(code, offset); offset += 4;
+ lowCase = readInt(code, offset); offset += 4;
+ highCase = readInt(code, offset); offset += 4;
+
+ // Read the jump offsets.
+ jumpOffsets = new int[highCase - lowCase + 1];
+
+ for (int index = 0; index < jumpOffsets.length; index++)
+ {
+ jumpOffsets[index] = readInt(code, offset); offset += 4;
+ }
+ }
+
+
+ protected void writeInfo(byte[] code, int offset)
+ {
+ // Write up to three padding bytes.
+ while ((offset & 3) != 0)
+ {
+ writeByte(code, offset++, 0);
+ }
+
+ // Write the three 32-bit arguments.
+ writeInt(code, offset, defaultOffset); offset += 4;
+ writeInt(code, offset, lowCase); offset += 4;
+ writeInt(code, offset, highCase); offset += 4;
+
+ // Write the jump offsets.
+ int length = highCase - lowCase + 1;
+ for (int index = 0; index < length; index++)
+ {
+ writeInt(code, offset, jumpOffsets[index]); offset += 4;
+ }
+ }
+
+
+ public int length(int offset)
+ {
+ return 1 + (-(offset+1) & 3) + 12 + (highCase - lowCase + 1) * 4;
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
+ {
+ instructionVisitor.visitTableSwitchInstruction(clazz, method, codeAttribute, offset, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/VariableInstruction.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/VariableInstruction.java
new file mode 100644
index 0000000000..dd232cc589
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/VariableInstruction.java
@@ -0,0 +1,372 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+
+/**
+ * This Instruction represents an instruction that refers to a variable on the
+ * local variable stack.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableInstruction extends Instruction
+{
+ public boolean wide;
+ public int variableIndex;
+ public int constant;
+
+
+ /**
+ * Creates an uninitialized VariableInstruction.
+ */
+ public VariableInstruction() {}
+
+
+ public VariableInstruction(boolean wide)
+ {
+ this.wide = wide;
+ }
+
+
+ public VariableInstruction(byte opcode)
+ {
+ this(opcode, embeddedVariable(opcode), 0);
+ }
+
+
+ public VariableInstruction(byte opcode,
+ int variableIndex)
+ {
+ this(opcode, variableIndex, 0);
+ }
+
+
+ public VariableInstruction(byte opcode,
+ int variableIndex,
+ int constant)
+ {
+ this.opcode = opcode;
+ this.variableIndex = variableIndex;
+ this.constant = constant;
+ this.wide = requiredVariableIndexSize() > 1 ||
+ requiredConstantSize() > 1;
+ }
+
+
+ /**
+ * Copies the given instruction into this instruction.
+ * @param variableInstruction the instruction to be copied.
+ * @return this instruction.
+ */
+ public VariableInstruction copy(VariableInstruction variableInstruction)
+ {
+ this.opcode = variableInstruction.opcode;
+ this.variableIndex = variableInstruction.variableIndex;
+ this.constant = variableInstruction.constant;
+ this.wide = variableInstruction.wide;
+
+ return this;
+ }
+
+
+ /**
+ * Return the embedded variable of the given opcode, or 0 if the opcode
+ * doesn't have one.
+ */
+ private static int embeddedVariable(byte opcode)
+ {
+ switch (opcode)
+ {
+ case InstructionConstants.OP_ILOAD_1:
+ case InstructionConstants.OP_LLOAD_1:
+ case InstructionConstants.OP_FLOAD_1:
+ case InstructionConstants.OP_DLOAD_1:
+ case InstructionConstants.OP_ALOAD_1:
+ case InstructionConstants.OP_ISTORE_1:
+ case InstructionConstants.OP_LSTORE_1:
+ case InstructionConstants.OP_FSTORE_1:
+ case InstructionConstants.OP_DSTORE_1:
+ case InstructionConstants.OP_ASTORE_1: return 1;
+
+ case InstructionConstants.OP_ILOAD_2:
+ case InstructionConstants.OP_LLOAD_2:
+ case InstructionConstants.OP_FLOAD_2:
+ case InstructionConstants.OP_DLOAD_2:
+ case InstructionConstants.OP_ALOAD_2:
+ case InstructionConstants.OP_ISTORE_2:
+ case InstructionConstants.OP_LSTORE_2:
+ case InstructionConstants.OP_FSTORE_2:
+ case InstructionConstants.OP_DSTORE_2:
+ case InstructionConstants.OP_ASTORE_2: return 2;
+
+ case InstructionConstants.OP_ILOAD_3:
+ case InstructionConstants.OP_LLOAD_3:
+ case InstructionConstants.OP_FLOAD_3:
+ case InstructionConstants.OP_DLOAD_3:
+ case InstructionConstants.OP_ALOAD_3:
+ case InstructionConstants.OP_ISTORE_3:
+ case InstructionConstants.OP_LSTORE_3:
+ case InstructionConstants.OP_FSTORE_3:
+ case InstructionConstants.OP_DSTORE_3:
+ case InstructionConstants.OP_ASTORE_3: return 3;
+
+ default: return 0;
+ }
+ }
+
+
+ /**
+ * Returns whether this instruction stores the value of a variable.
+ * The value is false for the ret instruction, but true for the iinc
+ * instruction.
+ */
+ public boolean isStore()
+ {
+ // A store instruction can be recognized as follows. Note that this
+ // excludes the ret instruction, which has a negative opcode.
+ return opcode >= InstructionConstants.OP_ISTORE ||
+ opcode == InstructionConstants.OP_IINC;
+ }
+
+
+ /**
+ * Returns whether this instruction loads the value of a variable.
+ * The value is true for the ret instruction and for the iinc
+ * instruction.
+ */
+ public boolean isLoad()
+ {
+ // A load instruction can be recognized as follows. Note that this
+ // includes the ret instruction, which has a negative opcode.
+ return opcode < InstructionConstants.OP_ISTORE;
+ }
+
+
+ // Implementations for Instruction.
+
+ public byte canonicalOpcode()
+ {
+ // Remove the _0, _1, _2, _3 extension, if any.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_ILOAD_0:
+ case InstructionConstants.OP_ILOAD_1:
+ case InstructionConstants.OP_ILOAD_2:
+ case InstructionConstants.OP_ILOAD_3: return InstructionConstants.OP_ILOAD;
+ case InstructionConstants.OP_LLOAD_0:
+ case InstructionConstants.OP_LLOAD_1:
+ case InstructionConstants.OP_LLOAD_2:
+ case InstructionConstants.OP_LLOAD_3: return InstructionConstants.OP_LLOAD;
+ case InstructionConstants.OP_FLOAD_0:
+ case InstructionConstants.OP_FLOAD_1:
+ case InstructionConstants.OP_FLOAD_2:
+ case InstructionConstants.OP_FLOAD_3: return InstructionConstants.OP_FLOAD;
+ case InstructionConstants.OP_DLOAD_0:
+ case InstructionConstants.OP_DLOAD_1:
+ case InstructionConstants.OP_DLOAD_2:
+ case InstructionConstants.OP_DLOAD_3: return InstructionConstants.OP_DLOAD;
+ case InstructionConstants.OP_ALOAD_0:
+ case InstructionConstants.OP_ALOAD_1:
+ case InstructionConstants.OP_ALOAD_2:
+ case InstructionConstants.OP_ALOAD_3: return InstructionConstants.OP_ALOAD;
+
+ case InstructionConstants.OP_ISTORE_0:
+ case InstructionConstants.OP_ISTORE_1:
+ case InstructionConstants.OP_ISTORE_2:
+ case InstructionConstants.OP_ISTORE_3: return InstructionConstants.OP_ISTORE;
+ case InstructionConstants.OP_LSTORE_0:
+ case InstructionConstants.OP_LSTORE_1:
+ case InstructionConstants.OP_LSTORE_2:
+ case InstructionConstants.OP_LSTORE_3: return InstructionConstants.OP_LSTORE;
+ case InstructionConstants.OP_FSTORE_0:
+ case InstructionConstants.OP_FSTORE_1:
+ case InstructionConstants.OP_FSTORE_2:
+ case InstructionConstants.OP_FSTORE_3: return InstructionConstants.OP_FSTORE;
+ case InstructionConstants.OP_DSTORE_0:
+ case InstructionConstants.OP_DSTORE_1:
+ case InstructionConstants.OP_DSTORE_2:
+ case InstructionConstants.OP_DSTORE_3: return InstructionConstants.OP_DSTORE;
+ case InstructionConstants.OP_ASTORE_0:
+ case InstructionConstants.OP_ASTORE_1:
+ case InstructionConstants.OP_ASTORE_2:
+ case InstructionConstants.OP_ASTORE_3: return InstructionConstants.OP_ASTORE;
+
+ default: return opcode;
+ }
+ }
+
+ public Instruction shrink()
+ {
+ opcode = canonicalOpcode();
+
+ // Is this instruction pointing to a variable with index from 0 to 3?
+ if (variableIndex <= 3)
+ {
+ switch (opcode)
+ {
+ case InstructionConstants.OP_ILOAD: opcode = (byte)(InstructionConstants.OP_ILOAD_0 + variableIndex); break;
+ case InstructionConstants.OP_LLOAD: opcode = (byte)(InstructionConstants.OP_LLOAD_0 + variableIndex); break;
+ case InstructionConstants.OP_FLOAD: opcode = (byte)(InstructionConstants.OP_FLOAD_0 + variableIndex); break;
+ case InstructionConstants.OP_DLOAD: opcode = (byte)(InstructionConstants.OP_DLOAD_0 + variableIndex); break;
+ case InstructionConstants.OP_ALOAD: opcode = (byte)(InstructionConstants.OP_ALOAD_0 + variableIndex); break;
+
+ case InstructionConstants.OP_ISTORE: opcode = (byte)(InstructionConstants.OP_ISTORE_0 + variableIndex); break;
+ case InstructionConstants.OP_LSTORE: opcode = (byte)(InstructionConstants.OP_LSTORE_0 + variableIndex); break;
+ case InstructionConstants.OP_FSTORE: opcode = (byte)(InstructionConstants.OP_FSTORE_0 + variableIndex); break;
+ case InstructionConstants.OP_DSTORE: opcode = (byte)(InstructionConstants.OP_DSTORE_0 + variableIndex); break;
+ case InstructionConstants.OP_ASTORE: opcode = (byte)(InstructionConstants.OP_ASTORE_0 + variableIndex); break;
+ }
+ }
+
+ // Only make the instruction wide if necessary.
+ wide = requiredVariableIndexSize() > 1 ||
+ requiredConstantSize() > 1;
+
+ return this;
+ }
+
+
+ protected boolean isWide()
+ {
+ return wide;
+ }
+
+
+ protected void readInfo(byte[] code, int offset)
+ {
+ int variableIndexSize = variableIndexSize();
+ int constantSize = constantSize();
+
+ // Also initialize embedded variable indexes.
+ if (variableIndexSize == 0)
+ {
+ // An embedded variable index can be decoded as follows.
+ variableIndex = opcode < InstructionConstants.OP_ISTORE_0 ?
+ (opcode - InstructionConstants.OP_ILOAD_0 ) & 3 :
+ (opcode - InstructionConstants.OP_ISTORE_0) & 3;
+ }
+ else
+ {
+ variableIndex = readValue(code, offset, variableIndexSize); offset += variableIndexSize;
+ }
+
+ constant = readSignedValue(code, offset, constantSize);
+ }
+
+
+ protected void writeInfo(byte[] code, int offset)
+ {
+ int variableIndexSize = variableIndexSize();
+ int constantSize = constantSize();
+
+ if (requiredVariableIndexSize() > variableIndexSize)
+ {
+ throw new IllegalArgumentException("Instruction has invalid variable index size ("+this.toString(offset)+")");
+ }
+
+ if (requiredConstantSize() > constantSize)
+ {
+ throw new IllegalArgumentException("Instruction has invalid constant size ("+this.toString(offset)+")");
+ }
+
+ writeValue(code, offset, variableIndex, variableIndexSize); offset += variableIndexSize;
+ writeSignedValue(code, offset, constant, constantSize);
+ }
+
+
+ public int length(int offset)
+ {
+ return (wide ? 2 : 1) + variableIndexSize() + constantSize();
+ }
+
+
+ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
+ {
+ instructionVisitor.visitVariableInstruction(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return getName() +
+ (wide ? "_w" : "") +
+ " v"+variableIndex +
+ (constantSize() > 0 ? ", "+constant : "");
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the variable index size for this instruction.
+ */
+ private int variableIndexSize()
+ {
+ return (opcode >= InstructionConstants.OP_ILOAD_0 &&
+ opcode <= InstructionConstants.OP_ALOAD_3) ||
+ (opcode >= InstructionConstants.OP_ISTORE_0 &&
+ opcode <= InstructionConstants.OP_ASTORE_3) ? 0 :
+ wide ? 2 :
+ 1;
+ }
+
+
+ /**
+ * Computes the required variable index size for this instruction's variable
+ * index.
+ */
+ private int requiredVariableIndexSize()
+ {
+ return (variableIndex & 0x3) == variableIndex ? 0 :
+ (variableIndex & 0xff) == variableIndex ? 1 :
+ (variableIndex & 0xffff) == variableIndex ? 2 :
+ 4;
+
+ }
+
+
+ /**
+ * Returns the constant size for this instruction.
+ */
+ private int constantSize()
+ {
+ return opcode != InstructionConstants.OP_IINC ? 0 :
+ wide ? 2 :
+ 1;
+ }
+
+
+ /**
+ * Computes the required constant size for this instruction's constant.
+ */
+ private int requiredConstantSize()
+ {
+ return opcode != InstructionConstants.OP_IINC ? 0 :
+ (byte)constant == constant ? 1 :
+ (short)constant == constant ? 2 :
+ 4;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/package.html
new file mode 100644
index 0000000000..48c234e3c4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/package.html
@@ -0,0 +1,9 @@
+<body>
+This package contains classes to represent Java bytecode instructions.
+<p>
+Not every instruction currently has its own class. Only groups of instructions
+that refer to the constant pool get their own representations.
+<p>
+While the package is sufficient for the current needs of the ProGuard
+application, it may very well be reorganised and extended in the future.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
new file mode 100644
index 0000000000..b06b957fb7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
@@ -0,0 +1,56 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given InstructionVisitor visit all Instruction
+ * objects of the CodeAttribute objects it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllInstructionVisitor
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final InstructionVisitor instructionVisitor;
+
+
+ public AllInstructionVisitor(InstructionVisitor instructionVisitor)
+ {
+ this.instructionVisitor = instructionVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.instructionsAccept(clazz, method, instructionVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java
new file mode 100644
index 0000000000..439c635311
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor lets a given ConstantVisitor visit all constants
+ * of the instructions it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class InstructionConstantVisitor
+extends SimplifiedVisitor
+implements InstructionVisitor
+{
+ private final ConstantVisitor constantVisitor;
+
+
+ /**
+ * Creates a new InstructionConstantVisitor.
+ * @param constantVisitor the ConstantVisitor to which visits will be
+ * delegated.
+ */
+ public InstructionConstantVisitor(ConstantVisitor constantVisitor)
+ {
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ constantVisitor);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionCounter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionCounter.java
new file mode 100644
index 0000000000..a67b5f35b6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionCounter.java
@@ -0,0 +1,59 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.Instruction;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor counts the number of instructions that has been visited.
+ *
+ * @author Eric Lafortune
+ */
+public class InstructionCounter
+extends SimplifiedVisitor
+implements InstructionVisitor
+{
+ private int count;
+
+
+ /**
+ * Returns the number of instructions that has been visited so far.
+ */
+ public int getCount()
+ {
+ return count;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int offset,
+ Instruction instruction)
+ {
+ count++;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionVisitor.java
new file mode 100644
index 0000000000..37596dd7b1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/InstructionVisitor.java
@@ -0,0 +1,42 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.*;
+
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>Instruction</code> objects.
+ *
+ * @author Eric Lafortune
+ */
+public interface InstructionVisitor
+{
+ public void visitSimpleInstruction( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction);
+ public void visitVariableInstruction( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction);
+ public void visitConstantInstruction( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction);
+ public void visitBranchInstruction( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction);
+ public void visitTableSwitchInstruction( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction);
+ public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java
new file mode 100644
index 0000000000..a4be5409cb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java
@@ -0,0 +1,131 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.instruction.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.*;
+
+
+/**
+ * This InstructionVisitor delegates all visits to each InstructionVisitor
+ * in a given list.
+ *
+ * @author Eric Lafortune
+ */
+public class MultiInstructionVisitor implements InstructionVisitor
+{
+ private static final int ARRAY_SIZE_INCREMENT = 5;
+
+
+ private InstructionVisitor[] instructionVisitors;
+ private int instructionVisitorCount;
+
+
+ public MultiInstructionVisitor()
+ {
+ }
+
+
+ public MultiInstructionVisitor(InstructionVisitor[] instructionVisitors)
+ {
+ this.instructionVisitors = instructionVisitors;
+ this.instructionVisitorCount = instructionVisitors.length;
+ }
+
+
+ public void addInstructionVisitor(InstructionVisitor instructionVisitor)
+ {
+ ensureArraySize();
+
+ instructionVisitors[instructionVisitorCount++] = instructionVisitor;
+ }
+
+
+ private void ensureArraySize()
+ {
+ if (instructionVisitors == null)
+ {
+ instructionVisitors = new InstructionVisitor[ARRAY_SIZE_INCREMENT];
+ }
+ else if (instructionVisitors.length == instructionVisitorCount)
+ {
+ InstructionVisitor[] newInstructionVisitors =
+ new InstructionVisitor[instructionVisitorCount +
+ ARRAY_SIZE_INCREMENT];
+ System.arraycopy(instructionVisitors, 0,
+ newInstructionVisitors, 0,
+ instructionVisitorCount);
+ instructionVisitors = newInstructionVisitors;
+ }
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ for (int index = 0; index < instructionVisitorCount; index++)
+ {
+ instructionVisitors[index].visitSimpleInstruction(clazz, method, codeAttribute, offset, simpleInstruction);
+ }
+ }
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ for (int index = 0; index < instructionVisitorCount; index++)
+ {
+ instructionVisitors[index].visitVariableInstruction(clazz, method, codeAttribute, offset, variableInstruction);
+ }
+ }
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ for (int index = 0; index < instructionVisitorCount; index++)
+ {
+ instructionVisitors[index].visitConstantInstruction(clazz, method, codeAttribute, offset, constantInstruction);
+ }
+ }
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ for (int index = 0; index < instructionVisitorCount; index++)
+ {
+ instructionVisitors[index].visitBranchInstruction(clazz, method, codeAttribute, offset, branchInstruction);
+ }
+ }
+
+ public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
+ {
+ for (int index = 0; index < instructionVisitorCount; index++)
+ {
+ instructionVisitors[index].visitTableSwitchInstruction(clazz, method, codeAttribute, offset, tableSwitchInstruction);
+ }
+ }
+
+ public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
+ {
+ for (int index = 0; index < instructionVisitorCount; index++)
+ {
+ instructionVisitors[index].visitLookUpSwitchInstruction(clazz, method, codeAttribute, offset, lookUpSwitchInstruction);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/package.html
new file mode 100644
index 0000000000..a31a4082fa
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/instruction/visitor/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains visitors for instructions.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/LibraryClassReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/LibraryClassReader.java
new file mode 100644
index 0000000000..f14d49838f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/LibraryClassReader.java
@@ -0,0 +1,383 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.io;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+import java.io.DataInput;
+
+/**
+ * This ClassVisitor fills out the LibraryClass objects that it visits with data
+ * from the given DataInput object.
+ *
+ * @author Eric Lafortune
+ */
+public class LibraryClassReader
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ ConstantVisitor
+{
+ private static final LibraryField[] EMPTY_LIBRARY_FIELDS = new LibraryField[0];
+ private static final LibraryMethod[] EMPTY_LIBRARY_METHODS = new LibraryMethod[0];
+
+
+ private final RuntimeDataInput dataInput;
+ private final boolean skipNonPublicClasses;
+ private final boolean skipNonPublicClassMembers;
+
+ // A global array that acts as a parameter for the visitor methods.
+ private Constant[] constantPool;
+
+
+ /**
+ * Creates a new ProgramClassReader for reading from the given DataInput.
+ */
+ public LibraryClassReader(DataInput dataInput,
+ boolean skipNonPublicClasses,
+ boolean skipNonPublicClassMembers)
+ {
+ this.dataInput = new RuntimeDataInput(dataInput);
+ this.skipNonPublicClasses = skipNonPublicClasses;
+ this.skipNonPublicClassMembers = skipNonPublicClassMembers;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass libraryClass)
+ {
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Read and check the magic number.
+ int u4magic = dataInput.readInt();
+
+ ClassUtil.checkMagicNumber(u4magic);
+
+ // Read and check the version numbers.
+ int u2minorVersion = dataInput.readUnsignedShort();
+ int u2majorVersion = dataInput.readUnsignedShort();
+
+ int u4version = ClassUtil.internalClassVersion(u2majorVersion,
+ u2minorVersion);
+
+ ClassUtil.checkVersionNumbers(u4version);
+
+ // Read the constant pool. Note that the first entry is not used.
+ int u2constantPoolCount = dataInput.readUnsignedShort();
+
+ // Create the constant pool array.
+ constantPool = new Constant[u2constantPoolCount];
+
+ for (int index = 1; index < u2constantPoolCount; index++)
+ {
+ Constant constant = createConstant();
+ constant.accept(libraryClass, this);
+
+ int tag = constant.getTag();
+ if (tag == ClassConstants.CONSTANT_Class ||
+ tag == ClassConstants.CONSTANT_Utf8)
+ {
+ constantPool[index] = constant;
+ }
+
+ // Long constants and double constants take up two entries in the
+ // constant pool.
+ if (tag == ClassConstants.CONSTANT_Long ||
+ tag == ClassConstants.CONSTANT_Double)
+ {
+ index++;
+ }
+ }
+
+ // Read the general class information.
+ libraryClass.u2accessFlags = dataInput.readUnsignedShort();
+
+ // We may stop parsing this library class if it's not public anyway.
+ // E.g. only about 60% of all rt.jar classes need to be parsed.
+ if (skipNonPublicClasses &&
+ AccessUtil.accessLevel(libraryClass.getAccessFlags()) < AccessUtil.PUBLIC)
+ {
+ return;
+ }
+
+ // Read the class and super class indices.
+ int u2thisClass = dataInput.readUnsignedShort();
+ int u2superClass = dataInput.readUnsignedShort();
+
+ // Store their actual names.
+ libraryClass.thisClassName = getClassName(u2thisClass);
+ libraryClass.superClassName = (u2superClass == 0) ? null :
+ getClassName(u2superClass);
+
+ // Read the interfaces
+ int u2interfacesCount = dataInput.readUnsignedShort();
+
+ libraryClass.interfaceNames = new String[u2interfacesCount];
+ for (int index = 0; index < u2interfacesCount; index++)
+ {
+ // Store the actual interface name.
+ int u2interface = dataInput.readUnsignedShort();
+ libraryClass.interfaceNames[index] = getClassName(u2interface);
+ }
+
+ // Read the fields.
+ int u2fieldsCount = dataInput.readUnsignedShort();
+
+ // Create the fields array.
+ LibraryField[] reusableFields = new LibraryField[u2fieldsCount];
+
+ int visibleFieldsCount = 0;
+ for (int index = 0; index < u2fieldsCount; index++)
+ {
+ LibraryField field = new LibraryField();
+ this.visitLibraryMember(libraryClass, field);
+
+ // Only store fields that are visible.
+ if (AccessUtil.accessLevel(field.getAccessFlags()) >=
+ (skipNonPublicClassMembers ? AccessUtil.PROTECTED :
+ AccessUtil.PACKAGE_VISIBLE))
+ {
+ reusableFields[visibleFieldsCount++] = field;
+ }
+ }
+
+ // Copy the visible fields (if any) into a fields array of the right size.
+ if (visibleFieldsCount == 0)
+ {
+ libraryClass.fields = EMPTY_LIBRARY_FIELDS;
+ }
+ else
+ {
+ libraryClass.fields = new LibraryField[visibleFieldsCount];
+ System.arraycopy(reusableFields, 0, libraryClass.fields, 0, visibleFieldsCount);
+ }
+
+ // Read the methods.
+ int u2methodsCount = dataInput.readUnsignedShort();
+
+ // Create the methods array.
+ LibraryMethod[] reusableMethods = new LibraryMethod[u2methodsCount];
+
+ int visibleMethodsCount = 0;
+ for (int index = 0; index < u2methodsCount; index++)
+ {
+ LibraryMethod method = new LibraryMethod();
+ this.visitLibraryMember(libraryClass, method);
+
+ // Only store methods that are visible.
+ if (AccessUtil.accessLevel(method.getAccessFlags()) >=
+ (skipNonPublicClassMembers ? AccessUtil.PROTECTED :
+ AccessUtil.PACKAGE_VISIBLE))
+ {
+ reusableMethods[visibleMethodsCount++] = method;
+ }
+ }
+
+ // Copy the visible methods (if any) into a methods array of the right size.
+ if (visibleMethodsCount == 0)
+ {
+ libraryClass.methods = EMPTY_LIBRARY_METHODS;
+ }
+ else
+ {
+ libraryClass.methods = new LibraryMethod[visibleMethodsCount];
+ System.arraycopy(reusableMethods, 0, libraryClass.methods, 0, visibleMethodsCount);
+ }
+
+ // Skip the class attributes.
+ skipAttributes();
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass libraryClass, ProgramMember libraryMember)
+ {
+ }
+
+
+ public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)
+ {
+ // Read the general field information.
+ libraryMember.u2accessFlags = dataInput.readUnsignedShort();
+ libraryMember.name = getString(dataInput.readUnsignedShort());
+ libraryMember.descriptor = getString(dataInput.readUnsignedShort());
+
+ // Skip the field attributes.
+ skipAttributes();
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ dataInput.skipBytes(4);
+ }
+
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ dataInput.skipBytes(8);
+ }
+
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ dataInput.skipBytes(4);
+ }
+
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ dataInput.skipBytes(8);
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ dataInput.skipBytes(2);
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ int u2length = dataInput.readUnsignedShort();
+
+ // Read the UTF-8 bytes.
+ byte[] bytes = new byte[u2length];
+ dataInput.readFully(bytes);
+ utf8Constant.setBytes(bytes);
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ dataInput.skipBytes(4);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ dataInput.skipBytes(3);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ dataInput.skipBytes(4);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.u2nameIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ dataInput.skipBytes(2);
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ dataInput.skipBytes(4);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the class name of the ClassConstant at the specified index in the
+ * reusable constant pool.
+ */
+ private String getClassName(int constantIndex)
+ {
+ ClassConstant classEntry = (ClassConstant)constantPool[constantIndex];
+
+ return getString(classEntry.u2nameIndex);
+ }
+
+
+ /**
+ * Returns the string of the Utf8Constant at the specified index in the
+ * reusable constant pool.
+ */
+ private String getString(int constantIndex)
+ {
+ return ((Utf8Constant)constantPool[constantIndex]).getString();
+ }
+
+
+ private Constant createConstant()
+ {
+ int u1tag = dataInput.readUnsignedByte();
+
+ switch (u1tag)
+ {
+ case ClassConstants.CONSTANT_Integer: return new IntegerConstant();
+ case ClassConstants.CONSTANT_Float: return new FloatConstant();
+ case ClassConstants.CONSTANT_Long: return new LongConstant();
+ case ClassConstants.CONSTANT_Double: return new DoubleConstant();
+ case ClassConstants.CONSTANT_String: return new StringConstant();
+ case ClassConstants.CONSTANT_Utf8: return new Utf8Constant();
+ case ClassConstants.CONSTANT_InvokeDynamic: return new InvokeDynamicConstant();
+ case ClassConstants.CONSTANT_MethodHandle: return new MethodHandleConstant();
+ case ClassConstants.CONSTANT_Fieldref: return new FieldrefConstant();
+ case ClassConstants.CONSTANT_Methodref: return new MethodrefConstant();
+ case ClassConstants.CONSTANT_InterfaceMethodref: return new InterfaceMethodrefConstant();
+ case ClassConstants.CONSTANT_Class: return new ClassConstant();
+ case ClassConstants.CONSTANT_MethodType: return new MethodTypeConstant();
+ case ClassConstants.CONSTANT_NameAndType: return new NameAndTypeConstant();
+
+ default: throw new RuntimeException("Unknown constant type ["+u1tag+"] in constant pool");
+ }
+ }
+
+
+ private void skipAttributes()
+ {
+ int u2attributesCount = dataInput.readUnsignedShort();
+
+ for (int index = 0; index < u2attributesCount; index++)
+ {
+ skipAttribute();
+ }
+ }
+
+
+ private void skipAttribute()
+ {
+ dataInput.skipBytes(2);
+ int u4attributeLength = dataInput.readInt();
+ dataInput.skipBytes(u4attributeLength);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/ProgramClassReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/ProgramClassReader.java
new file mode 100644
index 0000000000..5a02a8c832
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/ProgramClassReader.java
@@ -0,0 +1,1118 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.io;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.target.*;
+import proguard.classfile.attribute.annotation.target.visitor.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+import java.io.DataInput;
+
+/**
+ * This ClassVisitor fills out the ProgramClass objects that it visits with data
+ * from the given DataInput object.
+ *
+ * @author Eric Lafortune
+ */
+public class ProgramClassReader
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ ConstantVisitor,
+ AttributeVisitor,
+ BootstrapMethodInfoVisitor,
+ InnerClassesInfoVisitor,
+ ExceptionInfoVisitor,
+ StackMapFrameVisitor,
+ VerificationTypeVisitor,
+ LineNumberInfoVisitor,
+ ParameterInfoVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ TypeAnnotationVisitor,
+ TargetInfoVisitor,
+ TypePathInfoVisitor,
+ LocalVariableTargetElementVisitor,
+ ElementValueVisitor
+{
+ private final RuntimeDataInput dataInput;
+
+
+ /**
+ * Creates a new ProgramClassReader for reading from the given DataInput.
+ */
+ public ProgramClassReader(DataInput dataInput)
+ {
+ this.dataInput = new RuntimeDataInput(dataInput);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Read and check the magic number.
+ programClass.u4magic = dataInput.readInt();
+
+ ClassUtil.checkMagicNumber(programClass.u4magic);
+
+ // Read and check the version numbers.
+ int u2minorVersion = dataInput.readUnsignedShort();
+ int u2majorVersion = dataInput.readUnsignedShort();
+
+ programClass.u4version = ClassUtil.internalClassVersion(u2majorVersion,
+ u2minorVersion);
+
+ ClassUtil.checkVersionNumbers(programClass.u4version);
+
+ // Read the constant pool. Note that the first entry is not used.
+ programClass.u2constantPoolCount = dataInput.readUnsignedShort();
+
+ programClass.constantPool = new Constant[programClass.u2constantPoolCount];
+ for (int index = 1; index < programClass.u2constantPoolCount; index++)
+ {
+ Constant constant = createConstant();
+ constant.accept(programClass, this);
+ programClass.constantPool[index] = constant;
+
+ // Long constants and double constants take up two entries in the
+ // constant pool.
+ int tag = constant.getTag();
+ if (tag == ClassConstants.CONSTANT_Long ||
+ tag == ClassConstants.CONSTANT_Double)
+ {
+ programClass.constantPool[++index] = null;
+ }
+ }
+
+ // Read the general class information.
+ programClass.u2accessFlags = dataInput.readUnsignedShort();
+ programClass.u2thisClass = dataInput.readUnsignedShort();
+ programClass.u2superClass = dataInput.readUnsignedShort();
+
+ // Read the interfaces.
+ programClass.u2interfacesCount = dataInput.readUnsignedShort();
+
+ programClass.u2interfaces = new int[programClass.u2interfacesCount];
+ for (int index = 0; index < programClass.u2interfacesCount; index++)
+ {
+ programClass.u2interfaces[index] = dataInput.readUnsignedShort();
+ }
+
+ // Read the fields.
+ programClass.u2fieldsCount = dataInput.readUnsignedShort();
+
+ programClass.fields = new ProgramField[programClass.u2fieldsCount];
+ for (int index = 0; index < programClass.u2fieldsCount; index++)
+ {
+ ProgramField programField = new ProgramField();
+ this.visitProgramField(programClass, programField);
+ programClass.fields[index] = programField;
+ }
+
+ // Read the methods.
+ programClass.u2methodsCount = dataInput.readUnsignedShort();
+
+ programClass.methods = new ProgramMethod[programClass.u2methodsCount];
+ for (int index = 0; index < programClass.u2methodsCount; index++)
+ {
+ ProgramMethod programMethod = new ProgramMethod();
+ this.visitProgramMethod(programClass, programMethod);
+ programClass.methods[index] = programMethod;
+ }
+
+ // Read the class attributes.
+ programClass.u2attributesCount = dataInput.readUnsignedShort();
+
+ programClass.attributes = new Attribute[programClass.u2attributesCount];
+ for (int index = 0; index < programClass.u2attributesCount; index++)
+ {
+ Attribute attribute = createAttribute(programClass);
+ attribute.accept(programClass, this);
+ programClass.attributes[index] = attribute;
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Read the general field information.
+ programField.u2accessFlags = dataInput.readUnsignedShort();
+ programField.u2nameIndex = dataInput.readUnsignedShort();
+ programField.u2descriptorIndex = dataInput.readUnsignedShort();
+
+ // Read the field attributes.
+ programField.u2attributesCount = dataInput.readUnsignedShort();
+
+ programField.attributes = new Attribute[programField.u2attributesCount];
+ for (int index = 0; index < programField.u2attributesCount; index++)
+ {
+ Attribute attribute = createAttribute(programClass);
+ attribute.accept(programClass, programField, this);
+ programField.attributes[index] = attribute;
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Read the general method information.
+ programMethod.u2accessFlags = dataInput.readUnsignedShort();
+ programMethod.u2nameIndex = dataInput.readUnsignedShort();
+ programMethod.u2descriptorIndex = dataInput.readUnsignedShort();
+
+ // Read the method attributes.
+ programMethod.u2attributesCount = dataInput.readUnsignedShort();
+
+ programMethod.attributes = new Attribute[programMethod.u2attributesCount];
+ for (int index = 0; index < programMethod.u2attributesCount; index++)
+ {
+ Attribute attribute = createAttribute(programClass);
+ attribute.accept(programClass, programMethod, this);
+ programMethod.attributes[index] = attribute;
+ }
+ }
+
+
+ public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)
+ {
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ integerConstant.u4value = dataInput.readInt();
+ }
+
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ longConstant.u8value = dataInput.readLong();
+ }
+
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ floatConstant.f4value = dataInput.readFloat();
+ }
+
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ doubleConstant.f8value = dataInput.readDouble();
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ stringConstant.u2stringIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ int u2length = dataInput.readUnsignedShort();
+
+ // Read the UTF-8 bytes.
+ byte[] bytes = new byte[u2length];
+ dataInput.readFully(bytes);
+ utf8Constant.setBytes(bytes);
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ invokeDynamicConstant.u2bootstrapMethodAttributeIndex = dataInput.readUnsignedShort();
+ invokeDynamicConstant.u2nameAndTypeIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ methodHandleConstant.u1referenceKind = dataInput.readUnsignedByte();
+ methodHandleConstant.u2referenceIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ refConstant.u2classIndex = dataInput.readUnsignedShort();
+ refConstant.u2nameAndTypeIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.u2nameIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ methodTypeConstant.u2descriptorIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ nameAndTypeConstant.u2nameIndex = dataInput.readUnsignedShort();
+ nameAndTypeConstant.u2descriptorIndex = dataInput.readUnsignedShort();
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ // Read the unknown information.
+ byte[] info = new byte[unknownAttribute.u4attributeLength];
+ dataInput.readFully(info);
+ unknownAttribute.info = info;
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Read the bootstrap methods.
+ bootstrapMethodsAttribute.u2bootstrapMethodsCount = dataInput.readUnsignedShort();
+
+ bootstrapMethodsAttribute.bootstrapMethods = new BootstrapMethodInfo[bootstrapMethodsAttribute.u2bootstrapMethodsCount];
+ for (int index = 0; index < bootstrapMethodsAttribute.u2bootstrapMethodsCount; index++)
+ {
+ BootstrapMethodInfo bootstrapMethodInfo = new BootstrapMethodInfo();
+ visitBootstrapMethodInfo(clazz, bootstrapMethodInfo);
+ bootstrapMethodsAttribute.bootstrapMethods[index] = bootstrapMethodInfo;
+ }
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ sourceFileAttribute.u2sourceFileIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ sourceDirAttribute.u2sourceDirIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ // Read the inner classes.
+ innerClassesAttribute.u2classesCount = dataInput.readUnsignedShort();
+
+ innerClassesAttribute.classes = new InnerClassesInfo[innerClassesAttribute.u2classesCount];
+ for (int index = 0; index < innerClassesAttribute.u2classesCount; index++)
+ {
+ InnerClassesInfo innerClassesInfo = new InnerClassesInfo();
+ visitInnerClassesInfo(clazz, innerClassesInfo);
+ innerClassesAttribute.classes[index] = innerClassesInfo;
+ }
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ enclosingMethodAttribute.u2classIndex = dataInput.readUnsignedShort();
+ enclosingMethodAttribute.u2nameAndTypeIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ // This attribute does not contain any additional information.
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ // This attribute does not contain any additional information.
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ signatureAttribute.u2signatureIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ constantValueAttribute.u2constantValueIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ // Read the parameter information.
+ methodParametersAttribute.u1parametersCount = dataInput.readUnsignedByte();
+
+ methodParametersAttribute.parameters = new ParameterInfo[methodParametersAttribute.u1parametersCount];
+ for (int index = 0; index < methodParametersAttribute.u1parametersCount; index++)
+ {
+ ParameterInfo parameterInfo = new ParameterInfo();
+ visitParameterInfo(clazz, method, index, parameterInfo);
+ methodParametersAttribute.parameters[index] = parameterInfo;
+ }
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ // Read the exceptions.
+ exceptionsAttribute.u2exceptionIndexTableLength = dataInput.readUnsignedShort();
+
+ exceptionsAttribute.u2exceptionIndexTable = new int[exceptionsAttribute.u2exceptionIndexTableLength];
+ for (int index = 0; index < exceptionsAttribute.u2exceptionIndexTableLength; index++)
+ {
+ exceptionsAttribute.u2exceptionIndexTable[index] = dataInput.readUnsignedShort();
+ }
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Read the stack size and local variable frame size.
+ codeAttribute.u2maxStack = dataInput.readUnsignedShort();
+ codeAttribute.u2maxLocals = dataInput.readUnsignedShort();
+
+ // Read the byte code.
+ codeAttribute.u4codeLength = dataInput.readInt();
+
+ byte[] code = new byte[codeAttribute.u4codeLength];
+ dataInput.readFully(code);
+ codeAttribute.code = code;
+
+ // Read the exceptions.
+ codeAttribute.u2exceptionTableLength = dataInput.readUnsignedShort();
+
+ codeAttribute.exceptionTable = new ExceptionInfo[codeAttribute.u2exceptionTableLength];
+ for (int index = 0; index < codeAttribute.u2exceptionTableLength; index++)
+ {
+ ExceptionInfo exceptionInfo = new ExceptionInfo();
+ visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
+ codeAttribute.exceptionTable[index] = exceptionInfo;
+ }
+
+ // Read the code attributes.
+ codeAttribute.u2attributesCount = dataInput.readUnsignedShort();
+
+ codeAttribute.attributes = new Attribute[codeAttribute.u2attributesCount];
+ for (int index = 0; index < codeAttribute.u2attributesCount; index++)
+ {
+ Attribute attribute = createAttribute(clazz);
+ attribute.accept(clazz, method, codeAttribute, this);
+ codeAttribute.attributes[index] = attribute;
+ }
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ // Read the stack map frames (only full frames, without tag).
+ stackMapAttribute.u2stackMapFramesCount = dataInput.readUnsignedShort();
+
+ stackMapAttribute.stackMapFrames = new FullFrame[stackMapAttribute.u2stackMapFramesCount];
+ for (int index = 0; index < stackMapAttribute.u2stackMapFramesCount; index++)
+ {
+ FullFrame stackMapFrame = new FullFrame();
+ visitFullFrame(clazz, method, codeAttribute, index, stackMapFrame);
+ stackMapAttribute.stackMapFrames[index] = stackMapFrame;
+ }
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ // Read the stack map frames.
+ stackMapTableAttribute.u2stackMapFramesCount = dataInput.readUnsignedShort();
+
+ stackMapTableAttribute.stackMapFrames = new StackMapFrame[stackMapTableAttribute.u2stackMapFramesCount];
+ for (int index = 0; index < stackMapTableAttribute.u2stackMapFramesCount; index++)
+ {
+ StackMapFrame stackMapFrame = createStackMapFrame();
+ stackMapFrame.accept(clazz, method, codeAttribute, 0, this);
+ stackMapTableAttribute.stackMapFrames[index] = stackMapFrame;
+ }
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ // Read the line numbers.
+ lineNumberTableAttribute.u2lineNumberTableLength = dataInput.readUnsignedShort();
+
+ lineNumberTableAttribute.lineNumberTable = new LineNumberInfo[lineNumberTableAttribute.u2lineNumberTableLength];
+ for (int index = 0; index < lineNumberTableAttribute.u2lineNumberTableLength; index++)
+ {
+ LineNumberInfo lineNumberInfo = new LineNumberInfo();
+ visitLineNumberInfo(clazz, method, codeAttribute, lineNumberInfo);
+ lineNumberTableAttribute.lineNumberTable[index] = lineNumberInfo;
+ }
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Read the local variables.
+ localVariableTableAttribute.u2localVariableTableLength = dataInput.readUnsignedShort();
+
+ localVariableTableAttribute.localVariableTable = new LocalVariableInfo[localVariableTableAttribute.u2localVariableTableLength];
+ for (int index = 0; index < localVariableTableAttribute.u2localVariableTableLength; index++)
+ {
+ LocalVariableInfo localVariableInfo = new LocalVariableInfo();
+ visitLocalVariableInfo(clazz, method, codeAttribute, localVariableInfo);
+ localVariableTableAttribute.localVariableTable[index] = localVariableInfo;
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Read the local variable types.
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength = dataInput.readUnsignedShort();
+
+ localVariableTypeTableAttribute.localVariableTypeTable = new LocalVariableTypeInfo[localVariableTypeTableAttribute.u2localVariableTypeTableLength];
+ for (int index = 0; index < localVariableTypeTableAttribute.u2localVariableTypeTableLength; index++)
+ {
+ LocalVariableTypeInfo localVariableTypeInfo = new LocalVariableTypeInfo();
+ visitLocalVariableTypeInfo(clazz, method, codeAttribute, localVariableTypeInfo);
+ localVariableTypeTableAttribute.localVariableTypeTable[index] = localVariableTypeInfo;
+ }
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ // Read the annotations.
+ annotationsAttribute.u2annotationsCount = dataInput.readUnsignedShort();
+
+ annotationsAttribute.annotations = new Annotation[annotationsAttribute.u2annotationsCount];
+ for (int index = 0; index < annotationsAttribute.u2annotationsCount; index++)
+ {
+ Annotation annotation = new Annotation();
+ visitAnnotation(clazz, annotation);
+ annotationsAttribute.annotations[index] = annotation;
+ }
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Read the parameter annotations.
+ parameterAnnotationsAttribute.u1parametersCount = dataInput.readUnsignedByte();
+
+ // The java compilers of JDK 1.5, JDK 1.6, and Eclipse all count the
+ // number of parameters of constructors of non-static inner classes
+ // incorrectly. Fix it right here.
+ int parameterStart = 0;
+ if (method.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT))
+ {
+ int realParametersCount = ClassUtil.internalMethodParameterCount(method.getDescriptor(clazz));
+ parameterStart = realParametersCount - parameterAnnotationsAttribute.u1parametersCount;
+ parameterAnnotationsAttribute.u1parametersCount = realParametersCount;
+ }
+
+ parameterAnnotationsAttribute.u2parameterAnnotationsCount = new int[parameterAnnotationsAttribute.u1parametersCount];
+ parameterAnnotationsAttribute.parameterAnnotations = new Annotation[parameterAnnotationsAttribute.u1parametersCount][];
+
+ for (int parameterIndex = parameterStart; parameterIndex < parameterAnnotationsAttribute.u1parametersCount; parameterIndex++)
+ {
+ // Read the parameter annotations of the given parameter.
+ int u2annotationsCount = dataInput.readUnsignedShort();
+
+ Annotation[] annotations = new Annotation[u2annotationsCount];
+
+ for (int index = 0; index < u2annotationsCount; index++)
+ {
+ Annotation annotation = new Annotation();
+ visitAnnotation(clazz, annotation);
+ annotations[index] = annotation;
+ }
+
+ parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex] = u2annotationsCount;
+ parameterAnnotationsAttribute.parameterAnnotations[parameterIndex] = annotations;
+ }
+ }
+
+
+ public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute)
+ {
+ // Read the type annotations.
+ typeAnnotationsAttribute.u2annotationsCount = dataInput.readUnsignedShort();
+
+ typeAnnotationsAttribute.annotations = new TypeAnnotation[typeAnnotationsAttribute.u2annotationsCount];
+ for (int index = 0; index < typeAnnotationsAttribute.u2annotationsCount; index++)
+ {
+ TypeAnnotation typeAnnotation = new TypeAnnotation();
+ visitTypeAnnotation(clazz, typeAnnotation);
+ typeAnnotationsAttribute.annotations[index] = typeAnnotation;
+ }
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Read the default element value.
+ ElementValue elementValue = createElementValue();
+ elementValue.accept(clazz, null, this);
+ annotationDefaultAttribute.defaultValue = elementValue;
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ bootstrapMethodInfo.u2methodHandleIndex = dataInput.readUnsignedShort();
+
+ // Read the bootstrap method arguments.
+ bootstrapMethodInfo.u2methodArgumentCount = dataInput.readUnsignedShort();
+ bootstrapMethodInfo.u2methodArguments = new int[bootstrapMethodInfo.u2methodArgumentCount];
+ for (int index = 0; index < bootstrapMethodInfo.u2methodArgumentCount; index++)
+ {
+ bootstrapMethodInfo.u2methodArguments[index] = dataInput.readUnsignedShort();
+ }
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ innerClassesInfo.u2innerClassIndex = dataInput.readUnsignedShort();
+ innerClassesInfo.u2outerClassIndex = dataInput.readUnsignedShort();
+ innerClassesInfo.u2innerNameIndex = dataInput.readUnsignedShort();
+ innerClassesInfo.u2innerClassAccessFlags = dataInput.readUnsignedShort();
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ exceptionInfo.u2startPC = dataInput.readUnsignedShort();
+ exceptionInfo.u2endPC = dataInput.readUnsignedShort();
+ exceptionInfo.u2handlerPC = dataInput.readUnsignedShort();
+ exceptionInfo.u2catchType = dataInput.readUnsignedShort();
+ }
+
+
+ // Implementations for StackMapFrameVisitor.
+
+ public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame)
+ {
+ if (sameZeroFrame.getTag() == StackMapFrame.SAME_ZERO_FRAME_EXTENDED)
+ {
+ sameZeroFrame.u2offsetDelta = dataInput.readUnsignedShort();
+ }
+ }
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ if (sameOneFrame.getTag() == StackMapFrame.SAME_ONE_FRAME_EXTENDED)
+ {
+ sameOneFrame.u2offsetDelta = dataInput.readUnsignedShort();
+ }
+
+ // Read the verification type of the stack entry.
+ VerificationType verificationType = createVerificationType();
+ verificationType.accept(clazz, method, codeAttribute, offset, this);
+ sameOneFrame.stackItem = verificationType;
+ }
+
+
+ public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame)
+ {
+ lessZeroFrame.u2offsetDelta = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ moreZeroFrame.u2offsetDelta = dataInput.readUnsignedShort();
+
+ // Read the verification types of the additional local variables.
+ moreZeroFrame.additionalVariables = new VerificationType[moreZeroFrame.additionalVariablesCount];
+ for (int index = 0; index < moreZeroFrame.additionalVariablesCount; index++)
+ {
+ VerificationType verificationType = createVerificationType();
+ verificationType.accept(clazz, method, codeAttribute, offset, this);
+ moreZeroFrame.additionalVariables[index] = verificationType;
+ }
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ fullFrame.u2offsetDelta = dataInput.readUnsignedShort();
+
+ // Read the verification types of the local variables.
+ fullFrame.variablesCount = dataInput.readUnsignedShort();
+ fullFrame.variables = new VerificationType[fullFrame.variablesCount];
+ for (int index = 0; index < fullFrame.variablesCount; index++)
+ {
+ VerificationType verificationType = createVerificationType();
+ verificationType.variablesAccept(clazz, method, codeAttribute, offset, index, this);
+ fullFrame.variables[index] = verificationType;
+ }
+
+ // Read the verification types of the stack entries.
+ fullFrame.stackCount = dataInput.readUnsignedShort();
+ fullFrame.stack = new VerificationType[fullFrame.stackCount];
+ for (int index = 0; index < fullFrame.stackCount; index++)
+ {
+ VerificationType verificationType = createVerificationType();
+ verificationType.stackAccept(clazz, method, codeAttribute, offset, index, this);
+ fullFrame.stack[index] = verificationType;
+ }
+ }
+
+
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType)
+ {
+ // Most verification types don't contain any additional information.
+ }
+
+
+ public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
+ {
+ objectType.u2classIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
+ {
+ uninitializedType.u2newInstructionOffset = dataInput.readUnsignedShort();
+ }
+
+
+ // Implementations for LineNumberInfoVisitor.
+
+ public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
+ {
+ lineNumberInfo.u2startPC = dataInput.readUnsignedShort();
+ lineNumberInfo.u2lineNumber = dataInput.readUnsignedShort();
+ }
+
+
+ // Implementations for ParameterInfoVisitor.
+
+ public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
+ {
+ parameterInfo.u2nameIndex = dataInput.readUnsignedShort();
+ parameterInfo.u2accessFlags = dataInput.readUnsignedShort();
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ localVariableInfo.u2startPC = dataInput.readUnsignedShort();
+ localVariableInfo.u2length = dataInput.readUnsignedShort();
+ localVariableInfo.u2nameIndex = dataInput.readUnsignedShort();
+ localVariableInfo.u2descriptorIndex = dataInput.readUnsignedShort();
+ localVariableInfo.u2index = dataInput.readUnsignedShort();
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ localVariableTypeInfo.u2startPC = dataInput.readUnsignedShort();
+ localVariableTypeInfo.u2length = dataInput.readUnsignedShort();
+ localVariableTypeInfo.u2nameIndex = dataInput.readUnsignedShort();
+ localVariableTypeInfo.u2signatureIndex = dataInput.readUnsignedShort();
+ localVariableTypeInfo.u2index = dataInput.readUnsignedShort();
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ // Read the annotation type.
+ annotation.u2typeIndex = dataInput.readUnsignedShort();
+
+ // Read the element value pairs.
+ annotation.u2elementValuesCount = dataInput.readUnsignedShort();
+
+ annotation.elementValues = new ElementValue[annotation.u2elementValuesCount];
+ for (int index = 0; index < annotation.u2elementValuesCount; index++)
+ {
+ int u2elementNameIndex = dataInput.readUnsignedShort();
+ ElementValue elementValue = createElementValue();
+ elementValue.u2elementNameIndex = u2elementNameIndex;
+ elementValue.accept(clazz, annotation, this);
+ annotation.elementValues[index] = elementValue;
+ }
+ }
+
+
+ // Implementations for TypeAnnotationVisitor.
+
+ public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)
+ {
+ // Read the target info.
+ TargetInfo targetInfo = createTargetInfo();
+ targetInfo.accept(clazz, typeAnnotation, this);
+ typeAnnotation.targetInfo = targetInfo;
+
+ // Read the type path.
+ int u1pathLength = dataInput.readUnsignedByte();
+
+ typeAnnotation.typePath = new TypePathInfo[u1pathLength];
+ for (int index = 0; index < u1pathLength; index++)
+ {
+ TypePathInfo typePathInfo = new TypePathInfo();
+ visitTypePathInfo(clazz, typeAnnotation, typePathInfo);
+ typeAnnotation.typePath[index] = typePathInfo;
+ }
+
+ // Read the actual annotation.
+ visitAnnotation(clazz, typeAnnotation);
+ }
+
+
+ // Implementations for TargetInfoVisitor.
+
+ public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo)
+ {
+ typeParameterTargetInfo.u1typeParameterIndex = dataInput.readUnsignedByte();
+ }
+
+
+ public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo)
+ {
+ superTypeTargetInfo.u2superTypeIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)
+ {
+ typeParameterBoundTargetInfo.u1typeParameterIndex = dataInput.readUnsignedByte();
+ typeParameterBoundTargetInfo.u1boundIndex = dataInput.readUnsignedByte();
+ }
+
+
+ public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo)
+ {
+ }
+
+
+ public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo)
+ {
+ formalParameterTargetInfo.u1formalParameterIndex = dataInput.readUnsignedByte();
+ }
+
+
+ public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo)
+ {
+ throwsTargetInfo.u2throwsTypeIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)
+ {
+ // Read the local variable target elements.
+ localVariableTargetInfo.u2tableLength = dataInput.readUnsignedShort();
+
+ localVariableTargetInfo.table = new LocalVariableTargetElement[localVariableTargetInfo.u2tableLength];
+ for (int index = 0; index < localVariableTargetInfo.u2tableLength; index++)
+ {
+ LocalVariableTargetElement element = new LocalVariableTargetElement();
+ visitLocalVariableTargetElement(clazz, method, codeAttribute, typeAnnotation, localVariableTargetInfo, element);
+ localVariableTargetInfo.table[index] = element;
+ }
+ }
+
+
+ public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo)
+ {
+ catchTargetInfo.u2exceptionTableIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo)
+ {
+ offsetTargetInfo.u2offset = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo)
+ {
+ typeArgumentTargetInfo.u2offset = dataInput.readUnsignedShort();
+ typeArgumentTargetInfo.u1typeArgumentIndex = dataInput.readUnsignedByte();
+ }
+
+
+ // Implementations for TypePathInfoVisitor.
+
+ public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)
+ {
+ typePathInfo.u1typePathKind = dataInput.readUnsignedByte();
+ typePathInfo.u1typeArgumentIndex = dataInput.readUnsignedByte();
+ }
+
+
+ // Implementations for LocalVariableTargetElementVisitor.
+
+ public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)
+ {
+ localVariableTargetElement.u2startPC = dataInput.readShort();
+ localVariableTargetElement.u2length = dataInput.readShort();
+ localVariableTargetElement.u2index = dataInput.readShort();
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ constantElementValue.u2constantValueIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ enumConstantElementValue.u2typeNameIndex = dataInput.readUnsignedShort();
+ enumConstantElementValue.u2constantNameIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ classElementValue.u2classInfoIndex = dataInput.readUnsignedShort();
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ // Read the annotation.
+ Annotation annotationValue = new Annotation();
+ visitAnnotation(clazz, annotationValue);
+ annotationElementValue.annotationValue = annotationValue;
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ // Read the element values.
+ arrayElementValue.u2elementValuesCount = dataInput.readUnsignedShort();
+
+ arrayElementValue.elementValues = new ElementValue[arrayElementValue.u2elementValuesCount];
+ for (int index = 0; index < arrayElementValue.u2elementValuesCount; index++)
+ {
+ ElementValue elementValue = createElementValue();
+ elementValue.accept(clazz, annotation, this);
+ arrayElementValue.elementValues[index] = elementValue;
+ }
+ }
+
+
+ // Small utility methods.
+
+ private Constant createConstant()
+ {
+ int u1tag = dataInput.readUnsignedByte();
+
+ switch (u1tag)
+ {
+ case ClassConstants.CONSTANT_Integer: return new IntegerConstant();
+ case ClassConstants.CONSTANT_Float: return new FloatConstant();
+ case ClassConstants.CONSTANT_Long: return new LongConstant();
+ case ClassConstants.CONSTANT_Double: return new DoubleConstant();
+ case ClassConstants.CONSTANT_String: return new StringConstant();
+ case ClassConstants.CONSTANT_Utf8: return new Utf8Constant();
+ case ClassConstants.CONSTANT_InvokeDynamic: return new InvokeDynamicConstant();
+ case ClassConstants.CONSTANT_MethodHandle: return new MethodHandleConstant();
+ case ClassConstants.CONSTANT_Fieldref: return new FieldrefConstant();
+ case ClassConstants.CONSTANT_Methodref: return new MethodrefConstant();
+ case ClassConstants.CONSTANT_InterfaceMethodref: return new InterfaceMethodrefConstant();
+ case ClassConstants.CONSTANT_Class: return new ClassConstant();
+ case ClassConstants.CONSTANT_MethodType: return new MethodTypeConstant();
+ case ClassConstants.CONSTANT_NameAndType: return new NameAndTypeConstant();
+
+ default: throw new RuntimeException("Unknown constant type ["+u1tag+"] in constant pool");
+ }
+ }
+
+
+ private Attribute createAttribute(Clazz clazz)
+ {
+ int u2attributeNameIndex = dataInput.readUnsignedShort();
+ int u4attributeLength = dataInput.readInt();
+ String attributeName = clazz.getString(u2attributeNameIndex);
+
+ Attribute attribute =
+ attributeName.equals(ClassConstants.ATTR_BootstrapMethods) ? (Attribute)new BootstrapMethodsAttribute():
+ attributeName.equals(ClassConstants.ATTR_SourceFile) ? (Attribute)new SourceFileAttribute():
+ attributeName.equals(ClassConstants.ATTR_SourceDir) ? (Attribute)new SourceDirAttribute():
+ attributeName.equals(ClassConstants.ATTR_InnerClasses) ? (Attribute)new InnerClassesAttribute():
+ attributeName.equals(ClassConstants.ATTR_EnclosingMethod) ? (Attribute)new EnclosingMethodAttribute():
+ attributeName.equals(ClassConstants.ATTR_Deprecated) ? (Attribute)new DeprecatedAttribute():
+ attributeName.equals(ClassConstants.ATTR_Synthetic) ? (Attribute)new SyntheticAttribute():
+ attributeName.equals(ClassConstants.ATTR_Signature) ? (Attribute)new SignatureAttribute():
+ attributeName.equals(ClassConstants.ATTR_ConstantValue) ? (Attribute)new ConstantValueAttribute():
+ attributeName.equals(ClassConstants.ATTR_MethodParameters) ? (Attribute)new MethodParametersAttribute():
+ attributeName.equals(ClassConstants.ATTR_Exceptions) ? (Attribute)new ExceptionsAttribute():
+ attributeName.equals(ClassConstants.ATTR_Code) ? (Attribute)new CodeAttribute():
+ attributeName.equals(ClassConstants.ATTR_StackMap) ? (Attribute)new StackMapAttribute():
+ attributeName.equals(ClassConstants.ATTR_StackMapTable) ? (Attribute)new StackMapTableAttribute():
+ attributeName.equals(ClassConstants.ATTR_LineNumberTable) ? (Attribute)new LineNumberTableAttribute():
+ attributeName.equals(ClassConstants.ATTR_LocalVariableTable) ? (Attribute)new LocalVariableTableAttribute():
+ attributeName.equals(ClassConstants.ATTR_LocalVariableTypeTable) ? (Attribute)new LocalVariableTypeTableAttribute():
+ attributeName.equals(ClassConstants.ATTR_RuntimeVisibleAnnotations) ? (Attribute)new RuntimeVisibleAnnotationsAttribute():
+ attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleAnnotations) ? (Attribute)new RuntimeInvisibleAnnotationsAttribute():
+ attributeName.equals(ClassConstants.ATTR_RuntimeVisibleParameterAnnotations) ? (Attribute)new RuntimeVisibleParameterAnnotationsAttribute():
+ attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleParameterAnnotations) ? (Attribute)new RuntimeInvisibleParameterAnnotationsAttribute():
+ attributeName.equals(ClassConstants.ATTR_RuntimeVisibleTypeAnnotations) ? (Attribute)new RuntimeVisibleTypeAnnotationsAttribute():
+ attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleTypeAnnotations) ? (Attribute)new RuntimeInvisibleTypeAnnotationsAttribute():
+ attributeName.equals(ClassConstants.ATTR_AnnotationDefault) ? (Attribute)new AnnotationDefaultAttribute():
+ (Attribute)new UnknownAttribute(u2attributeNameIndex, u4attributeLength);
+ attribute.u2attributeNameIndex = u2attributeNameIndex;
+
+ return attribute;
+ }
+
+
+ private StackMapFrame createStackMapFrame()
+ {
+ int u1tag = dataInput.readUnsignedByte();
+
+ return
+ u1tag < StackMapFrame.SAME_ONE_FRAME ? (StackMapFrame)new SameZeroFrame(u1tag) :
+ u1tag < StackMapFrame.SAME_ONE_FRAME_EXTENDED ? (StackMapFrame)new SameOneFrame(u1tag) :
+ u1tag < StackMapFrame.LESS_ZERO_FRAME ? (StackMapFrame)new SameOneFrame(u1tag) :
+ u1tag < StackMapFrame.SAME_ZERO_FRAME_EXTENDED ? (StackMapFrame)new LessZeroFrame(u1tag) :
+ u1tag < StackMapFrame.MORE_ZERO_FRAME ? (StackMapFrame)new SameZeroFrame(u1tag) :
+ u1tag < StackMapFrame.FULL_FRAME ? (StackMapFrame)new MoreZeroFrame(u1tag) :
+ (StackMapFrame)new FullFrame();
+ }
+
+
+ private VerificationType createVerificationType()
+ {
+ int u1tag = dataInput.readUnsignedByte();
+
+ switch (u1tag)
+ {
+ case VerificationType.INTEGER_TYPE: return new IntegerType();
+ case VerificationType.FLOAT_TYPE: return new FloatType();
+ case VerificationType.LONG_TYPE: return new LongType();
+ case VerificationType.DOUBLE_TYPE: return new DoubleType();
+ case VerificationType.TOP_TYPE: return new TopType();
+ case VerificationType.OBJECT_TYPE: return new ObjectType();
+ case VerificationType.NULL_TYPE: return new NullType();
+ case VerificationType.UNINITIALIZED_TYPE: return new UninitializedType();
+ case VerificationType.UNINITIALIZED_THIS_TYPE: return new UninitializedThisType();
+
+ default: throw new RuntimeException("Unknown verification type ["+u1tag+"] in stack map frame");
+ }
+ }
+
+
+ private TargetInfo createTargetInfo()
+ {
+ byte u1targetType = dataInput.readByte();
+
+ switch (u1targetType)
+ {
+ case ClassConstants.ANNOTATION_TARGET_ParameterGenericClass:
+ case ClassConstants.ANNOTATION_TARGET_ParameterGenericMethod: return new TypeParameterTargetInfo(u1targetType);
+ case ClassConstants.ANNOTATION_TARGET_Extends: return new SuperTypeTargetInfo(u1targetType);
+ case ClassConstants.ANNOTATION_TARGET_BoundGenericClass:
+ case ClassConstants.ANNOTATION_TARGET_BoundGenericMethod: return new TypeParameterBoundTargetInfo(u1targetType);
+ case ClassConstants.ANNOTATION_TARGET_Field:
+ case ClassConstants.ANNOTATION_TARGET_Return:
+ case ClassConstants.ANNOTATION_TARGET_Receiver: return new EmptyTargetInfo(u1targetType);
+ case ClassConstants.ANNOTATION_TARGET_Parameter: return new FormalParameterTargetInfo(u1targetType);
+ case ClassConstants.ANNOTATION_TARGET_Throws: return new ThrowsTargetInfo(u1targetType);
+ case ClassConstants.ANNOTATION_TARGET_LocalVariable:
+ case ClassConstants.ANNOTATION_TARGET_ResourceVariable: return new LocalVariableTargetInfo(u1targetType);
+ case ClassConstants.ANNOTATION_TARGET_Catch: return new CatchTargetInfo(u1targetType);
+ case ClassConstants.ANNOTATION_TARGET_InstanceOf:
+ case ClassConstants.ANNOTATION_TARGET_New:
+ case ClassConstants.ANNOTATION_TARGET_MethodReferenceNew:
+ case ClassConstants.ANNOTATION_TARGET_MethodReference: return new OffsetTargetInfo(u1targetType);
+ case ClassConstants.ANNOTATION_TARGET_Cast:
+ case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethodNew:
+ case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethod:
+ case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethodReferenceNew:
+ case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethodReference: return new TypeArgumentTargetInfo(u1targetType);
+
+ default: throw new RuntimeException("Unknown annotation target type ["+u1targetType+"]");
+ }
+ }
+
+
+ private ElementValue createElementValue()
+ {
+ int u1tag = dataInput.readUnsignedByte();
+
+ switch (u1tag)
+ {
+ case ClassConstants.TYPE_BOOLEAN:
+ case ClassConstants.TYPE_BYTE:
+ case ClassConstants.TYPE_CHAR:
+ case ClassConstants.TYPE_SHORT:
+ case ClassConstants.TYPE_INT:
+ case ClassConstants.TYPE_FLOAT:
+ case ClassConstants.TYPE_LONG:
+ case ClassConstants.TYPE_DOUBLE:
+ case ClassConstants.ELEMENT_VALUE_STRING_CONSTANT: return new ConstantElementValue((char)u1tag);
+
+ case ClassConstants.ELEMENT_VALUE_ENUM_CONSTANT: return new EnumConstantElementValue();
+ case ClassConstants.ELEMENT_VALUE_CLASS: return new ClassElementValue();
+ case ClassConstants.ELEMENT_VALUE_ANNOTATION: return new AnnotationElementValue();
+ case ClassConstants.ELEMENT_VALUE_ARRAY: return new ArrayElementValue();
+
+ default: throw new IllegalArgumentException("Unknown element value tag ["+u1tag+"]");
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/ProgramClassWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/ProgramClassWriter.java
new file mode 100644
index 0000000000..13fe74c68e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/ProgramClassWriter.java
@@ -0,0 +1,873 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.io;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.target.*;
+import proguard.classfile.attribute.annotation.target.visitor.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+import java.io.*;
+
+/**
+ * This ClassVisitor writes out the ProgramClass objects that it visits to the
+ * given DataOutput object.
+ *
+ * @author Eric Lafortune
+ */
+public class ProgramClassWriter
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ ConstantVisitor,
+ AttributeVisitor
+{
+ private RuntimeDataOutput dataOutput;
+
+ private final ConstantBodyWriter constantBodyWriter = new ConstantBodyWriter();
+ private final AttributeBodyWriter attributeBodyWriter = new AttributeBodyWriter();
+ private final StackMapFrameBodyWriter stackMapFrameBodyWriter = new StackMapFrameBodyWriter();
+ private final VerificationTypeBodyWriter verificationTypeBodyWriter = new VerificationTypeBodyWriter();
+ private final ElementValueBodyWriter elementValueBodyWriter = new ElementValueBodyWriter();
+
+
+ /**
+ * Creates a new ProgramClassWriter for writing to the given DataOutput.
+ */
+ public ProgramClassWriter(DataOutput dataOutput)
+ {
+ this.dataOutput = new RuntimeDataOutput(dataOutput);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Write the magic number.
+ dataOutput.writeInt(programClass.u4magic);
+
+ // Write the version numbers.
+ dataOutput.writeShort(ClassUtil.internalMinorClassVersion(programClass.u4version));
+ dataOutput.writeShort(ClassUtil.internalMajorClassVersion(programClass.u4version));
+
+ // Write the constant pool.
+ dataOutput.writeUnsignedShort(programClass.u2constantPoolCount);
+
+ programClass.constantPoolEntriesAccept(this);
+
+ // Write the general class information.
+ dataOutput.writeUnsignedShort(programClass.u2accessFlags);
+ dataOutput.writeUnsignedShort(programClass.u2thisClass);
+ dataOutput.writeUnsignedShort(programClass.u2superClass);
+
+ // Write the interfaces.
+ dataOutput.writeUnsignedShort(programClass.u2interfacesCount);
+
+ for (int index = 0; index < programClass.u2interfacesCount; index++)
+ {
+ dataOutput.writeUnsignedShort(programClass.u2interfaces[index]);
+ }
+
+ // Write the fields.
+ dataOutput.writeUnsignedShort(programClass.u2fieldsCount);
+
+ programClass.fieldsAccept(this);
+
+ // Write the methods.
+ dataOutput.writeUnsignedShort(programClass.u2methodsCount);
+
+ programClass.methodsAccept(this);
+
+ // Write the class attributes.
+ dataOutput.writeUnsignedShort(programClass.u2attributesCount);
+
+ programClass.attributesAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Write the general field information.
+ dataOutput.writeUnsignedShort(programField.u2accessFlags);
+ dataOutput.writeUnsignedShort(programField.u2nameIndex);
+ dataOutput.writeUnsignedShort(programField.u2descriptorIndex);
+
+ // Write the field attributes.
+ dataOutput.writeUnsignedShort(programField.u2attributesCount);
+
+ programField.attributesAccept(programClass, this);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Write the general method information.
+ dataOutput.writeUnsignedShort(programMethod.u2accessFlags);
+ dataOutput.writeUnsignedShort(programMethod.u2nameIndex);
+ dataOutput.writeUnsignedShort(programMethod.u2descriptorIndex);
+
+ // Write the method attributes.
+ dataOutput.writeUnsignedShort(programMethod.u2attributesCount);
+
+ programMethod.attributesAccept(programClass, this);
+ }
+
+
+ public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)
+ {
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ // Write the tag.
+ dataOutput.writeByte(constant.getTag());
+
+ // Write the actual body.
+ constant.accept(clazz, constantBodyWriter);
+ }
+
+
+ private class ConstantBodyWriter
+ extends SimplifiedVisitor
+ implements ConstantVisitor
+ {
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ dataOutput.writeInt(integerConstant.u4value);
+ }
+
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ dataOutput.writeLong(longConstant.u8value);
+ }
+
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ dataOutput.writeFloat(floatConstant.f4value);
+ }
+
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ dataOutput.writeDouble(doubleConstant.f8value);
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ dataOutput.writeUnsignedShort(stringConstant.u2stringIndex);
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ byte[] bytes = utf8Constant.getBytes();
+
+ dataOutput.writeUnsignedShort(bytes.length);
+ dataOutput.write(bytes);
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ dataOutput.writeUnsignedShort(invokeDynamicConstant.u2bootstrapMethodAttributeIndex);
+ dataOutput.writeUnsignedShort(invokeDynamicConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ dataOutput.writeByte(methodHandleConstant.u1referenceKind);
+ dataOutput.writeUnsignedShort(methodHandleConstant.u2referenceIndex);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ dataOutput.writeUnsignedShort(refConstant.u2classIndex);
+ dataOutput.writeUnsignedShort(refConstant.u2nameAndTypeIndex);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ dataOutput.writeUnsignedShort(classConstant.u2nameIndex);
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ dataOutput.writeUnsignedShort(methodTypeConstant.u2descriptorIndex);
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ dataOutput.writeUnsignedShort(nameAndTypeConstant.u2nameIndex);
+ dataOutput.writeUnsignedShort(nameAndTypeConstant.u2descriptorIndex);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute)
+ {
+ // Write the attribute name index.
+ dataOutput.writeUnsignedShort(attribute.u2attributeNameIndex);
+
+ // We'll write the attribute body into an array first, so we can
+ // automatically figure out its length.
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+
+ // Temporarily replace the current data output.
+ RuntimeDataOutput oldDataOutput = dataOutput;
+ dataOutput = new RuntimeDataOutput(new DataOutputStream(byteArrayOutputStream));
+
+ // Write the attribute body into the array. Note that the
+ // accept method with two dummy null arguments never throws
+ // an UnsupportedOperationException.
+ attribute.accept(clazz, null, null, attributeBodyWriter);
+
+ // Restore the original data output.
+ dataOutput = oldDataOutput;
+
+ // Write the attribute length and body.
+ byte[] info = byteArrayOutputStream.toByteArray();
+
+ dataOutput.writeInt(info.length);
+ dataOutput.write(info);
+ }
+
+
+ private class AttributeBodyWriter
+ extends SimplifiedVisitor
+ implements AttributeVisitor,
+ BootstrapMethodInfoVisitor,
+ InnerClassesInfoVisitor,
+ ExceptionInfoVisitor,
+ StackMapFrameVisitor,
+ VerificationTypeVisitor,
+ LineNumberInfoVisitor,
+ ParameterInfoVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ TypeAnnotationVisitor,
+ TargetInfoVisitor,
+ TypePathInfoVisitor,
+ LocalVariableTargetElementVisitor,
+ ElementValueVisitor
+ {
+ // Implementations for AttributeVisitor.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ // Write the unknown information.
+ dataOutput.write(unknownAttribute.info);
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Write the bootstrap methods.
+ dataOutput.writeUnsignedShort(bootstrapMethodsAttribute.u2bootstrapMethodsCount);
+
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ dataOutput.writeUnsignedShort(sourceFileAttribute.u2sourceFileIndex);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ dataOutput.writeUnsignedShort(sourceDirAttribute.u2sourceDirIndex);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ // Write the inner classes.
+ dataOutput.writeUnsignedShort(innerClassesAttribute.u2classesCount);
+
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ dataOutput.writeUnsignedShort(enclosingMethodAttribute.u2classIndex);
+ dataOutput.writeUnsignedShort(enclosingMethodAttribute.u2nameAndTypeIndex);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ // This attribute does not contain any additional information.
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ // This attribute does not contain any additional information.
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ dataOutput.writeUnsignedShort(signatureAttribute.u2signatureIndex);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ dataOutput.writeUnsignedShort(constantValueAttribute.u2constantValueIndex);
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ // Write the parameter information.
+ dataOutput.writeByte(methodParametersAttribute.u1parametersCount);
+
+ methodParametersAttribute.parametersAccept(clazz, method, this);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ // Write the exceptions.
+ dataOutput.writeUnsignedShort(exceptionsAttribute.u2exceptionIndexTableLength);
+
+ for (int index = 0; index < exceptionsAttribute.u2exceptionIndexTableLength; index++)
+ {
+ dataOutput.writeUnsignedShort(exceptionsAttribute.u2exceptionIndexTable[index]);
+ }
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Write the stack size and local variable frame size.
+ dataOutput.writeUnsignedShort(codeAttribute.u2maxStack);
+ dataOutput.writeUnsignedShort(codeAttribute.u2maxLocals);
+
+ // Write the byte code.
+ dataOutput.writeInt(codeAttribute.u4codeLength);
+
+ dataOutput.write(codeAttribute.code, 0, codeAttribute.u4codeLength);
+
+ // Write the exceptions.
+ dataOutput.writeUnsignedShort(codeAttribute.u2exceptionTableLength);
+
+ codeAttribute.exceptionsAccept(clazz, method, this);
+
+ // Write the code attributes.
+ dataOutput.writeUnsignedShort(codeAttribute.u2attributesCount);
+
+ codeAttribute.attributesAccept(clazz, method, ProgramClassWriter.this);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ // Write the stack map frames (only full frames, without tag).
+ dataOutput.writeUnsignedShort(stackMapAttribute.u2stackMapFramesCount);
+
+ stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, stackMapFrameBodyWriter);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ // Write the stack map frames.
+ dataOutput.writeUnsignedShort(stackMapTableAttribute.u2stackMapFramesCount);
+
+ stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ // Write the line numbers.
+ dataOutput.writeUnsignedShort(lineNumberTableAttribute.u2lineNumberTableLength);
+
+ lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Write the local variables.
+ dataOutput.writeUnsignedShort(localVariableTableAttribute.u2localVariableTableLength);
+
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Write the local variable types.
+ dataOutput.writeUnsignedShort(localVariableTypeTableAttribute.u2localVariableTypeTableLength);
+
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ // Write the annotations.
+ dataOutput.writeUnsignedShort(annotationsAttribute.u2annotationsCount);
+
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Write the parameter annotations.
+ dataOutput.writeByte(parameterAnnotationsAttribute.u1parametersCount);
+
+ for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u1parametersCount; parameterIndex++)
+ {
+ // Write the parameter annotations of the given parameter.
+ int u2annotationsCount = parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex];
+ Annotation[] annotations = parameterAnnotationsAttribute.parameterAnnotations[parameterIndex];
+
+ dataOutput.writeUnsignedShort(u2annotationsCount);
+
+ for (int index = 0; index < u2annotationsCount; index++)
+ {
+ visitAnnotation(clazz, annotations[index]);
+ }
+
+ }
+ }
+
+
+ public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute)
+ {
+ // Write the type annotations.
+ dataOutput.writeUnsignedShort(typeAnnotationsAttribute.u2annotationsCount);
+
+ typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Write the default element value.
+ annotationDefaultAttribute.defaultValue.accept(clazz, null, this);
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ dataOutput.writeUnsignedShort(bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Write the bootstrap method arguments.
+ dataOutput.writeUnsignedShort(bootstrapMethodInfo.u2methodArgumentCount);
+
+ for (int index = 0; index < bootstrapMethodInfo.u2methodArgumentCount; index++)
+ {
+ dataOutput.writeUnsignedShort(bootstrapMethodInfo.u2methodArguments[index]);
+ }
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ dataOutput.writeUnsignedShort(innerClassesInfo.u2innerClassIndex);
+ dataOutput.writeUnsignedShort(innerClassesInfo.u2outerClassIndex);
+ dataOutput.writeUnsignedShort(innerClassesInfo.u2innerNameIndex);
+ dataOutput.writeUnsignedShort(innerClassesInfo.u2innerClassAccessFlags);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ dataOutput.writeUnsignedShort(exceptionInfo.u2startPC);
+ dataOutput.writeUnsignedShort(exceptionInfo.u2endPC);
+ dataOutput.writeUnsignedShort(exceptionInfo.u2handlerPC);
+ dataOutput.writeUnsignedShort(exceptionInfo.u2catchType);
+ }
+
+
+ // Implementations for StackMapFrameVisitor.
+
+ public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)
+ {
+ // Write the stack map frame tag.
+ dataOutput.writeByte(stackMapFrame.getTag());
+
+ // Write the actual body.
+ stackMapFrame.accept(clazz, method, codeAttribute, offset, stackMapFrameBodyWriter);
+ }
+
+
+ // Implementations for LineNumberInfoVisitor.
+
+ public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
+ {
+ dataOutput.writeUnsignedShort(lineNumberInfo.u2startPC);
+ dataOutput.writeUnsignedShort(lineNumberInfo.u2lineNumber);
+ }
+
+
+ // Implementations for ParameterInfoVisitor.
+
+ public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
+ {
+ dataOutput.writeUnsignedShort(parameterInfo.u2nameIndex);
+ dataOutput.writeUnsignedShort(parameterInfo.u2accessFlags);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ dataOutput.writeUnsignedShort(localVariableInfo.u2startPC);
+ dataOutput.writeUnsignedShort(localVariableInfo.u2length);
+ dataOutput.writeUnsignedShort(localVariableInfo.u2nameIndex);
+ dataOutput.writeUnsignedShort(localVariableInfo.u2descriptorIndex);
+ dataOutput.writeUnsignedShort(localVariableInfo.u2index);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ dataOutput.writeUnsignedShort(localVariableTypeInfo.u2startPC);
+ dataOutput.writeUnsignedShort(localVariableTypeInfo.u2length);
+ dataOutput.writeUnsignedShort(localVariableTypeInfo.u2nameIndex);
+ dataOutput.writeUnsignedShort(localVariableTypeInfo.u2signatureIndex);
+ dataOutput.writeUnsignedShort(localVariableTypeInfo.u2index);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ // Write the annotation type.
+ dataOutput.writeUnsignedShort(annotation.u2typeIndex);
+
+ // Write the element value pairs.
+ dataOutput.writeUnsignedShort(annotation.u2elementValuesCount);
+
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for TypeAnnotationVisitor.
+
+ public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)
+ {
+ // Write the target info.
+ dataOutput.writeByte(typeAnnotation.targetInfo.u1targetType);
+
+ typeAnnotation.targetInfoAccept(clazz, this);
+
+ // Write the type path.
+ dataOutput.writeByte(typeAnnotation.typePath.length);
+
+ typeAnnotation.typePathInfosAccept(clazz, this);
+
+ // Write the actual annotation.
+ visitAnnotation(clazz, typeAnnotation);
+ }
+
+
+ // Implementations for TargetInfoVisitor.
+
+ public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo)
+ {
+ dataOutput.writeByte(typeParameterTargetInfo.u1typeParameterIndex);
+ }
+
+
+ public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo)
+ {
+ dataOutput.writeUnsignedShort(superTypeTargetInfo.u2superTypeIndex);
+ }
+
+
+ public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)
+ {
+ dataOutput.writeByte(typeParameterBoundTargetInfo.u1typeParameterIndex);
+ dataOutput.writeByte(typeParameterBoundTargetInfo.u1boundIndex);
+ }
+
+
+ public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo)
+ {
+ }
+
+
+ public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo)
+ {
+ dataOutput.writeByte(formalParameterTargetInfo.u1formalParameterIndex);
+ }
+
+
+ public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo)
+ {
+ dataOutput.writeUnsignedShort(throwsTargetInfo.u2throwsTypeIndex);
+ }
+
+
+ public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)
+ {
+ // Write the local variable target elements.
+ dataOutput.writeUnsignedShort(localVariableTargetInfo.u2tableLength);
+
+ localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this);
+ }
+
+
+ public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo)
+ {
+ dataOutput.writeUnsignedShort(catchTargetInfo.u2exceptionTableIndex);
+ }
+
+
+ public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo)
+ {
+ dataOutput.writeUnsignedShort(offsetTargetInfo.u2offset);
+ }
+
+
+ public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo)
+ {
+ dataOutput.writeUnsignedShort(typeArgumentTargetInfo.u2offset);
+ dataOutput.writeByte(typeArgumentTargetInfo.u1typeArgumentIndex);
+ }
+
+
+ // Implementations for TypePathInfoVisitor.
+
+ public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)
+ {
+ dataOutput.writeByte(typePathInfo.u1typePathKind);
+ dataOutput.writeByte(typePathInfo.u1typeArgumentIndex);
+ }
+
+
+ // Implementations for LocalVariableTargetElementVisitor.
+
+ public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)
+ {
+ dataOutput.writeUnsignedShort(localVariableTargetElement.u2startPC);
+ dataOutput.writeUnsignedShort(localVariableTargetElement.u2length);
+ dataOutput.writeUnsignedShort(localVariableTargetElement.u2index);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue)
+ {
+ // Write the element name index, if applicable.
+ int u2elementNameIndex = elementValue.u2elementNameIndex;
+ if (u2elementNameIndex != 0)
+ {
+ dataOutput.writeUnsignedShort(u2elementNameIndex);
+ }
+
+ // Write the tag.
+ dataOutput.writeByte(elementValue.getTag());
+
+ // Write the actual body.
+ elementValue.accept(clazz, annotation, elementValueBodyWriter);
+ }
+ }
+
+
+ private class StackMapFrameBodyWriter
+ extends SimplifiedVisitor
+ implements StackMapFrameVisitor,
+ VerificationTypeVisitor
+ {
+ public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame)
+ {
+ if (sameZeroFrame.getTag() == StackMapFrame.SAME_ZERO_FRAME_EXTENDED)
+ {
+ dataOutput.writeUnsignedShort(sameZeroFrame.u2offsetDelta);
+ }
+ }
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ if (sameOneFrame.getTag() == StackMapFrame.SAME_ONE_FRAME_EXTENDED)
+ {
+ dataOutput.writeUnsignedShort(sameOneFrame.u2offsetDelta);
+ }
+
+ // Write the verification type of the stack entry.
+ sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame)
+ {
+ dataOutput.writeUnsignedShort(lessZeroFrame.u2offsetDelta);
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ dataOutput.writeUnsignedShort(moreZeroFrame.u2offsetDelta);
+
+ // Write the verification types of the additional local variables.
+ moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ dataOutput.writeUnsignedShort(fullFrame.u2offsetDelta);
+
+ // Write the verification types of the local variables.
+ dataOutput.writeUnsignedShort(fullFrame.variablesCount);
+ fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
+
+ // Write the verification types of the stack entries.
+ dataOutput.writeUnsignedShort(fullFrame.stackCount);
+ fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType)
+ {
+ // Write the verification type tag.
+ dataOutput.writeByte(verificationType.getTag());
+
+ // Write the actual body.
+ verificationType.accept(clazz, method, codeAttribute, offset, verificationTypeBodyWriter);
+ }
+ }
+
+
+ private class VerificationTypeBodyWriter
+ extends SimplifiedVisitor
+ implements VerificationTypeVisitor
+ {
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType)
+ {
+ // Most verification types don't contain any additional information.
+ }
+
+
+ public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
+ {
+ dataOutput.writeUnsignedShort(objectType.u2classIndex);
+ }
+
+
+ public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
+ {
+ dataOutput.writeUnsignedShort(uninitializedType.u2newInstructionOffset);
+ }
+ }
+
+
+ private class ElementValueBodyWriter
+ extends SimplifiedVisitor
+ implements ElementValueVisitor
+ {
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ dataOutput.writeUnsignedShort(constantElementValue.u2constantValueIndex);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ dataOutput.writeUnsignedShort(enumConstantElementValue.u2typeNameIndex);
+ dataOutput.writeUnsignedShort(enumConstantElementValue.u2constantNameIndex);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ dataOutput.writeUnsignedShort(classElementValue.u2classInfoIndex);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ // Write the annotation.
+ attributeBodyWriter.visitAnnotation(clazz, annotationElementValue.annotationValue);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ // Write the element values.
+ dataOutput.writeUnsignedShort(arrayElementValue.u2elementValuesCount);
+
+ arrayElementValue.elementValuesAccept(clazz, annotation, attributeBodyWriter);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/RuntimeDataInput.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/RuntimeDataInput.java
new file mode 100644
index 0000000000..5796269c21
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/RuntimeDataInput.java
@@ -0,0 +1,223 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.io;
+
+import java.io.*;
+
+/**
+ * This class delegates its method calls to the corresponding DataInput methods,
+ * converting its IOExceptions to RuntimeExceptions.
+ *
+ * @author Eric Lafortune
+ */
+final class RuntimeDataInput
+{
+ private final DataInput dataInput;
+
+
+ public RuntimeDataInput(DataInput dataInput)
+ {
+ this.dataInput = dataInput;
+ }
+
+
+ // Methods delegating to DataInput.
+
+ public boolean readBoolean()
+ {
+ try
+ {
+ return dataInput.readBoolean();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public byte readByte()
+ {
+ try
+ {
+ return dataInput.readByte();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public char readChar()
+ {
+ try
+ {
+ return dataInput.readChar();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public double readDouble()
+ {
+ try
+ {
+ return dataInput.readDouble();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public float readFloat()
+ {
+ try
+ {
+ return dataInput.readFloat();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public void readFully(byte[] b)
+ {
+ try
+ {
+ dataInput.readFully(b);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public void readFully(byte[] b, int off, int len)
+ {
+ try
+ {
+ dataInput.readFully(b, off, len);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public int readInt()
+ {
+ try
+ {
+ return dataInput.readInt();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public String readLine()
+ {
+ try
+ {
+ return dataInput.readLine();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public long readLong()
+ {
+ try
+ {
+ return dataInput.readLong();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public short readShort()
+ {
+ try
+ {
+ return dataInput.readShort();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public int readUnsignedByte()
+ {
+ try
+ {
+ return dataInput.readUnsignedByte();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public int readUnsignedShort()
+ {
+ try
+ {
+ return dataInput.readUnsignedShort();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public String readUTF()
+ {
+ try
+ {
+ return dataInput.readUTF();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ public int skipBytes(int n)
+ {
+ try
+ {
+ return dataInput.skipBytes(n);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/RuntimeDataOutput.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/RuntimeDataOutput.java
new file mode 100644
index 0000000000..781c6c9e5d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/RuntimeDataOutput.java
@@ -0,0 +1,261 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.io;
+
+import java.io.*;
+
+/**
+ * This class delegates its method calls to the corresponding DataOutput methods,
+ * converting its IOExceptions to RuntimeExceptions.
+ *
+ * The class provides two convenience methods that additionally check whether the
+ * written values are unsigned resp. signed short values before writing them.
+ *
+ * @author Eric Lafortune
+ */
+final class RuntimeDataOutput
+{
+ private final DataOutput dataOutput;
+
+
+ public RuntimeDataOutput(DataOutput dataOutput)
+ {
+ this.dataOutput = dataOutput;
+ }
+
+
+ // Methods delegating to DataOutput.
+
+ public void write(byte[] b)
+ {
+ try
+ {
+ dataOutput.write(b);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void write(byte[] b, int off, int len)
+ {
+ try
+ {
+ dataOutput.write(b, off, len);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void write(int b)
+ {
+ try
+ {
+ dataOutput.write(b);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void writeBoolean(boolean v)
+ {
+ try
+ {
+ dataOutput.writeBoolean(v);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void writeByte(int v)
+ {
+ try
+ {
+ dataOutput.writeByte(v);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void writeBytes(String s)
+ {
+ try
+ {
+ dataOutput.writeBytes(s);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void writeChar(int v)
+ {
+ try
+ {
+ dataOutput.writeChar(v);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void writeChars(String s)
+ {
+ try
+ {
+ dataOutput.writeChars(s);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void writeDouble(double v)
+ {
+ try
+ {
+ dataOutput.writeDouble(v);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void writeFloat(float v)
+ {
+ try
+ {
+ dataOutput.writeFloat(v);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void writeInt(int v)
+ {
+ try
+ {
+ dataOutput.writeInt(v);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void writeLong(long v)
+ {
+ try
+ {
+ dataOutput.writeLong(v);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ /**
+ * Checks if the given value is an unsigned short value before writing it.
+ *
+ * @throws IllegalArgumentException if the value is not an unsigned short value.
+ * @see #writeShort(int)
+ */
+ public void writeUnsignedShort(int v)
+ {
+ if ((v & 0xffff) != v)
+ {
+ throw new IllegalArgumentException("Overflow of unsigned short value ["+v+"]");
+ }
+
+ writeShort(v);
+ }
+
+
+ /**
+ * Checks if the given value is a signed short value before writing it.
+ *
+ * @throws IllegalArgumentException if the value is not a signed short value.
+ * @see #writeShort(int)
+ */
+ public void writeSignedShort(int v)
+ {
+ if ((short)v != v)
+ {
+ throw new IllegalArgumentException("Overflow of signed short value ["+v+"]");
+ }
+
+ writeShort(v);
+ }
+
+
+ public void writeShort(int v)
+ {
+ try
+ {
+ dataOutput.writeShort(v);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ public void writeUTF(String str)
+ {
+ try
+ {
+ dataOutput.writeUTF(str);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/package.html
new file mode 100644
index 0000000000..780b91710f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/io/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains classes for reading and writing class files.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/package.html
new file mode 100644
index 0000000000..9a68094a6a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/package.html
@@ -0,0 +1,15 @@
+<body>
+This package contains classes to represent the various elements of class files.
+<p>
+A class file is represented by the <code>{@link proguard.classfile.Clazz
+Clazz}</code> interface. This interface currently has two alternative
+representations:
+<ul>
+<li><code>{@link ProgramClass ProgramClass}</code>:
+ a complete representation that can be read, modified, and written back.
+<li><code>{@link LibraryClass LibraryClass}</code>:
+ an incomplete representation that can be only be read. It is however
+ more compact than <code>ProgramClass</code>, and sufficient for
+ analyzing class files from library jars.
+</ul>
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/AccessUtil.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/AccessUtil.java
new file mode 100644
index 0000000000..6799fa7fb6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/AccessUtil.java
@@ -0,0 +1,105 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.ClassConstants;
+
+
+/**
+ * Utility methods for working with access flags. For convenience, this class
+ * defines access levels, in ascending order: <code>PRIVATE</code>,
+ * <code>PACKAGE_VISIBLE</code>, <code>PROTECTED</code>, and <code>PUBLIC</code>.
+ *
+ * @author Eric Lafortune
+ */
+public class AccessUtil
+{
+ public static final int PRIVATE = 0;
+ public static final int PACKAGE_VISIBLE = 1;
+ public static final int PROTECTED = 2;
+ public static final int PUBLIC = 3;
+
+
+ // The mask of access flags.
+ private static final int ACCESS_MASK =
+ ClassConstants.ACC_PUBLIC |
+ ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_PROTECTED;
+
+
+ /**
+ * Returns the corresponding access level of the given access flags.
+ * @param accessFlags the internal access flags.
+ * @return the corresponding access level: <code>PRIVATE</code>,
+ * <code>PACKAGE_VISIBLE</code>, <code>PROTECTED</code>, or
+ * <code>PUBLIC</code>.
+ */
+ public static int accessLevel(int accessFlags)
+ {
+ switch (accessFlags & ACCESS_MASK)
+ {
+ case ClassConstants.ACC_PRIVATE: return PRIVATE;
+ default: return PACKAGE_VISIBLE;
+ case ClassConstants.ACC_PROTECTED: return PROTECTED;
+ case ClassConstants.ACC_PUBLIC: return PUBLIC;
+ }
+ }
+
+
+ /**
+ * Returns the corresponding access flags of the given access level.
+ * @param accessLevel the access level: <code>PRIVATE</code>,
+ * <code>PACKAGE_VISIBLE</code>, <code>PROTECTED</code>,
+ * or <code>PUBLIC</code>.
+ * @return the corresponding internal access flags, the internal access
+ * flags as a logical bit mask of <code>INTERNAL_ACC_PRIVATE</code>,
+ * <code>INTERNAL_ACC_PROTECTED</code>, and
+ * <code>INTERNAL_ACC_PUBLIC</code>.
+ */
+ public static int accessFlags(int accessLevel)
+ {
+ switch (accessLevel)
+ {
+ case PRIVATE: return ClassConstants.ACC_PRIVATE;
+ default: return 0;
+ case PROTECTED: return ClassConstants.ACC_PROTECTED;
+ case PUBLIC: return ClassConstants.ACC_PUBLIC;
+ }
+ }
+
+
+ /**
+ * Replaces the access part of the given access flags.
+ * @param accessFlags the internal access flags.
+ * @param newAccessFlags the new internal access flags.
+ */
+ public static int replaceAccessFlags(int accessFlags, int newAccessFlags)
+ {
+ // A private class member should not be explicitly final.
+ if (newAccessFlags == ClassConstants.ACC_PRIVATE)
+ {
+ accessFlags &= ~ClassConstants.ACC_FINAL;
+ }
+
+ return (accessFlags & ~ACCESS_MASK) |
+ (newAccessFlags & ACCESS_MASK);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/AllParameterVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/AllParameterVisitor.java
new file mode 100644
index 0000000000..b665d2b73a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/AllParameterVisitor.java
@@ -0,0 +1,239 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This MemberVisitor lets a given parameter visitor visit all the parameters
+ * of the methods that it visits. The parameters do not include or count the
+ * 'this' parameter or the return value.
+ *
+ * @author Eric Lafortune
+ */
+public class AllParameterVisitor
+implements MemberVisitor
+{
+ private final ParameterVisitor parameterVisitor;
+
+
+ /**
+ * Creates a new AllParameterVisitor for the given parameter
+ * visitor.
+ */
+ public AllParameterVisitor(ParameterVisitor parameterVisitor)
+ {
+ this.parameterVisitor = parameterVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ visitFieldType(programClass,
+ programField,
+ programField.referencedClass);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ visitFieldType(libraryClass,
+ libraryField,
+ libraryField.referencedClass);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ visitParameters(programClass,
+ programMethod,
+ programMethod.referencedClasses);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ visitParameters(libraryClass,
+ libraryMethod,
+ libraryMethod.referencedClasses);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Lets the parameter visitor visit the type of the given field.
+ */
+ private void visitFieldType(Clazz clazz,
+ Field field,
+ Clazz referencedClass)
+ {
+ String descriptor = field.getDescriptor(clazz);
+ parameterVisitor.visitParameter(clazz,
+ field,
+ 0,
+ 1,
+ 0,
+ ClassUtil.internalTypeSize(descriptor),
+ descriptor,
+ referencedClass);
+ }
+
+
+ /**
+ * Lets the parameter visitor visit the parameters of the given method.
+ */
+ private void visitParameters(Clazz clazz,
+ Method method,
+ Clazz[] referencedClasses)
+ {
+ String descriptor = method.getDescriptor(clazz);
+
+ // Count the number of parameters and their total size.
+ int parameterCount = 0;
+ int parameterSize = 0;
+
+ int index = 1;
+
+ loop: while (true)
+ {
+ char c = descriptor.charAt(index++);
+ switch (c)
+ {
+ case ClassConstants.TYPE_LONG:
+ case ClassConstants.TYPE_DOUBLE:
+ {
+ // Long and double primitive types.
+ parameterSize++;
+ break;
+ }
+ default:
+ {
+ // All other primitive types.
+ break;
+ }
+ case ClassConstants.TYPE_CLASS_START:
+ {
+ // Class types.
+ // Skip the class name.
+ index = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1;
+ break;
+ }
+ case ClassConstants.TYPE_ARRAY:
+ {
+ // Array types.
+ // Skip all array characters.
+ while ((c = descriptor.charAt(index++)) == ClassConstants.TYPE_ARRAY) {}
+
+ if (c == ClassConstants.TYPE_CLASS_START)
+ {
+ // Skip the class type.
+ index = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1;
+ }
+ break;
+ }
+ case ClassConstants.METHOD_ARGUMENTS_CLOSE:
+ {
+ break loop;
+ }
+ }
+
+ parameterCount++;
+ parameterSize++;
+ }
+
+ // Visit the parameters.
+ int parameterIndex = 0;
+ int parameterOffset = 0;
+ int referenceClassIndex = 0;
+
+ index = 1;
+
+ while (true)
+ {
+ int newIndex = index + 1;
+ int thisParameterSize = 1;
+ Clazz referencedClass = null;
+
+ char c = descriptor.charAt(index);
+ switch (c)
+ {
+ case ClassConstants.TYPE_LONG:
+ case ClassConstants.TYPE_DOUBLE:
+ {
+ // Long and double primitive types.
+ thisParameterSize = 2;
+ break;
+ }
+ default:
+ {
+ // All other primitive types.
+ break;
+ }
+ case ClassConstants.TYPE_CLASS_START:
+ {
+ // Class types.
+ // Skip the class name.
+ newIndex = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, newIndex) + 1;
+ referencedClass = referencedClasses == null ? null :
+ referencedClasses[referenceClassIndex++];
+ break;
+ }
+ case ClassConstants.TYPE_ARRAY:
+ {
+ // Array types.
+ // Skip all array characters.
+ while ((c = descriptor.charAt(newIndex++)) == ClassConstants.TYPE_ARRAY) {}
+
+ if (c == ClassConstants.TYPE_CLASS_START)
+ {
+ // Skip the class type.
+ newIndex = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, newIndex) + 1;
+ referencedClass = referencedClasses == null ? null :
+ referencedClasses[referenceClassIndex++];
+ }
+ break;
+ }
+ case ClassConstants.METHOD_ARGUMENTS_CLOSE:
+ {
+ // End of the method parameters.
+ return;
+ }
+ }
+
+ parameterVisitor.visitParameter(clazz,
+ method,
+ parameterIndex++,
+ parameterCount,
+ parameterOffset,
+ parameterSize,
+ descriptor.substring(index, newIndex),
+ referencedClass);
+
+ // Continue with the next parameter.
+ index = newIndex;
+ parameterOffset += thisParameterSize;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassReferenceInitializer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassReferenceInitializer.java
new file mode 100644
index 0000000000..5a6bf8d81d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassReferenceInitializer.java
@@ -0,0 +1,587 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.visitor.*;
+
+
+/**
+ * This ClassVisitor initializes the references of all classes that
+ * it visits.
+ * <p>
+ * All class constant pool entries get direct references to the corresponding
+ * classes. These references make it more convenient to travel up and across
+ * the class hierarchy.
+ * <p>
+ * All field and method reference constant pool entries get direct references
+ * to the corresponding classes, fields, and methods.
+ * <p>
+ * All name and type constant pool entries get a list of direct references to
+ * the classes listed in the type.
+ * <p>
+ * This visitor optionally prints warnings if some items can't be found.
+ * <p>
+ * The class hierarchy must be initialized before using this visitor.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassReferenceInitializer
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ ConstantVisitor,
+ AttributeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor
+{
+ private final ClassPool programClassPool;
+ private final ClassPool libraryClassPool;
+ private final WarningPrinter missingClassWarningPrinter;
+ private final WarningPrinter missingProgramMemberWarningPrinter;
+ private final WarningPrinter missingLibraryMemberWarningPrinter;
+ private final WarningPrinter dependencyWarningPrinter;
+
+ private final MemberFinder memberFinder = new MemberFinder();
+
+
+ /**
+ * Creates a new ClassReferenceInitializer that initializes the references
+ * of all visited class files, optionally printing warnings if some classes
+ * or class members can't be found or if they are in the program class pool.
+ */
+ public ClassReferenceInitializer(ClassPool programClassPool,
+ ClassPool libraryClassPool,
+ WarningPrinter missingClassWarningPrinter,
+ WarningPrinter missingProgramMemberWarningPrinter,
+ WarningPrinter missingLibraryMemberWarningPrinter,
+ WarningPrinter dependencyWarningPrinter)
+ {
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ this.missingClassWarningPrinter = missingClassWarningPrinter;
+ this.missingProgramMemberWarningPrinter = missingProgramMemberWarningPrinter;
+ this.missingLibraryMemberWarningPrinter = missingLibraryMemberWarningPrinter;
+ this.dependencyWarningPrinter = dependencyWarningPrinter;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Initialize the constant pool entries.
+ programClass.constantPoolEntriesAccept(this);
+
+ // Initialize all fields and methods.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ // Initialize the attributes.
+ programClass.attributesAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Initialize all fields and methods.
+ libraryClass.fieldsAccept(this);
+ libraryClass.methodsAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ programField.referencedClass =
+ findReferencedClass(programClass,
+ programField.getDescriptor(programClass));
+
+ // Initialize the attributes.
+ programField.attributesAccept(programClass, this);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ programMethod.referencedClasses =
+ findReferencedClasses(programClass,
+ programMethod.getDescriptor(programClass));
+
+ // Initialize the attributes.
+ programMethod.attributesAccept(programClass, this);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ libraryField.referencedClass =
+ findReferencedClass(libraryClass,
+ libraryField.getDescriptor(libraryClass));
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ libraryMethod.referencedClasses =
+ findReferencedClasses(libraryClass,
+ libraryMethod.getDescriptor(libraryClass));
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Fill out the String class.
+ stringConstant.javaLangStringClass =
+ findClass(clazz, ClassConstants.NAME_JAVA_LANG_STRING);
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ invokeDynamicConstant.referencedClasses =
+ findReferencedClasses(clazz,
+ invokeDynamicConstant.getType(clazz));
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Fill out the MethodHandle class.
+ methodHandleConstant.javaLangInvokeMethodHandleClass =
+ findClass(clazz, ClassConstants.NAME_JAVA_LANG_INVOKE_METHOD_HANDLE);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ String className = refConstant.getClassName(clazz);
+
+ // Methods for array types should be found in the Object class.
+ if (ClassUtil.isInternalArrayType(className))
+ {
+ className = ClassConstants.NAME_JAVA_LANG_OBJECT;
+ }
+
+ // See if we can find the referenced class.
+ // Unresolved references are assumed to refer to library classes
+ // that will not change anyway.
+ Clazz referencedClass = findClass(clazz, className);
+
+ if (referencedClass != null)
+ {
+ String name = refConstant.getName(clazz);
+ String type = refConstant.getType(clazz);
+
+ boolean isFieldRef = refConstant.getTag() == ClassConstants.CONSTANT_Fieldref;
+
+ // See if we can find the referenced class member somewhere in the
+ // hierarchy.
+ refConstant.referencedMember = memberFinder.findMember(clazz,
+ referencedClass,
+ name,
+ type,
+ isFieldRef);
+ refConstant.referencedClass = memberFinder.correspondingClass();
+
+ if (refConstant.referencedMember == null)
+ {
+ // We haven't found the class member anywhere in the hierarchy.
+ boolean isProgramClass = referencedClass instanceof ProgramClass;
+
+ WarningPrinter missingMemberWarningPrinter = isProgramClass ?
+ missingProgramMemberWarningPrinter :
+ missingLibraryMemberWarningPrinter;
+
+ missingMemberWarningPrinter.print(clazz.getName(),
+ className,
+ "Warning: " +
+ ClassUtil.externalClassName(clazz.getName()) +
+ ": can't find referenced " +
+ (isFieldRef ?
+ "field '" + ClassUtil.externalFullFieldDescription(0, name, type) :
+ "method '" + ClassUtil.externalFullMethodDescription(className, 0, name, type)) +
+ "' in " +
+ (isProgramClass ?
+ "program" :
+ "library") +
+ " class " +
+ ClassUtil.externalClassName(className));
+ }
+ }
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Fill out the referenced class.
+ classConstant.referencedClass =
+ findClass(clazz, ClassUtil.internalClassNameFromClassType(classConstant.getName(clazz)));
+
+ // Fill out the Class class.
+ classConstant.javaLangClassClass =
+ findClass(clazz, ClassConstants.NAME_JAVA_LANG_CLASS);
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ // Fill out the MethodType class.
+ methodTypeConstant.javaLangInvokeMethodTypeClass =
+ findClass(clazz, ClassConstants.NAME_JAVA_LANG_INVOKE_METHOD_TYPE);
+
+ methodTypeConstant.referencedClasses =
+ findReferencedClasses(clazz,
+ methodTypeConstant.getType(clazz));
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ String enclosingClassName = enclosingMethodAttribute.getClassName(clazz);
+
+ // See if we can find the referenced class.
+ enclosingMethodAttribute.referencedClass =
+ findClass(clazz, enclosingClassName);
+
+ if (enclosingMethodAttribute.referencedClass != null)
+ {
+ // Is there an enclosing method? Otherwise it's just initialization
+ // code outside of the constructors.
+ if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
+ {
+ String name = enclosingMethodAttribute.getName(clazz);
+ String type = enclosingMethodAttribute.getType(clazz);
+
+ // See if we can find the method in the referenced class.
+ enclosingMethodAttribute.referencedMethod =
+ enclosingMethodAttribute.referencedClass.findMethod(name, type);
+
+ if (enclosingMethodAttribute.referencedMethod == null)
+ {
+ // We couldn't find the enclosing method.
+ String className = clazz.getName();
+
+ missingProgramMemberWarningPrinter.print(className,
+ enclosingClassName,
+ "Warning: " +
+ ClassUtil.externalClassName(className) +
+ ": can't find enclosing method '" +
+ ClassUtil.externalFullMethodDescription(enclosingClassName, 0, name, type) +
+ "' in program class " +
+ ClassUtil.externalClassName(enclosingClassName));
+ }
+ }
+ }
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Initialize the nested attributes.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Initialize the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Initialize the local variable types.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ signatureAttribute.referencedClasses =
+ findReferencedClasses(clazz,
+ signatureAttribute.getSignature(clazz));
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ // Initialize the annotations.
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Initialize the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Initialize the annotation.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ localVariableInfo.referencedClass =
+ findReferencedClass(clazz,
+ localVariableInfo.getDescriptor(clazz));
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ localVariableTypeInfo.referencedClasses =
+ findReferencedClasses(clazz,
+ localVariableTypeInfo.getSignature(clazz));
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ annotation.referencedClasses =
+ findReferencedClasses(clazz,
+ annotation.getType(clazz));
+
+ // Initialize the element values.
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ initializeElementValue(clazz, annotation, constantElementValue);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ initializeElementValue(clazz, annotation, enumConstantElementValue);
+
+ enumConstantElementValue.referencedClasses =
+ findReferencedClasses(clazz,
+ enumConstantElementValue.getTypeName(clazz));
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ initializeElementValue(clazz, annotation, classElementValue);
+
+ classElementValue.referencedClasses =
+ findReferencedClasses(clazz,
+ classElementValue.getClassName(clazz));
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ initializeElementValue(clazz, annotation, annotationElementValue);
+
+ // Initialize the annotation.
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ initializeElementValue(clazz, annotation, arrayElementValue);
+
+ // Initialize the element values.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ }
+
+
+ /**
+ * Initializes the referenced method of an element value, if any.
+ */
+ private void initializeElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue)
+ {
+ // See if we have a referenced class.
+ if (annotation != null &&
+ annotation.referencedClasses != null &&
+ elementValue.u2elementNameIndex != 0)
+ {
+ // See if we can find the method in the referenced class
+ // (ignoring the descriptor).
+ String name = elementValue.getMethodName(clazz);
+
+ Clazz referencedClass = annotation.referencedClasses[0];
+ elementValue.referencedClass = referencedClass;
+ elementValue.referencedMethod = referencedClass.findMethod(name, null);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the single class referenced by the given descriptor, or
+ * <code>null</code> if there isn't any useful reference.
+ */
+ private Clazz findReferencedClass(Clazz referencingClass,
+ String descriptor)
+ {
+ DescriptorClassEnumeration enumeration =
+ new DescriptorClassEnumeration(descriptor);
+
+ enumeration.nextFluff();
+
+ if (enumeration.hasMoreClassNames())
+ {
+ return findClass(referencingClass, enumeration.nextClassName());
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Returns an array of classes referenced by the given descriptor, or
+ * <code>null</code> if there aren't any useful references.
+ */
+ private Clazz[] findReferencedClasses(Clazz referencingClass,
+ String descriptor)
+ {
+ DescriptorClassEnumeration enumeration =
+ new DescriptorClassEnumeration(descriptor);
+
+ int classCount = enumeration.classCount();
+ if (classCount > 0)
+ {
+ Clazz[] referencedClasses = new Clazz[classCount];
+
+ boolean foundReferencedClasses = false;
+
+ for (int index = 0; index < classCount; index++)
+ {
+ String fluff = enumeration.nextFluff();
+ String name = enumeration.nextClassName();
+
+ Clazz referencedClass = findClass(referencingClass, name);
+
+ if (referencedClass != null)
+ {
+ referencedClasses[index] = referencedClass;
+ foundReferencedClasses = true;
+ }
+ }
+
+ if (foundReferencedClasses)
+ {
+ return referencedClasses;
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Returns the class with the given name, either for the program class pool
+ * or from the library class pool, or <code>null</code> if it can't be found.
+ */
+ private Clazz findClass(Clazz referencingClass, String name)
+ {
+ // Is it an array type?
+ if (ClassUtil.isInternalArrayType(name))
+ {
+ // Ignore any primitive array types.
+ if (!ClassUtil.isInternalClassType(name))
+ {
+ return null;
+ }
+
+ // Strip the array part.
+ name = ClassUtil.internalClassNameFromClassType(name);
+ }
+
+ // First look for the class in the program class pool.
+ Clazz clazz = programClassPool.getClass(name);
+
+ // Otherwise look for the class in the library class pool.
+ if (clazz == null)
+ {
+ clazz = libraryClassPool.getClass(name);
+
+ if (clazz == null &&
+ missingClassWarningPrinter != null)
+ {
+ // We didn't find the superclass or interface. Print a warning.
+ String referencingClassName = referencingClass.getName();
+
+ missingClassWarningPrinter.print(referencingClassName,
+ name,
+ "Warning: " +
+ ClassUtil.externalClassName(referencingClassName) +
+ ": can't find referenced class " +
+ ClassUtil.externalClassName(name));
+ }
+ }
+ else if (dependencyWarningPrinter != null)
+ {
+ // The superclass or interface was found in the program class pool.
+ // Print a warning.
+ String referencingClassName = referencingClass.getName();
+
+ dependencyWarningPrinter.print(referencingClassName,
+ name,
+ "Warning: library class " +
+ ClassUtil.externalClassName(referencingClassName) +
+ " depends on program class " +
+ ClassUtil.externalClassName(name));
+ }
+
+ return clazz;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassSubHierarchyInitializer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
new file mode 100644
index 0000000000..ef5df7e9f7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
@@ -0,0 +1,77 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor adds all classes that it visits to the list of subclasses
+ * of their superclass. These subclass lists make it more convenient to travel
+ *
+ * @author Eric Lafortune
+ */
+public class ClassSubHierarchyInitializer
+implements ClassVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Add this class to the subclasses of its superclass.
+ addSubclass(programClass, programClass.getSuperClass());
+
+ // Add this class to the subclasses of its interfaces.
+ for (int index = 0; index < programClass.u2interfacesCount; index++)
+ {
+ addSubclass(programClass, programClass.getInterface(index));
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Add this class to the subclasses of its superclass,
+ addSubclass(libraryClass, libraryClass.superClass);
+
+ // Add this class to the subclasses of its interfaces.
+ Clazz[] interfaceClasses = libraryClass.interfaceClasses;
+ if (interfaceClasses != null)
+ {
+ for (int index = 0; index < interfaceClasses.length; index++)
+ {
+ // Add this class to the subclasses of the interface class.
+ addSubclass(libraryClass, interfaceClasses[index]);
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ private void addSubclass(Clazz subclass, Clazz clazz)
+ {
+ if (clazz != null)
+ {
+ clazz.addSubClass(subclass);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java
new file mode 100644
index 0000000000..b5b5a08267
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java
@@ -0,0 +1,163 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor initializes the superclass hierarchy of all classes that
+ * it visits.
+ * <p>
+ * Visited library classes get direct references to their superclasses and
+ * interfaces, replacing the superclass names and interface names. The direct
+ * references are equivalent to the names, but they are more efficient to work
+ * with.
+ * <p>
+ * This visitor optionally prints warnings if some superclasses can't be found
+ * or if they are in the program class pool.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassSuperHierarchyInitializer
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor
+{
+ private final ClassPool programClassPool;
+ private final ClassPool libraryClassPool;
+ private final WarningPrinter missingWarningPrinter;
+ private final WarningPrinter dependencyWarningPrinter;
+
+
+ /**
+ * Creates a new ClassSuperHierarchyInitializer that initializes the super
+ * hierarchy of all visited class files, optionally printing warnings if
+ * some classes can't be found or if they are in the program class pool.
+ */
+ public ClassSuperHierarchyInitializer(ClassPool programClassPool,
+ ClassPool libraryClassPool,
+ WarningPrinter missingWarningPrinter,
+ WarningPrinter dependencyWarningPrinter)
+ {
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ this.missingWarningPrinter = missingWarningPrinter;
+ this.dependencyWarningPrinter = dependencyWarningPrinter;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Link to the super class.
+ programClass.superClassConstantAccept(this);
+
+ // Link to the interfaces.
+ programClass.interfaceConstantsAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ String className = libraryClass.getName();
+
+ // Link to the super class.
+ String superClassName = libraryClass.superClassName;
+ if (superClassName != null)
+ {
+ // Keep a reference to the superclass.
+ libraryClass.superClass = findClass(className, superClassName);
+ }
+
+ // Link to the interfaces.
+ if (libraryClass.interfaceNames != null)
+ {
+ String[] interfaceNames = libraryClass.interfaceNames;
+ Clazz[] interfaceClasses = new Clazz[interfaceNames.length];
+
+ for (int index = 0; index < interfaceNames.length; index++)
+ {
+ // Keep a reference to the interface class.
+ interfaceClasses[index] =
+ findClass(className, interfaceNames[index]);
+ }
+
+ libraryClass.interfaceClasses = interfaceClasses;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.referencedClass =
+ findClass(clazz.getName(), classConstant.getName(clazz));
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the class with the given name, either for the program class pool
+ * or from the library class pool, or <code>null</code> if it can't be found.
+ */
+ private Clazz findClass(String referencingClassName, String name)
+ {
+ // First look for the class in the program class pool.
+ Clazz clazz = programClassPool.getClass(name);
+
+ // Otherwise look for the class in the library class pool.
+ if (clazz == null)
+ {
+ clazz = libraryClassPool.getClass(name);
+
+ if (clazz == null &&
+ missingWarningPrinter != null)
+ {
+ // We didn't find the superclass or interface. Print a warning.
+ missingWarningPrinter.print(referencingClassName,
+ name,
+ "Warning: " +
+ ClassUtil.externalClassName(referencingClassName) +
+ ": can't find superclass or interface " +
+ ClassUtil.externalClassName(name));
+ }
+ }
+ else if (dependencyWarningPrinter != null)
+ {
+ // The superclass or interface was found in the program class pool.
+ // Print a warning.
+ dependencyWarningPrinter.print(referencingClassName,
+ name,
+ "Warning: library class " +
+ ClassUtil.externalClassName(referencingClassName) +
+ " extends or implements program class " +
+ ClassUtil.externalClassName(name));
+ }
+
+ return clazz;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassUtil.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassUtil.java
new file mode 100644
index 0000000000..439c65ad55
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ClassUtil.java
@@ -0,0 +1,1311 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+
+import java.util.List;
+
+/**
+ * Utility methods for converting between internal and external representations
+ * of names and descriptions.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassUtil
+{
+ private static final String EMPTY_STRING = "";
+
+
+ /**
+ * Checks whether the given class magic number is correct.
+ * @param magicNumber the magic number.
+ * @throws UnsupportedOperationException when the magic number is incorrect.
+ */
+ public static void checkMagicNumber(int magicNumber) throws UnsupportedOperationException
+ {
+ if (magicNumber != ClassConstants.MAGIC)
+ {
+ throw new UnsupportedOperationException("Invalid magic number ["+Integer.toHexString(magicNumber)+"] in class");
+ }
+ }
+
+
+ /**
+ * Returns the combined class version number.
+ * @param majorVersion the major part of the class version number.
+ * @param minorVersion the minor part of the class version number.
+ * @return the combined class version number.
+ */
+ public static int internalClassVersion(int majorVersion, int minorVersion)
+ {
+ return (majorVersion << 16) | minorVersion;
+ }
+
+
+ /**
+ * Returns the major part of the given class version number.
+ * @param classVersion the combined class version number.
+ * @return the major part of the class version number.
+ */
+ public static int internalMajorClassVersion(int classVersion)
+ {
+ return classVersion >>> 16;
+ }
+
+
+ /**
+ * Returns the internal class version number.
+ * @param classVersion the external class version number.
+ * @return the internal class version number.
+ */
+ public static int internalMinorClassVersion(int classVersion)
+ {
+ return classVersion & 0xffff;
+ }
+
+
+ /**
+ * Returns the internal class version number.
+ * @param classVersion the external class version number.
+ * @return the internal class version number.
+ */
+ public static int internalClassVersion(String classVersion)
+ {
+ return
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_0) ||
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_1) ? ClassConstants.CLASS_VERSION_1_0 :
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_2) ? ClassConstants.CLASS_VERSION_1_2 :
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_3) ? ClassConstants.CLASS_VERSION_1_3 :
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_4) ? ClassConstants.CLASS_VERSION_1_4 :
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_5_ALIAS) ||
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_5) ? ClassConstants.CLASS_VERSION_1_5 :
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_6_ALIAS) ||
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_6) ? ClassConstants.CLASS_VERSION_1_6 :
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_7_ALIAS) ||
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_7) ? ClassConstants.CLASS_VERSION_1_7 :
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_8_ALIAS) ||
+ classVersion.equals(JavaConstants.CLASS_VERSION_1_8) ? ClassConstants.CLASS_VERSION_1_8 :
+ 0;
+ }
+
+
+ /**
+ * Returns the minor part of the given class version number.
+ * @param classVersion the combined class version number.
+ * @return the minor part of the class version number.
+ */
+ public static String externalClassVersion(int classVersion)
+ {
+ switch (classVersion)
+ {
+ case ClassConstants.CLASS_VERSION_1_0: return JavaConstants.CLASS_VERSION_1_0;
+ case ClassConstants.CLASS_VERSION_1_2: return JavaConstants.CLASS_VERSION_1_2;
+ case ClassConstants.CLASS_VERSION_1_3: return JavaConstants.CLASS_VERSION_1_3;
+ case ClassConstants.CLASS_VERSION_1_4: return JavaConstants.CLASS_VERSION_1_4;
+ case ClassConstants.CLASS_VERSION_1_5: return JavaConstants.CLASS_VERSION_1_5;
+ case ClassConstants.CLASS_VERSION_1_6: return JavaConstants.CLASS_VERSION_1_6;
+ case ClassConstants.CLASS_VERSION_1_7: return JavaConstants.CLASS_VERSION_1_7;
+ case ClassConstants.CLASS_VERSION_1_8: return JavaConstants.CLASS_VERSION_1_8;
+ default: return null;
+ }
+ }
+
+
+ /**
+ * Checks whether the given class version number is supported.
+ * @param classVersion the combined class version number.
+ * @throws UnsupportedOperationException when the version is not supported.
+ */
+ public static void checkVersionNumbers(int classVersion) throws UnsupportedOperationException
+ {
+ if (classVersion < ClassConstants.CLASS_VERSION_1_0 ||
+ classVersion > ClassConstants.CLASS_VERSION_1_8)
+ {
+ throw new UnsupportedOperationException("Unsupported class version number ["+
+ internalMajorClassVersion(classVersion)+"."+
+ internalMinorClassVersion(classVersion)+"] (maximum "+
+ ClassConstants.CLASS_VERSION_1_8_MAJOR+"."+
+ ClassConstants.CLASS_VERSION_1_8_MINOR+", Java "+
+ JavaConstants.CLASS_VERSION_1_8+")");
+ }
+ }
+
+
+ /**
+ * Converts an external class name into an internal class name.
+ * @param externalClassName the external class name,
+ * e.g. "<code>java.lang.Object</code>"
+ * @return the internal class name,
+ * e.g. "<code>java/lang/Object</code>".
+ */
+ public static String internalClassName(String externalClassName)
+ {
+ return externalClassName.replace(JavaConstants.PACKAGE_SEPARATOR,
+ ClassConstants.PACKAGE_SEPARATOR);
+ }
+
+
+ /**
+ * Converts an internal class description into an external class description.
+ * @param accessFlags the access flags of the class.
+ * @param internalClassName the internal class name,
+ * e.g. "<code>java/lang/Object</code>".
+ * @return the external class description,
+ * e.g. "<code>public java.lang.Object</code>".
+ */
+ public static String externalFullClassDescription(int accessFlags,
+ String internalClassName)
+ {
+ return externalClassAccessFlags(accessFlags) +
+ externalClassName(internalClassName);
+ }
+
+
+ /**
+ * Converts an internal class name into an external class name.
+ * @param internalClassName the internal class name,
+ * e.g. "<code>java/lang/Object</code>".
+ * @return the external class name,
+ * e.g. "<code>java.lang.Object</code>".
+ */
+ public static String externalClassName(String internalClassName)
+ {
+ return //internalClassName.startsWith(ClassConstants.PACKAGE_JAVA_LANG) &&
+ //internalClassName.indexOf(ClassConstants.PACKAGE_SEPARATOR, ClassConstants.PACKAGE_JAVA_LANG.length() + 1) < 0 ?
+ //internalClassName.substring(ClassConstants.PACKAGE_JAVA_LANG.length()) :
+ internalClassName.replace(ClassConstants.PACKAGE_SEPARATOR,
+ JavaConstants.PACKAGE_SEPARATOR);
+ }
+
+
+ /**
+ * Returns the external base type of an external array type, dropping any
+ * array brackets.
+ * @param externalArrayType the external array type,
+ * e.g. "<code>java.lang.Object[][]</code>"
+ * @return the external base type,
+ * e.g. "<code>java.lang.Object</code>".
+ */
+ public static String externalBaseType(String externalArrayType)
+ {
+ int index = externalArrayType.indexOf(JavaConstants.TYPE_ARRAY);
+ return index >= 0 ?
+ externalArrayType.substring(0, index) :
+ externalArrayType;
+ }
+
+
+ /**
+ * Returns the external short class name of an external class name, dropping
+ * the package specification.
+ * @param externalClassName the external class name,
+ * e.g. "<code>java.lang.Object</code>"
+ * @return the external short class name,
+ * e.g. "<code>Object</code>".
+ */
+ public static String externalShortClassName(String externalClassName)
+ {
+ int index = externalClassName.lastIndexOf(JavaConstants.PACKAGE_SEPARATOR);
+ return externalClassName.substring(index+1);
+ }
+
+
+ /**
+ * Returns whether the given internal type is an array type.
+ * @param internalType the internal type,
+ * e.g. "<code>[[Ljava/lang/Object;</code>".
+ * @return <code>true</code> if the given type is an array type,
+ * <code>false</code> otherwise.
+ */
+ public static boolean isInternalArrayType(String internalType)
+ {
+ return internalType.length() > 1 &&
+ internalType.charAt(0) == ClassConstants.TYPE_ARRAY;
+ }
+
+
+ /**
+ * Returns the number of dimensions of the given internal type.
+ * @param internalType the internal type,
+ * e.g. "<code>[[Ljava/lang/Object;</code>".
+ * @return the number of dimensions, e.g. 2.
+ */
+ public static int internalArrayTypeDimensionCount(String internalType)
+ {
+ int dimensions = 0;
+ while (internalType.charAt(dimensions) == ClassConstants.TYPE_ARRAY)
+ {
+ dimensions++;
+ }
+
+ return dimensions;
+ }
+
+
+ /**
+ * Returns whether the given internal class name is one of the interfaces
+ * that is implemented by all array types. These class names are
+ * "<code>java/lang/Object</code>", "<code>java/lang/Cloneable</code>", and
+ * "<code>java/io/Serializable</code>"
+ * @param internalClassName the internal class name,
+ * e.g. "<code>java/lang/Object</code>".
+ * @return <code>true</code> if the given type is an array interface name,
+ * <code>false</code> otherwise.
+ */
+ public static boolean isInternalArrayInterfaceName(String internalClassName)
+ {
+ return ClassConstants.NAME_JAVA_LANG_OBJECT.equals(internalClassName) ||
+ ClassConstants.NAME_JAVA_LANG_CLONEABLE.equals(internalClassName) ||
+ ClassConstants.NAME_JAVA_IO_SERIALIZABLE.equals(internalClassName);
+ }
+
+
+ /**
+ * Returns whether the given internal type is a plain primitive type
+ * (not void).
+ * @param internalType the internal type,
+ * e.g. "<code>I</code>".
+ * @return <code>true</code> if the given type is a class type,
+ * <code>false</code> otherwise.
+ */
+ public static boolean isInternalPrimitiveType(char internalType)
+ {
+ return internalType == ClassConstants.TYPE_BOOLEAN ||
+ internalType == ClassConstants.TYPE_BYTE ||
+ internalType == ClassConstants.TYPE_CHAR ||
+ internalType == ClassConstants.TYPE_SHORT ||
+ internalType == ClassConstants.TYPE_INT ||
+ internalType == ClassConstants.TYPE_FLOAT ||
+ internalType == ClassConstants.TYPE_LONG ||
+ internalType == ClassConstants.TYPE_DOUBLE;
+ }
+
+
+ /**
+ * Returns whether the given internal type is a primitive Category 2 type.
+ * @param internalType the internal type,
+ * e.g. "<code>L</code>".
+ * @return <code>true</code> if the given type is a Category 2 type,
+ * <code>false</code> otherwise.
+ */
+ public static boolean isInternalCategory2Type(String internalType)
+ {
+ return internalType.length() == 1 &&
+ (internalType.charAt(0) == ClassConstants.TYPE_LONG ||
+ internalType.charAt(0) == ClassConstants.TYPE_DOUBLE);
+ }
+
+
+ /**
+ * Returns whether the given internal type is a plain class type
+ * (including an array type of a plain class type).
+ * @param internalType the internal type,
+ * e.g. "<code>Ljava/lang/Object;</code>".
+ * @return <code>true</code> if the given type is a class type,
+ * <code>false</code> otherwise.
+ */
+ public static boolean isInternalClassType(String internalType)
+ {
+ int length = internalType.length();
+ return length > 1 &&
+// internalType.charAt(0) == ClassConstants.TYPE_CLASS_START &&
+ internalType.charAt(length-1) == ClassConstants.TYPE_CLASS_END;
+ }
+
+
+ /**
+ * Returns the internal type of a given class name.
+ * @param internalClassName the internal class name,
+ * e.g. "<code>java/lang/Object</code>".
+ * @return the internal type,
+ * e.g. "<code>Ljava/lang/Object;</code>".
+ */
+ public static String internalTypeFromClassName(String internalClassName)
+ {
+ return internalArrayTypeFromClassName(internalClassName, 0);
+ }
+
+
+ /**
+ * Returns the internal array type of a given class name with a given number
+ * of dimensions. If the number of dimensions is 0, the class name itself is
+ * returned.
+ * @param internalClassName the internal class name,
+ * e.g. "<code>java/lang/Object</code>".
+ * @param dimensionCount the number of array dimensions.
+ * @return the internal array type of the array elements,
+ * e.g. "<code>Ljava/lang/Object;</code>".
+ */
+ public static String internalArrayTypeFromClassName(String internalClassName,
+ int dimensionCount)
+ {
+ StringBuffer buffer = new StringBuffer(internalClassName.length() + dimensionCount + 2);
+
+ for (int dimension = 0; dimension < dimensionCount; dimension++)
+ {
+ buffer.append(ClassConstants.TYPE_ARRAY);
+ }
+
+ return buffer.append(ClassConstants.TYPE_CLASS_START)
+ .append(internalClassName)
+ .append(ClassConstants.TYPE_CLASS_END)
+ .toString();
+ }
+
+
+ /**
+ * Returns the internal element type of a given internal array type.
+ * @param internalArrayType the internal array type,
+ * e.g. "<code>[[Ljava/lang/Object;</code>" or
+ * "<code>[I</code>".
+ * @return the internal type of the array elements,
+ * e.g. "<code>Ljava/lang/Object;</code>" or
+ * "<code>I</code>".
+ */
+ public static String internalTypeFromArrayType(String internalArrayType)
+ {
+ int index = internalArrayType.lastIndexOf(ClassConstants.TYPE_ARRAY);
+ return internalArrayType.substring(index+1);
+ }
+
+
+ /**
+ * Returns the internal class name of a given internal class type
+ * (including an array type). Types involving primitive types are returned
+ * unchanged.
+ * @param internalClassType the internal class type,
+ * e.g. "<code>[Ljava/lang/Object;</code>",
+ * "<code>Ljava/lang/Object;</code>", or
+ * "<code>java/lang/Object</code>".
+ * @return the internal class name,
+ * e.g. "<code>java/lang/Object</code>".
+ */
+ public static String internalClassNameFromClassType(String internalClassType)
+ {
+ return isInternalClassType(internalClassType) ?
+ internalClassType.substring(internalClassType.indexOf(ClassConstants.TYPE_CLASS_START)+1,
+ internalClassType.length()-1) :
+ internalClassType;
+ }
+
+
+ /**
+ * Returns the internal class name of any given internal descriptor type,
+ * disregarding array prefixes.
+ * @param internalClassType the internal class type,
+ * e.g. "<code>Ljava/lang/Object;</code>" or
+ * "<code>[[I</code>".
+ * @return the internal class name,
+ * e.g. "<code>java/lang/Object</code>" or
+ * <code>null</code>.
+ */
+ public static String internalClassNameFromType(String internalClassType)
+ {
+ if (!isInternalClassType(internalClassType))
+ {
+ return null;
+ }
+
+ // Is it an array type?
+ if (isInternalArrayType(internalClassType))
+ {
+ internalClassType = internalTypeFromArrayType(internalClassType);
+ }
+
+ return internalClassNameFromClassType(internalClassType);
+ }
+
+
+ /**
+ * Returns whether the given method name refers to a class initializer or
+ * an instance initializer.
+ * @param internalMethodName the internal method name,
+ * e.g. "<code>&lt;clinit&gt;</code>".
+ * @return whether the method name refers to an initializer,
+ * e.g. <code>true</code>.
+ */
+ public static boolean isInitializer(String internalMethodName)
+ {
+ return internalMethodName.equals(ClassConstants.METHOD_NAME_CLINIT) ||
+ internalMethodName.equals(ClassConstants.METHOD_NAME_INIT);
+ }
+
+
+ /**
+ * Returns the internal type of the given internal method descriptor.
+ * @param internalMethodDescriptor the internal method descriptor,
+ * e.g. "<code>(II)Z</code>".
+ * @return the internal return type,
+ * e.g. "<code>Z</code>".
+ */
+ public static String internalMethodReturnType(String internalMethodDescriptor)
+ {
+ int index = internalMethodDescriptor.indexOf(ClassConstants.METHOD_ARGUMENTS_CLOSE);
+ return internalMethodDescriptor.substring(index + 1);
+ }
+
+
+ /**
+ * Returns the number of parameters of the given internal method descriptor.
+ * @param internalMethodDescriptor the internal method descriptor,
+ * e.g. "<code>(ID)Z</code>".
+ * @return the number of parameters,
+ * e.g. 2.
+ */
+ public static int internalMethodParameterCount(String internalMethodDescriptor)
+ {
+ int counter = 0;
+ int index = 1;
+
+ while (true)
+ {
+ char c = internalMethodDescriptor.charAt(index++);
+ switch (c)
+ {
+ case ClassConstants.TYPE_ARRAY:
+ {
+ // Just ignore all array characters.
+ break;
+ }
+ case ClassConstants.TYPE_CLASS_START:
+ {
+ counter++;
+
+ // Skip the class name.
+ index = internalMethodDescriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1;
+ break;
+ }
+ default:
+ {
+ counter++;
+ break;
+ }
+ case ClassConstants.METHOD_ARGUMENTS_CLOSE:
+ {
+ return counter;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Returns the size taken up on the stack by the parameters of the given
+ * internal method descriptor. This accounts for long and double parameters
+ * taking up two entries.
+ * @param internalMethodDescriptor the internal method descriptor,
+ * e.g. "<code>(ID)Z</code>".
+ * @return the size taken up on the stack,
+ * e.g. 3.
+ */
+ public static int internalMethodParameterSize(String internalMethodDescriptor)
+ {
+ return internalMethodParameterSize(internalMethodDescriptor, true);
+ }
+
+
+ /**
+ * Returns the size taken up on the stack by the parameters of the given
+ * internal method descriptor. This accounts for long and double parameters
+ * taking up two entries, and a non-static method taking up an additional
+ * entry.
+ * @param internalMethodDescriptor the internal method descriptor,
+ * e.g. "<code>(ID)Z</code>".
+ * @param accessFlags the access flags of the method,
+ * e.g. 0.
+ * @return the size taken up on the stack,
+ * e.g. 4.
+ */
+ public static int internalMethodParameterSize(String internalMethodDescriptor,
+ int accessFlags)
+ {
+ return internalMethodParameterSize(internalMethodDescriptor,
+ (accessFlags & ClassConstants.ACC_STATIC) != 0);
+ }
+
+
+ /**
+ * Returns the size taken up on the stack by the parameters of the given
+ * internal method descriptor. This accounts for long and double parameters
+ * taking up two spaces, and a non-static method taking up an additional
+ * entry.
+ * @param internalMethodDescriptor the internal method descriptor,
+ * e.g. "<code>(ID)Z</code>".
+ * @param isStatic specifies whether the method is static,
+ * e.g. false.
+ * @return the size taken up on the stack,
+ * e.g. 4.
+ */
+ public static int internalMethodParameterSize(String internalMethodDescriptor,
+ boolean isStatic)
+ {
+ int size = isStatic ? 0 : 1;
+ int index = 1;
+
+ while (true)
+ {
+ char c = internalMethodDescriptor.charAt(index++);
+ switch (c)
+ {
+ case ClassConstants.TYPE_LONG:
+ case ClassConstants.TYPE_DOUBLE:
+ {
+ size += 2;
+ break;
+ }
+ case ClassConstants.TYPE_CLASS_START:
+ {
+ size++;
+
+ // Skip the class name.
+ index = internalMethodDescriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1;
+ break;
+ }
+ case ClassConstants.TYPE_ARRAY:
+ {
+ size++;
+
+ // Skip all array characters.
+ while ((c = internalMethodDescriptor.charAt(index++)) == ClassConstants.TYPE_ARRAY) {}
+
+ if (c == ClassConstants.TYPE_CLASS_START)
+ {
+ // Skip the class type.
+ index = internalMethodDescriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1;
+ }
+ break;
+ }
+ default:
+ {
+ size++;
+ break;
+ }
+ case ClassConstants.METHOD_ARGUMENTS_CLOSE:
+ {
+ return size;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Returns the size taken up on the stack by the given internal type.
+ * The size is 1, except for long and double types, for which it is 2,
+ * and for the void type, for which 0 is returned.
+ * @param internalType the internal type,
+ * e.g. "<code>I</code>".
+ * @return the size taken up on the stack,
+ * e.g. 1.
+ */
+ public static int internalTypeSize(String internalType)
+ {
+ if (internalType.length() == 1)
+ {
+ char internalPrimitiveType = internalType.charAt(0);
+ if (internalPrimitiveType == ClassConstants.TYPE_LONG ||
+ internalPrimitiveType == ClassConstants.TYPE_DOUBLE)
+ {
+ return 2;
+ }
+ else if (internalPrimitiveType == ClassConstants.TYPE_VOID)
+ {
+ return 0;
+ }
+ }
+
+ return 1;
+ }
+
+
+ /**
+ * Converts an external type into an internal type.
+ * @param externalType the external type,
+ * e.g. "<code>java.lang.Object[][]</code>" or
+ * "<code>int[]</code>".
+ * @return the internal type,
+ * e.g. "<code>[[Ljava/lang/Object;</code>" or
+ * "<code>[I</code>".
+ */
+ public static String internalType(String externalType)
+ {
+ // Strip the array part, if any.
+ int dimensionCount = externalArrayTypeDimensionCount(externalType);
+ if (dimensionCount > 0)
+ {
+ externalType = externalType.substring(0, externalType.length() - dimensionCount * JavaConstants.TYPE_ARRAY.length());
+ }
+
+ // Analyze the actual type part.
+ char internalTypeChar =
+ externalType.equals(JavaConstants.TYPE_VOID ) ? ClassConstants.TYPE_VOID :
+ externalType.equals(JavaConstants.TYPE_BOOLEAN) ? ClassConstants.TYPE_BOOLEAN :
+ externalType.equals(JavaConstants.TYPE_BYTE ) ? ClassConstants.TYPE_BYTE :
+ externalType.equals(JavaConstants.TYPE_CHAR ) ? ClassConstants.TYPE_CHAR :
+ externalType.equals(JavaConstants.TYPE_SHORT ) ? ClassConstants.TYPE_SHORT :
+ externalType.equals(JavaConstants.TYPE_INT ) ? ClassConstants.TYPE_INT :
+ externalType.equals(JavaConstants.TYPE_FLOAT ) ? ClassConstants.TYPE_FLOAT :
+ externalType.equals(JavaConstants.TYPE_LONG ) ? ClassConstants.TYPE_LONG :
+ externalType.equals(JavaConstants.TYPE_DOUBLE ) ? ClassConstants.TYPE_DOUBLE :
+ externalType.equals("%" ) ? '%' :
+ (char)0;
+
+ String internalType =
+ internalTypeChar != 0 ? String.valueOf(internalTypeChar) :
+ ClassConstants.TYPE_CLASS_START +
+ internalClassName(externalType) +
+ ClassConstants.TYPE_CLASS_END;
+
+ // Prepend the array part, if any.
+ for (int count = 0; count < dimensionCount; count++)
+ {
+ internalType = ClassConstants.TYPE_ARRAY + internalType;
+ }
+
+ return internalType;
+ }
+
+
+ /**
+ * Returns the number of dimensions of the given external type.
+ * @param externalType the external type,
+ * e.g. "<code>[[Ljava/lang/Object;</code>".
+ * @return the number of dimensions, e.g. 2.
+ */
+ public static int externalArrayTypeDimensionCount(String externalType)
+ {
+ int dimensions = 0;
+ int length = JavaConstants.TYPE_ARRAY.length();
+ int offset = externalType.length() - length;
+ while (externalType.regionMatches(offset,
+ JavaConstants.TYPE_ARRAY,
+ 0,
+ length))
+ {
+ dimensions++;
+ offset -= length;
+ }
+
+ return dimensions;
+ }
+
+
+ /**
+ * Converts an internal type into an external type.
+ * @param internalType the internal type,
+ * e.g. "<code>[[Ljava/lang/Object;</code>" or
+ * "<code>[I</code>".
+ * @return the external type,
+ * e.g. "<code>java.lang.Object[][]</code>" or
+ * "<code>int[]</code>".
+ */
+ public static String externalType(String internalType)
+ {
+ // Strip the array part, if any.
+ int dimensionCount = internalArrayTypeDimensionCount(internalType);
+ if (dimensionCount > 0)
+ {
+ internalType = internalType.substring(dimensionCount);
+ }
+
+ // Analyze the actual type part.
+ char internalTypeChar = internalType.charAt(0);
+
+ String externalType =
+ internalTypeChar == ClassConstants.TYPE_VOID ? JavaConstants.TYPE_VOID :
+ internalTypeChar == ClassConstants.TYPE_BOOLEAN ? JavaConstants.TYPE_BOOLEAN :
+ internalTypeChar == ClassConstants.TYPE_BYTE ? JavaConstants.TYPE_BYTE :
+ internalTypeChar == ClassConstants.TYPE_CHAR ? JavaConstants.TYPE_CHAR :
+ internalTypeChar == ClassConstants.TYPE_SHORT ? JavaConstants.TYPE_SHORT :
+ internalTypeChar == ClassConstants.TYPE_INT ? JavaConstants.TYPE_INT :
+ internalTypeChar == ClassConstants.TYPE_FLOAT ? JavaConstants.TYPE_FLOAT :
+ internalTypeChar == ClassConstants.TYPE_LONG ? JavaConstants.TYPE_LONG :
+ internalTypeChar == ClassConstants.TYPE_DOUBLE ? JavaConstants.TYPE_DOUBLE :
+ internalTypeChar == '%' ? "%" :
+ internalTypeChar == ClassConstants.TYPE_CLASS_START ? externalClassName(internalType.substring(1, internalType.indexOf(ClassConstants.TYPE_CLASS_END))) :
+ null;
+
+ if (externalType == null)
+ {
+ throw new IllegalArgumentException("Unknown type ["+internalType+"]");
+ }
+
+ // Append the array part, if any.
+ for (int count = 0; count < dimensionCount; count++)
+ {
+ externalType += JavaConstants.TYPE_ARRAY;
+ }
+
+ return externalType;
+ }
+
+
+ /**
+ * Returns whether the given internal descriptor String represents a method
+ * descriptor.
+ * @param internalDescriptor the internal descriptor String,
+ * e.g. "<code>(II)Z</code>".
+ * @return <code>true</code> if the given String is a method descriptor,
+ * <code>false</code> otherwise.
+ */
+ public static boolean isInternalMethodDescriptor(String internalDescriptor)
+ {
+ return internalDescriptor.charAt(0) == ClassConstants.METHOD_ARGUMENTS_OPEN;
+ }
+
+
+ /**
+ * Returns whether the given member String represents an external method
+ * name with arguments.
+ * @param externalMemberNameAndArguments the external member String,
+ * e.g. "<code>myField</code>" or
+ * e.g. "<code>myMethod(int,int)</code>".
+ * @return <code>true</code> if the given String refers to a method,
+ * <code>false</code> otherwise.
+ */
+ public static boolean isExternalMethodNameAndArguments(String externalMemberNameAndArguments)
+ {
+ return externalMemberNameAndArguments.indexOf(JavaConstants.METHOD_ARGUMENTS_OPEN) > 0;
+ }
+
+
+ /**
+ * Returns the name part of the given external method name and arguments.
+ * @param externalMethodNameAndArguments the external method name and arguments,
+ * e.g. "<code>myMethod(int,int)</code>".
+ * @return the name part of the String, e.g. "<code>myMethod</code>".
+ */
+ public static String externalMethodName(String externalMethodNameAndArguments)
+ {
+ ExternalTypeEnumeration externalTypeEnumeration =
+ new ExternalTypeEnumeration(externalMethodNameAndArguments);
+
+ return externalTypeEnumeration.methodName();
+ }
+
+
+ /**
+ * Converts the given external method return type and name and arguments to
+ * an internal method descriptor.
+ * @param externalReturnType the external method return type,
+ * e.g. "<code>boolean</code>".
+ * @param externalMethodNameAndArguments the external method name and arguments,
+ * e.g. "<code>myMethod(int,int)</code>".
+ * @return the internal method descriptor,
+ * e.g. "<code>(II)Z</code>".
+ */
+ public static String internalMethodDescriptor(String externalReturnType,
+ String externalMethodNameAndArguments)
+ {
+ StringBuffer internalMethodDescriptor = new StringBuffer();
+ internalMethodDescriptor.append(ClassConstants.METHOD_ARGUMENTS_OPEN);
+
+ ExternalTypeEnumeration externalTypeEnumeration =
+ new ExternalTypeEnumeration(externalMethodNameAndArguments);
+
+ while (externalTypeEnumeration.hasMoreTypes())
+ {
+ internalMethodDescriptor.append(internalType(externalTypeEnumeration.nextType()));
+ }
+
+ internalMethodDescriptor.append(ClassConstants.METHOD_ARGUMENTS_CLOSE);
+ internalMethodDescriptor.append(internalType(externalReturnType));
+
+ return internalMethodDescriptor.toString();
+ }
+
+
+ /**
+ * Converts the given external method return type and List of arguments to
+ * an internal method descriptor.
+ * @param externalReturnType the external method return type,
+ * e.g. "<code>boolean</code>".
+ * @param externalArguments the external method arguments,
+ * e.g. <code>{ "int", "int" }</code>.
+ * @return the internal method descriptor,
+ * e.g. "<code>(II)Z</code>".
+ */
+ public static String internalMethodDescriptor(String externalReturnType,
+ List externalArguments)
+ {
+ StringBuffer internalMethodDescriptor = new StringBuffer();
+ internalMethodDescriptor.append(ClassConstants.METHOD_ARGUMENTS_OPEN);
+
+ for (int index = 0; index < externalArguments.size(); index++)
+ {
+ internalMethodDescriptor.append(internalType((String)externalArguments.get(index)));
+ }
+
+ internalMethodDescriptor.append(ClassConstants.METHOD_ARGUMENTS_CLOSE);
+ internalMethodDescriptor.append(internalType(externalReturnType));
+
+ return internalMethodDescriptor.toString();
+ }
+
+
+ /**
+ * Converts an internal field description into an external full field description.
+ * @param accessFlags the access flags of the field.
+ * @param fieldName the field name,
+ * e.g. "<code>myField</code>".
+ * @param internalFieldDescriptor the internal field descriptor,
+ * e.g. "<code>Z</code>".
+ * @return the external full field description,
+ * e.g. "<code>public boolean myField</code>".
+ */
+ public static String externalFullFieldDescription(int accessFlags,
+ String fieldName,
+ String internalFieldDescriptor)
+ {
+ return externalFieldAccessFlags(accessFlags) +
+ externalType(internalFieldDescriptor) +
+ ' ' +
+ fieldName;
+ }
+
+
+ /**
+ * Converts an internal method description into an external full method description.
+ * @param internalClassName the internal name of the class of the method,
+ * e.g. "<code>mypackage/MyClass</code>".
+ * @param accessFlags the access flags of the method.
+ * @param internalMethodName the internal method name,
+ * e.g. "<code>myMethod</code>" or
+ * "<code>&lt;init&gt;</code>".
+ * @param internalMethodDescriptor the internal method descriptor,
+ * e.g. "<code>(II)Z</code>".
+ * @return the external full method description,
+ * e.g. "<code>public boolean myMethod(int,int)</code>" or
+ * "<code>public MyClass(int,int)</code>".
+ */
+ public static String externalFullMethodDescription(String internalClassName,
+ int accessFlags,
+ String internalMethodName,
+ String internalMethodDescriptor)
+ {
+ return externalMethodAccessFlags(accessFlags) +
+ externalMethodReturnTypeAndName(internalClassName,
+ internalMethodName,
+ internalMethodDescriptor) +
+ JavaConstants.METHOD_ARGUMENTS_OPEN +
+ externalMethodArguments(internalMethodDescriptor) +
+ JavaConstants.METHOD_ARGUMENTS_CLOSE;
+ }
+
+
+ /**
+ * Converts internal class access flags into an external access description.
+ * @param accessFlags the class access flags.
+ * @return the external class access description,
+ * e.g. "<code>public final </code>".
+ */
+ public static String externalClassAccessFlags(int accessFlags)
+ {
+ return externalClassAccessFlags(accessFlags, "");
+ }
+
+
+ /**
+ * Converts internal class access flags into an external access description.
+ * @param accessFlags the class access flags.
+ * @param prefix a prefix that is added to each access modifier.
+ * @return the external class access description,
+ * e.g. "<code>public final </code>".
+ */
+ public static String externalClassAccessFlags(int accessFlags, String prefix)
+ {
+ if (accessFlags == 0)
+ {
+ return EMPTY_STRING;
+ }
+
+ StringBuffer string = new StringBuffer(50);
+
+ if ((accessFlags & ClassConstants.ACC_PUBLIC) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_PUBLIC).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_PRIVATE) != 0)
+ {
+ // Only in InnerClasses attributes.
+ string.append(prefix).append(JavaConstants.ACC_PRIVATE).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_PROTECTED) != 0)
+ {
+ // Only in InnerClasses attributes.
+ string.append(prefix).append(JavaConstants.ACC_PROTECTED).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_STATIC) != 0)
+ {
+ // Only in InnerClasses attributes.
+ string.append(prefix).append(JavaConstants.ACC_STATIC).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_FINAL) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_FINAL).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_ANNOTATTION) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_ANNOTATION);
+ }
+ if ((accessFlags & ClassConstants.ACC_INTERFACE) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_INTERFACE).append(' ');
+ }
+ else if ((accessFlags & ClassConstants.ACC_ENUM) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_ENUM).append(' ');
+ }
+ else if ((accessFlags & ClassConstants.ACC_ABSTRACT) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_ABSTRACT).append(' ');
+ }
+ else if ((accessFlags & ClassConstants.ACC_SYNTHETIC) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_SYNTHETIC).append(' ');
+ }
+
+ return string.toString();
+ }
+
+
+ /**
+ * Converts internal field access flags into an external access description.
+ * @param accessFlags the field access flags.
+ * @return the external field access description,
+ * e.g. "<code>public volatile </code>".
+ */
+ public static String externalFieldAccessFlags(int accessFlags)
+ {
+ return externalFieldAccessFlags(accessFlags, "");
+ }
+
+
+ /**
+ * Converts internal field access flags into an external access description.
+ * @param accessFlags the field access flags.
+ * @param prefix a prefix that is added to each access modifier.
+ * @return the external field access description,
+ * e.g. "<code>public volatile </code>".
+ */
+ public static String externalFieldAccessFlags(int accessFlags, String prefix)
+ {
+ if (accessFlags == 0)
+ {
+ return EMPTY_STRING;
+ }
+
+ StringBuffer string = new StringBuffer(50);
+
+ if ((accessFlags & ClassConstants.ACC_PUBLIC) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_PUBLIC).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_PRIVATE) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_PRIVATE).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_PROTECTED) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_PROTECTED).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_STATIC) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_STATIC).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_FINAL) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_FINAL).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_VOLATILE) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_VOLATILE).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_TRANSIENT) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_TRANSIENT).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_SYNTHETIC) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_SYNTHETIC).append(' ');
+ }
+
+ return string.toString();
+ }
+
+
+ /**
+ * Converts internal method access flags into an external access description.
+ * @param accessFlags the method access flags.
+ * @return the external method access description,
+ * e.g. "<code>public synchronized </code>".
+ */
+ public static String externalMethodAccessFlags(int accessFlags)
+ {
+ return externalMethodAccessFlags(accessFlags, "");
+ }
+
+
+ /**
+ * Converts internal method access flags into an external access description.
+ * @param accessFlags the method access flags.
+ * @param prefix a prefix that is added to each access modifier.
+ * @return the external method access description,
+ * e.g. "public synchronized ".
+ */
+ public static String externalMethodAccessFlags(int accessFlags, String prefix)
+ {
+ if (accessFlags == 0)
+ {
+ return EMPTY_STRING;
+ }
+
+ StringBuffer string = new StringBuffer(50);
+
+ if ((accessFlags & ClassConstants.ACC_PUBLIC) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_PUBLIC).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_PRIVATE) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_PRIVATE).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_PROTECTED) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_PROTECTED).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_STATIC) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_STATIC).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_FINAL) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_FINAL).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_SYNCHRONIZED) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_SYNCHRONIZED).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_BRIDGE) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_BRIDGE).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_VARARGS) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_VARARGS).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_NATIVE) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_NATIVE).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_ABSTRACT) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_ABSTRACT).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_STRICT) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_STRICT).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_SYNTHETIC) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_SYNTHETIC).append(' ');
+ }
+
+ return string.toString();
+ }
+
+
+ /**
+ * Converts internal method parameter access flags into an external access
+ * description.
+ * @param accessFlags the method parameter access flags.
+ * @return the external method parameter access description,
+ * e.g. "<code>final mandated </code>".
+ */
+ public static String externalParameterAccessFlags(int accessFlags)
+ {
+ return externalParameterAccessFlags(accessFlags, "");
+ }
+
+
+ /**
+ * Converts internal method parameter access flags into an external access
+ * description.
+ * @param accessFlags the method parameter access flags.
+ * @param prefix a prefix that is added to each access modifier.
+ * @return the external method parameter access description,
+ * e.g. "final mandated ".
+ */
+ public static String externalParameterAccessFlags(int accessFlags, String prefix)
+ {
+ if (accessFlags == 0)
+ {
+ return EMPTY_STRING;
+ }
+
+ StringBuffer string = new StringBuffer(50);
+
+ if ((accessFlags & ClassConstants.ACC_FINAL) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_FINAL).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_SYNTHETIC) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_SYNTHETIC).append(' ');
+ }
+ if ((accessFlags & ClassConstants.ACC_MANDATED) != 0)
+ {
+ string.append(prefix).append(JavaConstants.ACC_MANDATED).append(' ');
+ }
+
+ return string.toString();
+ }
+
+
+ /**
+ * Converts an internal method descriptor into an external method return type.
+ * @param internalMethodDescriptor the internal method descriptor,
+ * e.g. "<code>(II)Z</code>".
+ * @return the external method return type,
+ * e.g. "<code>boolean</code>".
+ */
+ public static String externalMethodReturnType(String internalMethodDescriptor)
+ {
+ return externalType(internalMethodReturnType(internalMethodDescriptor));
+ }
+
+
+ /**
+ * Converts an internal class name, method name, and method descriptor to
+ * an external method return type and name.
+ * @param internalClassName the internal name of the class of the method,
+ * e.g. "<code>mypackage/MyClass</code>".
+ * @param internalMethodName the internal method name,
+ * e.g. "<code>myMethod</code>" or
+ * "<code>&lt;init&gt;</code>".
+ * @param internalMethodDescriptor the internal method descriptor,
+ * e.g. "<code>(II)Z</code>".
+ * @return the external method return type and name,
+ * e.g. "<code>boolean myMethod</code>" or
+ * "<code>MyClass</code>".
+ */
+ private static String externalMethodReturnTypeAndName(String internalClassName,
+ String internalMethodName,
+ String internalMethodDescriptor)
+ {
+ return internalMethodName.equals(ClassConstants.METHOD_NAME_INIT) ?
+ externalShortClassName(externalClassName(internalClassName)) :
+ (externalMethodReturnType(internalMethodDescriptor) +
+ ' ' +
+ internalMethodName);
+ }
+
+
+ /**
+ * Converts an internal method descriptor into an external method argument
+ * description.
+ * @param internalMethodDescriptor the internal method descriptor,
+ * e.g. "<code>(II)Z</code>".
+ * @return the external method argument description,
+ * e.g. "<code>int,int</code>".
+ */
+ public static String externalMethodArguments(String internalMethodDescriptor)
+ {
+ StringBuffer externalMethodNameAndArguments = new StringBuffer();
+
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(internalMethodDescriptor);
+
+ while (internalTypeEnumeration.hasMoreTypes())
+ {
+ externalMethodNameAndArguments.append(externalType(internalTypeEnumeration.nextType()));
+ if (internalTypeEnumeration.hasMoreTypes())
+ {
+ externalMethodNameAndArguments.append(JavaConstants.METHOD_ARGUMENTS_SEPARATOR);
+ }
+ }
+
+ return externalMethodNameAndArguments.toString();
+ }
+
+
+ /**
+ * Returns the internal package name of the given internal class name.
+ * @param internalClassName the internal class name,
+ * e.g. "<code>java/lang/Object</code>".
+ * @return the internal package name,
+ * e.g. "<code>java/lang</code>".
+ */
+ public static String internalPackageName(String internalClassName)
+ {
+ String internalPackagePrefix = internalPackagePrefix(internalClassName);
+ int length = internalPackagePrefix.length();
+ return length > 0 ?
+ internalPackagePrefix.substring(0, length - 1) :
+ "";
+ }
+
+
+ /**
+ * Returns the internal package prefix of the given internal class name.
+ * @param internalClassName the internal class name,
+ * e.g. "<code>java/lang/Object</code>".
+ * @return the internal package prefix,
+ * e.g. "<code>java/lang/</code>".
+ */
+ public static String internalPackagePrefix(String internalClassName)
+ {
+ return internalClassName.substring(0, internalClassName.lastIndexOf(ClassConstants.PACKAGE_SEPARATOR,
+ internalClassName.length() - 2) + 1);
+ }
+
+
+ /**
+ * Returns the external package name of the given external class name.
+ * @param externalClassName the external class name,
+ * e.g. "<code>java.lang.Object</code>".
+ * @return the external package name,
+ * e.g. "<code>java.lang</code>".
+ */
+ public static String externalPackageName(String externalClassName)
+ {
+ String externalPackagePrefix = externalPackagePrefix(externalClassName);
+ int length = externalPackagePrefix.length();
+ return length > 0 ?
+ externalPackagePrefix.substring(0, length - 1) :
+ "";
+ }
+
+
+ /**
+ * Returns the external package prefix of the given external class name.
+ * @param externalClassName the external class name,
+ * e.g. "<code>java.lang.Object</code>".
+ * @return the external package prefix,
+ * e.g. "<code>java.lang.</code>".
+ */
+ public static String externalPackagePrefix(String externalClassName)
+ {
+ return externalClassName.substring(0, externalClassName.lastIndexOf(JavaConstants.PACKAGE_SEPARATOR,
+ externalClassName.length() - 2) + 1);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DescriptorClassEnumeration.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DescriptorClassEnumeration.java
new file mode 100644
index 0000000000..2be640c69d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DescriptorClassEnumeration.java
@@ -0,0 +1,252 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+
+import java.util.Stack;
+
+/**
+ * A <code>DescriptorClassEnumeration</code> provides an enumeration of all
+ * classes mentioned in a given descriptor or signature.
+ *
+ * @author Eric Lafortune
+ */
+public class DescriptorClassEnumeration
+{
+ private String descriptor;
+
+ private int index;
+ private int nestingLevel;
+ private boolean isInnerClassName;
+ private String accumulatedClassName;
+ private Stack accumulatedClassNames;
+
+
+ /**
+ * Creates a new DescriptorClassEnumeration for the given descriptor.
+ */
+ public DescriptorClassEnumeration(String descriptor)
+ {
+ this.descriptor = descriptor;
+ }
+
+
+ /**
+ * Returns the number of classes contained in the descriptor. This
+ * is the number of class names that the enumeration will return.
+ */
+ public int classCount()
+ {
+ int count = 0;
+
+ reset();
+
+ nextFluff();
+ while (hasMoreClassNames())
+ {
+ count++;
+
+ nextClassName();
+ nextFluff();
+ }
+
+ reset();
+
+ return count;
+ }
+
+
+ /**
+ * Resets the enumeration.
+ */
+ private void reset()
+ {
+ index = 0;
+ nestingLevel = 0;
+ isInnerClassName = false;
+ accumulatedClassName = null;
+ accumulatedClassNames = null;
+ }
+
+
+ /**
+ * Returns whether the enumeration can provide more class names from the
+ * descriptor.
+ */
+ public boolean hasMoreClassNames()
+ {
+ return index < descriptor.length();
+ }
+
+
+ /**
+ * Returns the next fluff (surrounding class names) from the descriptor.
+ */
+ public String nextFluff()
+ {
+ int fluffStartIndex = index;
+
+ // Find the first token marking the start of a class name 'L' or '.'.
+ loop: while (index < descriptor.length())
+ {
+ switch (descriptor.charAt(index++))
+ {
+ case ClassConstants.TYPE_GENERIC_START:
+ {
+ nestingLevel++;
+
+ // Make sure we have a stack.
+ if (accumulatedClassNames == null)
+ {
+ accumulatedClassNames = new Stack();
+ }
+
+ // Remember the accumulated class name.
+ accumulatedClassNames.push(accumulatedClassName);
+
+ break;
+ }
+ case ClassConstants.TYPE_GENERIC_END:
+ {
+ nestingLevel--;
+
+ // Return to the accumulated class name outside the
+ // generic block.
+ accumulatedClassName = (String)accumulatedClassNames.pop();
+
+ continue loop;
+ }
+ case ClassConstants.TYPE_GENERIC_BOUND:
+ case ClassConstants.TYPE_ARRAY:
+ {
+ continue loop;
+ }
+ case ClassConstants.TYPE_CLASS_START:
+ {
+ // We've found the start of an ordinary class name.
+ nestingLevel += 2;
+ isInnerClassName = false;
+ break loop;
+ }
+ case ClassConstants.TYPE_CLASS_END:
+ {
+ nestingLevel -= 2;
+ break;
+ }
+ case JavaConstants.INNER_CLASS_SEPARATOR:
+ {
+ // We've found the start of an inner class name in a signature.
+ isInnerClassName = true;
+ break loop;
+ }
+ case ClassConstants.TYPE_GENERIC_VARIABLE_START:
+ {
+ // We've found the start of a type identifier. Skip to the end.
+ while (descriptor.charAt(index++) != ClassConstants.TYPE_CLASS_END);
+ break;
+ }
+ }
+
+ if (nestingLevel == 1 &&
+ descriptor.charAt(index) != ClassConstants.TYPE_GENERIC_END)
+ {
+ // We're at the start of a type parameter. Skip to the start
+ // of the bounds.
+ while (descriptor.charAt(index++) != ClassConstants.TYPE_GENERIC_BOUND);
+ }
+ }
+
+ return descriptor.substring(fluffStartIndex, index);
+ }
+
+
+ /**
+ * Returns the next class name from the descriptor.
+ */
+ public String nextClassName()
+ {
+ int classNameStartIndex = index;
+
+ // Find the first token marking the end of a class name '<' or ';'.
+ loop: while (true)
+ {
+ switch (descriptor.charAt(index))
+ {
+ case ClassConstants.TYPE_GENERIC_START:
+ case ClassConstants.TYPE_CLASS_END:
+ case JavaConstants.INNER_CLASS_SEPARATOR:
+ {
+ break loop;
+ }
+ }
+
+ index++;
+ }
+
+ String className = descriptor.substring(classNameStartIndex, index);
+
+ // Recompose the inner class name if necessary.
+ accumulatedClassName = isInnerClassName ?
+ accumulatedClassName + ClassConstants.INNER_CLASS_SEPARATOR + className :
+ className;
+
+ return accumulatedClassName;
+ }
+
+
+ /**
+ * Returns whether the most recently returned class name was a recomposed
+ * inner class name from a signature.
+ */
+ public boolean isInnerClassName()
+ {
+ return isInnerClassName;
+ }
+
+
+ /**
+ * A main method for testing the class name enumeration.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ for (int index = 0; index < args.length; index++)
+ {
+ String descriptor = args[index];
+
+ System.out.println("Descriptor ["+descriptor+"]");
+ DescriptorClassEnumeration enumeration = new DescriptorClassEnumeration(descriptor);
+ System.out.println(" Fluff: ["+enumeration.nextFluff()+"]");
+ while (enumeration.hasMoreClassNames())
+ {
+ System.out.println(" Name: ["+enumeration.nextClassName()+"]");
+ System.out.println(" Fluff: ["+enumeration.nextFluff()+"]");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DynamicClassReferenceInitializer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
new file mode 100644
index 0000000000..c7e1c9b0d1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
@@ -0,0 +1,486 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.util.StringMatcher;
+
+/**
+ * This InstructionVisitor initializes any constant <code>Class.forName</code> or
+ * <code>.class</code> references of all classes it visits. More specifically,
+ * it fills out the references of string constant pool entries that refer to a
+ * class in the program class pool or in the library class pool.
+ * <p>
+ * It optionally prints notes if on usage of
+ * <code>(SomeClass)Class.forName(variable).newInstance()</code>.
+ * <p>
+ * The class hierarchy must be initialized before using this visitor.
+ *
+ * @see ClassSuperHierarchyInitializer
+ *
+ * @author Eric Lafortune
+ */
+public class DynamicClassReferenceInitializer
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ AttributeVisitor
+{
+ public static final int X = InstructionSequenceMatcher.X;
+ public static final int Y = InstructionSequenceMatcher.Y;
+ public static final int Z = InstructionSequenceMatcher.Z;
+
+ public static final int A = InstructionSequenceMatcher.A;
+ public static final int B = InstructionSequenceMatcher.B;
+ public static final int C = InstructionSequenceMatcher.C;
+ public static final int D = InstructionSequenceMatcher.D;
+
+
+ private final Constant[] CLASS_FOR_NAME_CONSTANTS = new Constant[]
+ {
+ // 0
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS),
+ new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_FOR_NAME),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_FOR_NAME),
+
+ // 6
+ new MethodrefConstant(1, 7, null, null),
+ new NameAndTypeConstant(8, 9),
+ new Utf8Constant(ClassConstants.METHOD_NAME_NEW_INSTANCE),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_NEW_INSTANCE),
+
+ // 10
+ new MethodrefConstant(1, 11, null, null),
+ new NameAndTypeConstant(12, 13),
+ new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_GET_COMPONENT_TYPE),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_GET_COMPONENT_TYPE),
+ };
+
+ // Class.forName("SomeClass").
+ private final Instruction[] CONSTANT_CLASS_FOR_NAME_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, X),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
+ // (SomeClass)Class.forName(someName).newInstance().
+ private final Instruction[] CLASS_FOR_NAME_CAST_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 6),
+ new ConstantInstruction(InstructionConstants.OP_CHECKCAST, X),
+ };
+
+
+// private Constant[] DOT_CLASS_JAVAC_CONSTANTS = new Constant[]
+// {
+// new MethodrefConstant(A, 1, null, null),
+// new NameAndTypeConstant(2, 3),
+// new Utf8Constant(ClassConstants.METHOD_NAME_DOT_CLASS_JAVAC),
+// new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JAVAC),
+// };
+
+ private final Constant[] DOT_CLASS_JAVAC_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(A, 1, null, null),
+ new NameAndTypeConstant(B, 2),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JAVAC),
+ };
+
+ // SomeClass.class = class$("SomeClass") (javac).
+ private final Instruction[] DOT_CLASS_JAVAC_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, X),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
+
+// private Constant[] DOT_CLASS_JIKES_CONSTANTS = new Constant[]
+// {
+// new MethodrefConstant(A, 1, null, null),
+// new NameAndTypeConstant(2, 3),
+// new Utf8Constant(ClassConstants.METHOD_NAME_DOT_CLASS_JIKES),
+// new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JIKES),
+// };
+
+ private final Constant[] DOT_CLASS_JIKES_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(A, 1, null, null),
+ new NameAndTypeConstant(B, 2),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JIKES),
+ };
+
+ // SomeClass.class = class("SomeClass", false) (jikes).
+ private final Instruction[] DOT_CLASS_JIKES_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, X),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
+ // return Class.forName(v0).
+ private final Instruction[] DOT_CLASS_JAVAC_IMPLEMENTATION_INSTRUCTIONS = new Instruction[]
+ {
+ new VariableInstruction(InstructionConstants.OP_ALOAD_0),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ new SimpleInstruction(InstructionConstants.OP_ARETURN),
+ };
+
+ // return Class.forName(v0), if (!v1) .getComponentType().
+ private final Instruction[] DOT_CLASS_JIKES_IMPLEMENTATION_INSTRUCTIONS = new Instruction[]
+ {
+ new VariableInstruction(InstructionConstants.OP_ALOAD_0),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ new VariableInstruction(InstructionConstants.OP_ALOAD_1),
+ new BranchInstruction(InstructionConstants.OP_IFNE, +6),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 10),
+ new SimpleInstruction(InstructionConstants.OP_ARETURN),
+ };
+
+ // return Class.forName(v0).getComponentType().
+ private final Instruction[] DOT_CLASS_JIKES_IMPLEMENTATION_INSTRUCTIONS2 = new Instruction[]
+ {
+ new VariableInstruction(InstructionConstants.OP_ALOAD_0),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 10),
+ new SimpleInstruction(InstructionConstants.OP_ARETURN),
+ };
+
+
+ private final ClassPool programClassPool;
+ private final ClassPool libraryClassPool;
+ private final WarningPrinter missingNotePrinter;
+ private final WarningPrinter dependencyWarningPrinter;
+ private final WarningPrinter notePrinter;
+ private final StringMatcher noteExceptionMatcher;
+
+
+ private final InstructionSequenceMatcher constantClassForNameMatcher =
+ new InstructionSequenceMatcher(CLASS_FOR_NAME_CONSTANTS,
+ CONSTANT_CLASS_FOR_NAME_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher classForNameCastMatcher =
+ new InstructionSequenceMatcher(CLASS_FOR_NAME_CONSTANTS,
+ CLASS_FOR_NAME_CAST_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher dotClassJavacMatcher =
+ new InstructionSequenceMatcher(DOT_CLASS_JAVAC_CONSTANTS,
+ DOT_CLASS_JAVAC_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher dotClassJikesMatcher =
+ new InstructionSequenceMatcher(DOT_CLASS_JIKES_CONSTANTS,
+ DOT_CLASS_JIKES_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher dotClassJavacImplementationMatcher =
+ new InstructionSequenceMatcher(CLASS_FOR_NAME_CONSTANTS,
+ DOT_CLASS_JAVAC_IMPLEMENTATION_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher dotClassJikesImplementationMatcher =
+ new InstructionSequenceMatcher(CLASS_FOR_NAME_CONSTANTS,
+ DOT_CLASS_JIKES_IMPLEMENTATION_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher dotClassJikesImplementationMatcher2 =
+ new InstructionSequenceMatcher(CLASS_FOR_NAME_CONSTANTS,
+ DOT_CLASS_JIKES_IMPLEMENTATION_INSTRUCTIONS2);
+
+
+ // A field acting as a return variable for the visitors.
+ private boolean isClassForNameInvocation;
+
+
+ /**
+ * Creates a new DynamicClassReferenceInitializer that optionally prints
+ * warnings and notes, with optional class specifications for which never
+ * to print notes.
+ */
+ public DynamicClassReferenceInitializer(ClassPool programClassPool,
+ ClassPool libraryClassPool,
+ WarningPrinter missingNotePrinter,
+ WarningPrinter dependencyWarningPrinter,
+ WarningPrinter notePrinter,
+ StringMatcher noteExceptionMatcher)
+ {
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ this.missingNotePrinter = missingNotePrinter;
+ this.dependencyWarningPrinter = dependencyWarningPrinter;
+ this.notePrinter = notePrinter;
+ this.noteExceptionMatcher = noteExceptionMatcher;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ // Try to match the (SomeClass)Class.forName(someName).newInstance()
+ // construct. Apply this matcher first, so the next matcher can still
+ // reset it after the first instruction.
+ instruction.accept(clazz, method, codeAttribute, offset,
+ classForNameCastMatcher);
+
+ // Did we find a match?
+ if (classForNameCastMatcher.isMatching())
+ {
+ // Print out a note about the construct.
+ clazz.constantPoolEntryAccept(classForNameCastMatcher.matchedConstantIndex(X), this);
+ }
+
+ // Try to match the Class.forName("SomeClass") construct.
+ instruction.accept(clazz, method, codeAttribute, offset,
+ constantClassForNameMatcher);
+
+ // Did we find a match?
+ if (constantClassForNameMatcher.isMatching())
+ {
+ // Fill out the matched string constant.
+ clazz.constantPoolEntryAccept(constantClassForNameMatcher.matchedConstantIndex(X), this);
+
+ // Don't look for the dynamic construct.
+ classForNameCastMatcher.reset();
+ }
+
+ // Try to match the javac .class construct.
+ instruction.accept(clazz, method, codeAttribute, offset,
+ dotClassJavacMatcher);
+
+ // Did we find a match?
+ if (dotClassJavacMatcher.isMatching() &&
+ isDotClassMethodref(clazz, dotClassJavacMatcher.matchedConstantIndex(0)))
+ {
+ // Fill out the matched string constant.
+ clazz.constantPoolEntryAccept(dotClassJavacMatcher.matchedConstantIndex(X), this);
+ }
+
+ // Try to match the jikes .class construct.
+ instruction.accept(clazz, method, codeAttribute, offset,
+ dotClassJikesMatcher);
+
+ // Did we find a match?
+ if (dotClassJikesMatcher.isMatching() &&
+ isDotClassMethodref(clazz, dotClassJikesMatcher.matchedConstantIndex(0)))
+ {
+ // Fill out the matched string constant.
+ clazz.constantPoolEntryAccept(dotClassJikesMatcher.matchedConstantIndex(X), this);
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ /**
+ * Fills out the link to the referenced class.
+ */
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Save a reference to the corresponding class.
+ String externalClassName = stringConstant.getString(clazz);
+ String internalClassName = ClassUtil.internalClassName(
+ ClassUtil.externalBaseType(externalClassName));
+
+ stringConstant.referencedClass = findClass(clazz.getName(), internalClassName);
+ }
+
+
+ /**
+ * Prints out a note about the class cast to this class, if applicable.
+ */
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Print out a note about the class cast.
+ if (noteExceptionMatcher == null ||
+ !noteExceptionMatcher.matches(classConstant.getName(clazz)))
+ {
+ notePrinter.print(clazz.getName(),
+ classConstant.getName(clazz),
+ "Note: " +
+ ClassUtil.externalClassName(clazz.getName()) +
+ " calls '(" +
+ ClassUtil.externalClassName(classConstant.getName(clazz)) +
+ ")Class.forName(variable).newInstance()'");
+ }
+ }
+
+
+ /**
+ * Checks whether the referenced method is a .class method.
+ */
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ String methodType = methodrefConstant.getType(clazz);
+
+ // Do the method's class and type match?
+ if (methodType.equals(ClassConstants.METHOD_TYPE_DOT_CLASS_JAVAC) ||
+ methodType.equals(ClassConstants.METHOD_TYPE_DOT_CLASS_JIKES))
+ {
+ String methodName = methodrefConstant.getName(clazz);
+
+ // Does the method's name match one of the special names?
+ isClassForNameInvocation =
+ methodName.equals(ClassConstants.METHOD_NAME_DOT_CLASS_JAVAC) ||
+ methodName.equals(ClassConstants.METHOD_NAME_DOT_CLASS_JIKES);
+
+ if (isClassForNameInvocation)
+ {
+ return;
+ }
+
+ String className = methodrefConstant.getClassName(clazz);
+
+ // Note that we look for the class by name, since the referenced
+ // class has not been initialized yet.
+ Clazz referencedClass = programClassPool.getClass(className);
+ if (referencedClass != null)
+ {
+ // Check if the code of the referenced method is .class code.
+ // Note that we look for the method by name and type, since the
+ // referenced method has not been initialized yet.
+ referencedClass.methodAccept(methodName,
+ methodType,
+ new AllAttributeVisitor(this));
+ }
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Check whether this is class$(String), as generated by javac, or
+ // class(String, boolean), as generated by jikes, or an optimized
+ // version.
+ isClassForNameInvocation =
+ isDotClassMethodCode(clazz, method, codeAttribute,
+ dotClassJavacImplementationMatcher, 5) ||
+ isDotClassMethodCode(clazz, method, codeAttribute,
+ dotClassJikesImplementationMatcher, 12) ||
+ isDotClassMethodCode(clazz, method, codeAttribute,
+ dotClassJikesImplementationMatcher2, 8);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the given method reference corresponds to a .class
+ * method, as generated by javac or by jikes.
+ */
+ private boolean isDotClassMethodref(Clazz clazz, int methodrefConstantIndex)
+ {
+ isClassForNameInvocation = false;
+
+ // Check if the code of the referenced method is .class code.
+ clazz.constantPoolEntryAccept(methodrefConstantIndex, this);
+
+ return isClassForNameInvocation;
+ }
+
+
+ /**
+ * Returns whether the first whether the first instructions of the
+ * given code attribute match with the given instruction matcher.
+ */
+ private boolean isDotClassMethodCode(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ InstructionSequenceMatcher codeMatcher,
+ int codeLength)
+ {
+ // Check the minimum code length.
+ if (codeAttribute.u4codeLength < codeLength)
+ {
+ return false;
+ }
+
+ // Check the actual instructions.
+ codeMatcher.reset();
+ codeAttribute.instructionsAccept(clazz, method, 0, codeLength, codeMatcher);
+ return codeMatcher.isMatching();
+ }
+
+
+ /**
+ * Returns the class with the given name, either for the program class pool
+ * or from the library class pool, or <code>null</code> if it can't be found.
+ */
+ private Clazz findClass(String referencingClassName, String name)
+ {
+ // Is it an array type?
+ if (ClassUtil.isInternalArrayType(name))
+ {
+ // Ignore any primitive array types.
+ if (!ClassUtil.isInternalClassType(name))
+ {
+ return null;
+ }
+
+ // Strip the array part.
+ name = ClassUtil.internalClassNameFromClassType(name);
+ }
+
+ // First look for the class in the program class pool.
+ Clazz clazz = programClassPool.getClass(name);
+
+ // Otherwise look for the class in the library class pool.
+ if (clazz == null)
+ {
+ clazz = libraryClassPool.getClass(name);
+
+ if (clazz == null &&
+ missingNotePrinter != null)
+ {
+ // We didn't find the superclass or interface. Print a note.
+ missingNotePrinter.print(referencingClassName,
+ name,
+ "Note: " +
+ ClassUtil.externalClassName(referencingClassName) +
+ ": can't find dynamically referenced class " +
+ ClassUtil.externalClassName(name));
+ }
+ }
+ else if (dependencyWarningPrinter != null)
+ {
+ // The superclass or interface was found in the program class pool.
+ // Print a warning.
+ dependencyWarningPrinter.print(referencingClassName,
+ name,
+ "Warning: library class " +
+ ClassUtil.externalClassName(referencingClassName) +
+ " depends dynamically on program class " +
+ ClassUtil.externalClassName(name));
+ }
+
+ return clazz;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
new file mode 100644
index 0000000000..504436ce8d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
@@ -0,0 +1,942 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.visitor.*;
+import proguard.util.StringMatcher;
+
+/**
+ * This InstructionVisitor initializes any constant
+ * <code>Class.get[Declared]{Field,Method}</code> references of all instructions
+ * it visits. More specifically, it fills out the references of string constant
+ * pool entries that refer to a class member in the program class pool or in the
+ * library class pool.
+ * <p>
+ * It optionally prints notes if on usage of
+ * <code>(SomeClass)Class.forName(variable).newInstance()</code>.
+ * <p>
+ * The class hierarchy and references must be initialized before using this
+ * visitor.
+ *
+ * @see ClassSuperHierarchyInitializer
+ * @see ClassReferenceInitializer
+ *
+ * @author Eric Lafortune
+ */
+public class DynamicMemberReferenceInitializer
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = true;
+ //*/
+
+ public static final int CLASS_INDEX = InstructionSequenceMatcher.X;
+ public static final int MEMBER_NAME_INDEX = InstructionSequenceMatcher.Y;
+ public static final int TYPE_CLASS_INDEX = InstructionSequenceMatcher.Z;
+
+ public static final int PARAMETER0_CLASS_INDEX = InstructionSequenceMatcher.A;
+ public static final int PARAMETER1_CLASS_INDEX = InstructionSequenceMatcher.B;
+ public static final int PARAMETER2_CLASS_INDEX = InstructionSequenceMatcher.C;
+ public static final int PARAMETER3_CLASS_INDEX = InstructionSequenceMatcher.D;
+
+
+ private final Constant[] GET_FIELD_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS),
+ new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_GET_FIELD),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_GET_FIELD),
+ };
+
+ private final Constant[] GET_DECLARED_FIELD_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS),
+ new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_GET_DECLARED_FIELD),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_GET_DECLARED_FIELD),
+ };
+
+ private final Constant[] GET_CONSTRUCTOR_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS),
+ new Utf8Constant(ClassConstants.CONSTRUCTOR_NAME_CLASS_GET_CONSTRUCTOR),
+ new Utf8Constant(ClassConstants.CONSTRUCTOR_TYPE_CLASS_GET_CONSTRUCTOR),
+ };
+
+ private final Constant[] GET_DECLARED_CONSTRUCTOR_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS),
+ new Utf8Constant(ClassConstants.CONSTRUCTOR_NAME_CLASS_GET_DECLARED_CONSTRUCTOR),
+ new Utf8Constant(ClassConstants.CONSTRUCTOR_TYPE_CLASS_GET_DECLARED_CONSTRUCTOR),
+ };
+
+ private final Constant[] GET_METHOD_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS),
+ new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_GET_METHOD),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_GET_METHOD),
+ };
+
+ private final Constant[] GET_DECLARED_METHOD_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS),
+ new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_GET_DECLARED_METHOD),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_GET_DECLARED_METHOD),
+ };
+
+ private final Constant[] NEW_INTEGER_UPDATER_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER),
+ new Utf8Constant(ClassConstants.METHOD_NAME_NEW_UPDATER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_NEW_INTEGER_UPDATER),
+ };
+
+ private final Constant[] NEW_LONG_UPDATER_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_LONG_FIELD_UPDATER),
+ new Utf8Constant(ClassConstants.METHOD_NAME_NEW_UPDATER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_NEW_LONG_UPDATER),
+ };
+
+ private final Constant[] NEW_REFERENCE_UPDATER_CONSTANTS = new Constant[]
+ {
+ new MethodrefConstant(1, 2, null, null),
+ new ClassConstant(3, null),
+ new NameAndTypeConstant(4, 5),
+ new Utf8Constant(ClassConstants.NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_REFERENCE_FIELD_UPDATER),
+ new Utf8Constant(ClassConstants.METHOD_NAME_NEW_UPDATER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_NEW_REFERENCE_UPDATER),
+ };
+
+ // SomeClass.class.get[Declared]Field("someField").
+ private final Instruction[] CONSTANT_GET_FIELD_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+// // SomeClass.class.get[Declared]Constructor(new Class[] {}).
+// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0 = new Instruction[]
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+//
+// // SomeClass.class.get[Declared]Constructor(new Class[] { A.class }).
+// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1 = new Instruction[]
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new SimpleInstruction(InstructionConstants.OP_DUP),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_AASTORE),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+//
+// // SomeClass.class.get[Declared]Constructor(new Class[] { A.class, B.class }).
+// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2 = new Instruction[]
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new SimpleInstruction(InstructionConstants.OP_DUP),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_AASTORE),
+// new SimpleInstruction(InstructionConstants.OP_DUP),
+// new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
+// new SimpleInstruction(InstructionConstants.OP_AASTORE),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+
+ // SomeClass.class.get[Declared]Method("someMethod", new Class[] {}).
+ private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS0 = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+ // SomeClass.class.get[Declared]Method("someMethod", new Class[] { A.class }).
+ private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS1 = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+ // SomeClass.class.get[Declared]Method("someMethod", new Class[] { A.class, B.class }).
+ private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS2 = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+ // AtomicIntegerFieldUpdater.newUpdater(A.class, "someField").
+ // AtomicLongFieldUpdater.newUpdater(A.class, "someField").
+ private final Instruction[] CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
+ // AtomicReferenceFieldUpdater.newUpdater(A.class, B.class, "someField").
+ private final Instruction[] CONSTANT_NEW_REFERENCE_UPDATER_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, TYPE_CLASS_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
+ // get[Declared]Field("someField").
+ private final Instruction[] GET_FIELD_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+// // get[Declared]Constructor(new Class[] {}).
+// private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS0 = new Instruction[]
+// {
+// new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+// };
+
+ // get[Declared]Constructor(new Class[] { A.class }).
+ private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS1 = new Instruction[]
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+ // get[Declared]Constructor(new Class[] { A.class, B.class }).
+ private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS2 = new Instruction[]
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+ // get[Declared]Method("someMethod", new Class[] {}).
+ private final Instruction[] GET_METHOD_INSTRUCTIONS0 = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+ // get[Declared]Method("someMethod", new Class[] { A.class }).
+ private final Instruction[] GET_METHOD_INSTRUCTIONS1 = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+ // get[Declared]Method("someMethod", new Class[] { A.class, B.class }).
+ private final Instruction[] GET_METHOD_INSTRUCTIONS2 = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+ new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX),
+ new SimpleInstruction(InstructionConstants.OP_AASTORE),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0),
+ };
+
+ // AtomicIntegerFieldUpdater.newUpdater(..., "someField").
+ // AtomicLongFieldUpdater.newUpdater(..., "someField").
+ // AtomicReferenceFieldUpdater.newUpdater(..., "someField").
+ private final Instruction[] NEW_UPDATER_INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
+ };
+
+
+ private final ClassPool programClassPool;
+ private final ClassPool libraryClassPool;
+ private final WarningPrinter notePrinter;
+ private final StringMatcher noteFieldExceptionMatcher;
+ private final StringMatcher noteMethodExceptionMatcher;
+
+
+ private final InstructionSequenceMatcher constantGetFieldMatcher =
+ new InstructionSequenceMatcher(GET_FIELD_CONSTANTS,
+ CONSTANT_GET_FIELD_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher constantGetDeclaredFieldMatcher =
+ new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS,
+ CONSTANT_GET_FIELD_INSTRUCTIONS);
+
+// private final InstructionSequenceMatcher constantGetConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0);
+//
+// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0);
+//
+// private final InstructionSequenceMatcher constantGetConstructorMatcher1 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1);
+//
+// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher1 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1);
+//
+// private final InstructionSequenceMatcher constantGetConstructorMatcher2 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2);
+//
+// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher2 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2);
+
+ private final InstructionSequenceMatcher constantGetMethodMatcher0 =
+ new InstructionSequenceMatcher(GET_METHOD_CONSTANTS,
+ CONSTANT_GET_METHOD_INSTRUCTIONS0);
+
+ private final InstructionSequenceMatcher constantGetDeclaredMethodMatcher0 =
+ new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS,
+ CONSTANT_GET_METHOD_INSTRUCTIONS0);
+
+ private final InstructionSequenceMatcher constantGetMethodMatcher1 =
+ new InstructionSequenceMatcher(GET_METHOD_CONSTANTS,
+ CONSTANT_GET_METHOD_INSTRUCTIONS1);
+
+ private final InstructionSequenceMatcher constantGetDeclaredMethodMatcher1 =
+ new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS,
+ CONSTANT_GET_METHOD_INSTRUCTIONS1);
+
+ private final InstructionSequenceMatcher constantGetMethodMatcher2 =
+ new InstructionSequenceMatcher(GET_METHOD_CONSTANTS,
+ CONSTANT_GET_METHOD_INSTRUCTIONS2);
+
+ private final InstructionSequenceMatcher constantGetDeclaredMethodMatcher2 =
+ new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS,
+ CONSTANT_GET_METHOD_INSTRUCTIONS2);
+
+ private final InstructionSequenceMatcher constantGetIntegerUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_INTEGER_UPDATER_CONSTANTS,
+ CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher constantGetLongUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_LONG_UPDATER_CONSTANTS,
+ CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher constantGetReferenceUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_REFERENCE_UPDATER_CONSTANTS,
+ CONSTANT_NEW_REFERENCE_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher getFieldMatcher =
+ new InstructionSequenceMatcher(GET_FIELD_CONSTANTS,
+ GET_FIELD_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher getDeclaredFieldMatcher =
+ new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS,
+ GET_FIELD_INSTRUCTIONS);
+
+// private final InstructionSequenceMatcher getConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+// GET_CONSTRUCTOR_INSTRUCTIONS0);
+//
+// private final InstructionSequenceMatcher getDeclaredConstructorMatcher0 =
+// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+// GET_CONSTRUCTOR_INSTRUCTIONS0);
+
+ private final InstructionSequenceMatcher getConstructorMatcher1 =
+ new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS1);
+
+ private final InstructionSequenceMatcher getDeclaredConstructorMatcher1 =
+ new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS1);
+
+ private final InstructionSequenceMatcher getConstructorMatcher2 =
+ new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS2);
+
+ private final InstructionSequenceMatcher getDeclaredConstructorMatcher2 =
+ new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS,
+ GET_CONSTRUCTOR_INSTRUCTIONS2);
+
+ private final InstructionSequenceMatcher getMethodMatcher0 =
+ new InstructionSequenceMatcher(GET_METHOD_CONSTANTS,
+ GET_METHOD_INSTRUCTIONS0);
+
+ private final InstructionSequenceMatcher getDeclaredMethodMatcher0 =
+ new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS,
+ GET_METHOD_INSTRUCTIONS0);
+
+ private final InstructionSequenceMatcher getMethodMatcher1 =
+ new InstructionSequenceMatcher(GET_METHOD_CONSTANTS,
+ GET_METHOD_INSTRUCTIONS1);
+
+ private final InstructionSequenceMatcher getDeclaredMethodMatcher1 =
+ new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS,
+ GET_METHOD_INSTRUCTIONS1);
+
+ private final InstructionSequenceMatcher getMethodMatcher2 =
+ new InstructionSequenceMatcher(GET_METHOD_CONSTANTS,
+ GET_METHOD_INSTRUCTIONS2);
+
+ private final InstructionSequenceMatcher getDeclaredMethodMatcher2 =
+ new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS,
+ GET_METHOD_INSTRUCTIONS2);
+
+ private final InstructionSequenceMatcher getIntegerUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_INTEGER_UPDATER_CONSTANTS,
+ NEW_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher getLongUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_LONG_UPDATER_CONSTANTS,
+ NEW_UPDATER_INSTRUCTIONS);
+
+ private final InstructionSequenceMatcher getReferenceUpdaterMatcher =
+ new InstructionSequenceMatcher(NEW_REFERENCE_UPDATER_CONSTANTS,
+ NEW_UPDATER_INSTRUCTIONS);
+
+ private final MemberFinder memberFinder = new MemberFinder();
+
+
+ // Fields acting as parameters for the visitors.
+ private Clazz referencedClass;
+ private String descriptor;
+ private boolean isDeclared;
+ private boolean isField;
+
+
+
+ /**
+ * Creates a new DynamicMemberReferenceInitializer.
+ */
+ public DynamicMemberReferenceInitializer(ClassPool programClassPool,
+ ClassPool libraryClassPool,
+ WarningPrinter notePrinter,
+ StringMatcher noteFieldExceptionMatcher,
+ StringMatcher noteMethodExceptionMatcher)
+ {
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ this.notePrinter = notePrinter;
+ this.noteFieldExceptionMatcher = noteFieldExceptionMatcher;
+ this.noteMethodExceptionMatcher = noteMethodExceptionMatcher;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ // Try to match the SomeClass.class.getField("someField") construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetFieldMatcher,
+ getFieldMatcher, true, false, null, null);
+
+ // Try to match the SomeClass.class.getDeclaredField("someField") construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetDeclaredFieldMatcher,
+ getDeclaredFieldMatcher, true, true, null, null);
+
+// // Try to match the SomeClass.class.getConstructor(new Class[]
+// // {}) construct.
+// matchGetMember(clazz, method, codeAttribute, offset, instruction,
+// cnull, //onstantGetConstructorMatcher0,
+// getConstructorMatcher0, false, false,
+// ClassConstants.METHOD_NAME_INIT, null);
+//
+// // Try to match the SomeClass.class.getDeclaredConstructor(new Class[]
+// // {}) construct.
+// matchGetMember(clazz, method, codeAttribute, offset, instruction,
+// null, //constantGetDeclaredConstructorMatcher0,
+// getDeclaredConstructorMatcher0, false, true,
+// ClassConstants.METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getConstructor(new Class[]
+ // { A.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetConstructorMatcher1,
+ getConstructorMatcher1, false, false,
+ ClassConstants.METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getDeclaredConstructor(new Class[]
+ // { A.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetDeclaredConstructorMatcher1,
+ getDeclaredConstructorMatcher1, false, true,
+ ClassConstants.METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getConstructor(new Class[]
+ // { A.class, B.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetConstructorMatcher2,
+ getConstructorMatcher2, false, false,
+ ClassConstants.METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getDeclaredConstructor(new Class[]
+ // { A.class, B.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ null, //constantGetDeclaredConstructorMatcher2,
+ getDeclaredConstructorMatcher2, false, true,
+ ClassConstants.METHOD_NAME_INIT, null);
+
+ // Try to match the SomeClass.class.getMethod("someMethod", new Class[]
+ // {}) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetMethodMatcher0,
+ getMethodMatcher0, false, false, null, null);
+
+ // Try to match the SomeClass.class.getDeclaredMethod("someMethod",
+ // new Class[] {}) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetDeclaredMethodMatcher0,
+ getDeclaredMethodMatcher0, false, true, null, null);
+
+ // Try to match the SomeClass.class.getMethod("someMethod", new Class[]
+ // { A.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetMethodMatcher1,
+ getMethodMatcher1, false, false, null, null);
+
+ // Try to match the SomeClass.class.getDeclaredMethod("someMethod",
+ // new Class[] { A.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetDeclaredMethodMatcher1,
+ getDeclaredMethodMatcher1, false, true, null, null);
+
+ // Try to match the SomeClass.class.getMethod("someMethod", new Class[]
+ // { A.class, B.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetMethodMatcher2,
+ getMethodMatcher2, false, false, null, null);
+
+ // Try to match the SomeClass.class.getDeclaredMethod("someMethod",
+ // new Class[] { A.class, B.class }) construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetDeclaredMethodMatcher2,
+ getDeclaredMethodMatcher2, false, true, null, null);
+
+ // Try to match the AtomicIntegerFieldUpdater.newUpdater(
+ // SomeClass.class, "someField") construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetIntegerUpdaterMatcher,
+ getIntegerUpdaterMatcher, true, false, null,
+ "" + ClassConstants.TYPE_INT);
+
+ // Try to match the AtomicLongFieldUpdater.newUpdater(
+ // SomeClass.class, "someField") construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetLongUpdaterMatcher,
+ getLongUpdaterMatcher, true, false, null,
+ "" + ClassConstants.TYPE_LONG);
+
+ // Try to match the AtomicReferenceFieldUpdater.newUpdater(
+ // SomeClass.class, SomeClass.class, "someField") construct.
+ matchGetMember(clazz, method, codeAttribute, offset, instruction,
+ constantGetReferenceUpdaterMatcher,
+ getReferenceUpdaterMatcher, true, false, null, null);
+ }
+
+
+ /**
+ * Tries to match the next instruction and fills out the string constant
+ * or prints out a note accordingly.
+ */
+ private void matchGetMember(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int offset,
+ Instruction instruction,
+ InstructionSequenceMatcher constantSequenceMatcher,
+ InstructionSequenceMatcher variableSequenceMatcher,
+ boolean isField,
+ boolean isDeclared,
+ String defaultName,
+ String defaultDescriptor)
+ {
+ if (constantSequenceMatcher != null)
+ {
+ // Try to match the next instruction in the constant sequence.
+ instruction.accept(clazz, method, codeAttribute, offset,
+ constantSequenceMatcher);
+
+ // Did we find a match to fill out the string constant?
+ if (constantSequenceMatcher.isMatching())
+ {
+ initializeStringReference(clazz,
+ constantSequenceMatcher,
+ isField,
+ isDeclared,
+ defaultDescriptor);
+
+ // Don't look for the dynamic construct.
+ variableSequenceMatcher.reset();
+ }
+ }
+
+ // Try to match the next instruction in the variable sequence.
+ instruction.accept(clazz, method, codeAttribute, offset,
+ variableSequenceMatcher);
+
+ // Did we find a match to print out a note?
+ if (variableSequenceMatcher.isMatching())
+ {
+ // Print out a note about the dynamic invocation.
+ printDynamicInvocationNote(clazz,
+ variableSequenceMatcher,
+ isField,
+ isDeclared,
+ defaultName,
+ defaultDescriptor);
+ }
+ }
+
+
+ /**
+ * Initializes the reference of the matched string constant to the
+ * referenced class member and its class.
+ */
+ private void initializeStringReference(Clazz clazz,
+ InstructionSequenceMatcher constantSequenceMatcher,
+ boolean isField,
+ boolean isDeclared,
+ String defaultDescriptor)
+ {
+ this.isField = isField;
+ this.isDeclared = isDeclared;
+
+ // Get the member's class.
+ int classIndex = constantSequenceMatcher.matchedConstantIndex(CLASS_INDEX);
+ clazz.constantPoolEntryAccept(classIndex, this);
+
+ // Get the field's reference type, if applicable.
+ int typeClassIndex = constantSequenceMatcher.matchedConstantIndex(TYPE_CLASS_INDEX);
+ descriptor = typeClassIndex <= 0 ? defaultDescriptor :
+ ClassUtil.internalTypeFromClassName(clazz.getClassName(typeClassIndex));
+
+ // Fill out the matched string constant.
+ int memberNameIndex = constantSequenceMatcher.matchedConstantIndex(MEMBER_NAME_INDEX);
+ clazz.constantPoolEntryAccept(memberNameIndex, this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ /**
+ * Remembers the referenced class.
+ */
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ if (DEBUG)
+ {
+ System.out.println("DynamicMemberReferenceInitializer: ["+clazz.getName()+"] matched class ["+classConstant.getName(clazz)+"]");
+ }
+
+ // Remember the referenced class.
+ referencedClass = ClassUtil.isInternalArrayType(classConstant.getName(clazz)) ?
+ null :
+ classConstant.referencedClass;
+ }
+
+
+ /**
+ * Fills out the link to the referenced class member.
+ */
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ if (referencedClass != null)
+ {
+ String name = stringConstant.getString(clazz);
+
+ if (DEBUG)
+ {
+ System.out.println("DynamicMemberReferenceInitializer: ["+clazz.getName()+"] matched string ["+name+"]");
+ }
+
+ // See if we can find the referenced class member locally, or
+ // somewhere in the hierarchy.
+ Member referencedMember = isDeclared ? isField ?
+ (Member)referencedClass.findField(name, descriptor) :
+ (Member)referencedClass.findMethod(name, descriptor) :
+ (Member)memberFinder.findMember(clazz,
+ referencedClass,
+ name,
+ descriptor,
+ isField);
+ if (referencedMember != null)
+ {
+ stringConstant.referencedMember = referencedMember;
+ stringConstant.referencedClass = isDeclared ?
+ referencedClass :
+ memberFinder.correspondingClass();
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Prints out a note on the matched dynamic invocation, if necessary.
+ */
+ private void printDynamicInvocationNote(Clazz clazz,
+ InstructionSequenceMatcher noteSequenceMatcher,
+ boolean isField,
+ boolean isDeclared,
+ String defaultName,
+ String defaultDescriptor)
+ {
+ // Print out a note about the dynamic invocation.
+ if (notePrinter != null &&
+ notePrinter.accepts(clazz.getName()))
+ {
+ // Is the class member name in the list of exceptions?
+ StringMatcher noteExceptionMatcher = isField ?
+ noteFieldExceptionMatcher :
+ noteMethodExceptionMatcher;
+
+ int memberNameIndex = noteSequenceMatcher.matchedConstantIndex(MEMBER_NAME_INDEX);
+ String memberName = memberNameIndex <= 0 ? defaultName :
+ clazz.getStringString(memberNameIndex);
+
+ if (noteExceptionMatcher == null ||
+ !noteExceptionMatcher.matches(memberName))
+ {
+ // Compose the external member name and partial descriptor.
+ String externalMemberDescription = memberName;
+
+ if (!isField)
+ {
+ externalMemberDescription += '(';
+ for (int count = 0; count < 2; count++)
+ {
+ int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(
+ PARAMETER0_CLASS_INDEX + count);
+ if (memberArgumentIndex > 0)
+ {
+ if (count > 0)
+ {
+ externalMemberDescription += ',';
+ }
+ String className = clazz.getClassName(memberArgumentIndex);
+ externalMemberDescription += ClassUtil.isInternalArrayType(className) ?
+ ClassUtil.externalType(className) :
+ ClassUtil.externalClassName(className);
+ }
+ }
+ externalMemberDescription += ')';
+ }
+
+ // Print out the actual note.
+ notePrinter.print(clazz.getName(),
+ "Note: " +
+ ClassUtil.externalClassName(clazz.getName()) +
+ " accesses a " +
+ (isDeclared ? "declared " : "") +
+ (isField ? "field" :
+ memberName.equals(ClassConstants.METHOD_NAME_INIT) ?
+ "constructor" : "method") +
+ " '" +
+ externalMemberDescription +
+ "' dynamically");
+
+ // Print out notes about potential candidates.
+ ClassVisitor classVisitor;
+
+ if (isField)
+ {
+ classVisitor = defaultDescriptor == null ?
+ new AllFieldVisitor(
+ new MemberNameFilter(memberName, this)) :
+ new AllFieldVisitor(
+ new MemberNameFilter(memberName,
+ new MemberDescriptorFilter(defaultDescriptor, this)));
+ }
+ else
+ {
+ // Compose the partial method descriptor.
+ String methodDescriptor = "(";
+ for (int count = 0; count < 2; count++)
+ {
+ int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(PARAMETER0_CLASS_INDEX + count);
+ if (memberArgumentIndex > 0)
+ {
+ String className = clazz.getClassName(memberArgumentIndex);
+ methodDescriptor += ClassUtil.isInternalArrayType(className) ?
+ className :
+ ClassUtil.internalTypeFromClassName(className);
+ }
+ }
+ methodDescriptor += ")L***;";
+
+ classVisitor =
+ new AllMethodVisitor(
+ new MemberNameFilter(memberName,
+ new MemberDescriptorFilter(methodDescriptor, this)));
+ }
+
+ programClassPool.classesAcceptAlphabetically(classVisitor);
+ libraryClassPool.classesAcceptAlphabetically(classVisitor);
+ }
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (notePrinter.accepts(programClass.getName()))
+ {
+ System.out.println(" Maybe this is program field '" +
+ ClassUtil.externalFullClassDescription(0, programClass.getName()) +
+ " { " +
+ ClassUtil.externalFullFieldDescription(0, programField.getName(programClass), programField.getDescriptor(programClass)) +
+ "; }'");
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (notePrinter.accepts(programClass.getName()))
+ {
+ System.out.println(" Maybe this is program method '" +
+ ClassUtil.externalFullClassDescription(0, programClass.getName()) +
+ " { " +
+ ClassUtil.externalFullMethodDescription(programClass.getName(), 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) +
+ "; }'");
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (notePrinter.accepts(libraryClass.getName()))
+ {
+ System.out.println(" Maybe this is library field '" +
+ ClassUtil.externalFullClassDescription(0, libraryClass.getName()) +
+ " { " +
+ ClassUtil.externalFullFieldDescription(0, libraryField.getName(libraryClass), libraryField.getDescriptor(libraryClass)) +
+ "; }'");
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (notePrinter.accepts(libraryClass.getName()))
+ {
+ System.out.println(" Maybe this is library method '" +
+ ClassUtil.externalFullClassDescription(0, libraryClass.getName()) +
+ " { " +
+ ClassUtil.externalFullMethodDescription(libraryClass.getName(), 0, libraryMethod.getName(libraryClass), libraryMethod.getDescriptor(libraryClass)) +
+ "; }'");
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/EnumFieldReferenceInitializer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/EnumFieldReferenceInitializer.java
new file mode 100644
index 0000000000..a633d43ae0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/EnumFieldReferenceInitializer.java
@@ -0,0 +1,149 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+import proguard.classfile.attribute.visitor.AllAttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This ElementValueVisitor initializes the field references of the
+ * EnumConstantElementValue instances that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class EnumFieldReferenceInitializer
+extends SimplifiedVisitor
+implements ElementValueVisitor,
+ InstructionVisitor,
+ ConstantVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = true;
+ //*/
+
+ private MemberVisitor enumFieldFinder = new AllAttributeVisitor(
+ new AllInstructionVisitor(this));
+
+ // Fields acting as parameters and return values for the visitors.
+ private String enumTypeName;
+ private String enumConstantName;
+ private boolean enumConstantNameFound;
+ private Clazz referencedEnumClass;
+ private Field referencedEnumField;
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) {}
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+
+ if (enumConstantElementValue.referencedClasses != null &&
+ enumConstantElementValue.referencedClasses.length > 0)
+ {
+ referencedEnumClass = enumConstantElementValue.referencedClasses[0];
+ if (referencedEnumClass != null)
+ {
+ // Try to find the enum field through the static enum
+ // initialization code (at least for program classes).
+ enumTypeName = enumConstantElementValue.getTypeName(clazz);
+ enumConstantName = enumConstantElementValue.getConstantName(clazz);
+ referencedEnumField = null;
+ referencedEnumClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT,
+ ClassConstants.METHOD_TYPE_CLINIT,
+ enumFieldFinder);
+
+ // Otherwise try to find the enum field through its name.
+ // The constant name could be different from the field name, if
+ // the latter is already obfuscated.
+ if (referencedEnumField == null)
+ {
+ referencedEnumField =
+ referencedEnumClass.findField(enumConstantName,
+ enumTypeName);
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("EnumFieldReferenceInitializer: ["+referencedEnumClass.getName()+"."+enumConstantName+"] -> "+referencedEnumField);
+ }
+
+ enumConstantElementValue.referencedField = referencedEnumField;
+ }
+ }
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_LDC:
+ case InstructionConstants.OP_LDC_W:
+ case InstructionConstants.OP_PUTSTATIC:
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ enumConstantNameFound =
+ enumConstantName.equals(stringConstant.getString(clazz));
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ if (enumConstantNameFound)
+ {
+ if (enumTypeName.equals(fieldrefConstant.getType(clazz)))
+ {
+ referencedEnumField = (Field)fieldrefConstant.referencedMember;
+ }
+
+ enumConstantNameFound = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ExternalTypeEnumeration.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ExternalTypeEnumeration.java
new file mode 100644
index 0000000000..0575a7bde9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/ExternalTypeEnumeration.java
@@ -0,0 +1,106 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+
+
+/**
+ * An <code>ExternalTypeEnumeration</code> provides an enumeration of all
+ * types listed in a given external descriptor string. The method name can
+ * be retrieved separately.
+ * <p>
+ * A <code>ExternalTypeEnumeration</code> object can be reused for processing
+ * different subsequent descriptors, by means of the <code>setDescriptor</code>
+ * method.
+ *
+ * @author Eric Lafortune
+ */
+public class ExternalTypeEnumeration
+{
+ private String descriptor;
+ private int index;
+
+
+ public ExternalTypeEnumeration(String descriptor)
+ {
+ setDescriptor(descriptor);
+ }
+
+
+ ExternalTypeEnumeration()
+ {
+ }
+
+
+ void setDescriptor(String descriptor)
+ {
+ this.descriptor = descriptor;
+
+ reset();
+ }
+
+
+ public void reset()
+ {
+ index = descriptor.indexOf(JavaConstants.METHOD_ARGUMENTS_OPEN) + 1;
+
+ if (index < 1)
+ {
+ throw new IllegalArgumentException("Missing opening parenthesis in descriptor ["+descriptor+"]");
+ }
+ }
+
+
+ public boolean hasMoreTypes()
+ {
+ return index < descriptor.length() - 1;
+ }
+
+
+ public String nextType()
+ {
+ int startIndex = index;
+
+ // Find the next separating comma.
+ index = descriptor.indexOf(JavaConstants.METHOD_ARGUMENTS_SEPARATOR,
+ startIndex);
+
+ // Otherwise find the closing parenthesis.
+ if (index < 0)
+ {
+ index = descriptor.indexOf(JavaConstants.METHOD_ARGUMENTS_CLOSE,
+ startIndex);
+ if (index < 0)
+ {
+ throw new IllegalArgumentException("Missing closing parenthesis in descriptor ["+descriptor+"]");
+ }
+ }
+
+ return descriptor.substring(startIndex, index++).trim();
+ }
+
+
+ public String methodName()
+ {
+ return descriptor.substring(0, descriptor.indexOf(JavaConstants.METHOD_ARGUMENTS_OPEN)).trim();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/InstructionSequenceMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/InstructionSequenceMatcher.java
new file mode 100644
index 0000000000..22aadfa0d4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/InstructionSequenceMatcher.java
@@ -0,0 +1,754 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+
+import java.util.Arrays;
+
+/**
+ * This InstructionVisitor checks whether a given pattern instruction sequence
+ * occurs in the instructions that are visited. The arguments of the
+ * instruction sequence can be wildcards that are matched.
+ *
+ * @author Eric Lafortune
+ */
+public class InstructionSequenceMatcher
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_MORE = false;
+ /*/
+ public static boolean DEBUG = true;
+ public static boolean DEBUG_MORE = true;
+ //*/
+
+ public static final int X = 0x40000000;
+ public static final int Y = 0x40000001;
+ public static final int Z = 0x40000002;
+
+ public static final int A = 0x40000003;
+ public static final int B = 0x40000004;
+ public static final int C = 0x40000005;
+ public static final int D = 0x40000006;
+
+
+ private final Constant[] patternConstants;
+ private final Instruction[] patternInstructions;
+
+ private boolean matching;
+ private int patternInstructionIndex;
+ private final int[] matchedInstructionOffsets;
+ private int matchedArgumentFlags;
+ private final int[] matchedArguments = new int[7];
+ private final long[] matchedConstantFlags;
+ private final int[] matchedConstantIndices;
+ private int constantFlags;
+ private int previousConstantFlags;
+
+ // Fields acting as a parameter and a return value for visitor methods.
+ private Constant patternConstant;
+ private boolean matchingConstant;
+
+
+ /**
+ * Creates a new InstructionSequenceMatcher.
+ * @param patternConstants any constants referenced by the pattern
+ * instruction.
+ * @param patternInstructions the pattern instruction sequence.
+ */
+ public InstructionSequenceMatcher(Constant[] patternConstants,
+ Instruction[] patternInstructions)
+ {
+ this.patternConstants = patternConstants;
+ this.patternInstructions = patternInstructions;
+
+ matchedInstructionOffsets = new int[patternInstructions.length];
+ matchedConstantFlags = new long[(patternConstants.length + 63) / 64];
+ matchedConstantIndices = new int[patternConstants.length];
+ }
+
+
+ /**
+ * Starts matching from the first instruction again next time.
+ */
+ public void reset()
+ {
+ patternInstructionIndex = 0;
+ matchedArgumentFlags = 0;
+
+ Arrays.fill(matchedConstantFlags, 0L);
+
+ previousConstantFlags = constantFlags;
+ constantFlags = 0;
+ }
+
+
+ /**
+ * Returns whether the complete pattern sequence has been matched.
+ */
+ public boolean isMatching()
+ {
+ return matching;
+ }
+
+
+ /**
+ * Returns the number of instructions in the pattern sequence.
+ */
+ public int instructionCount()
+ {
+ return patternInstructions.length;
+ }
+
+
+ /**
+ * Returns the matched instruction offset of the specified pattern
+ * instruction.
+ */
+ public int matchedInstructionOffset(int index)
+ {
+ return matchedInstructionOffsets[index];
+ }
+
+
+ /**
+ * Returns whether the specified wildcard argument was a constant from
+ * the constant pool in the most recent match.
+ */
+ public boolean wasConstant(int argument)
+ {
+ return (previousConstantFlags & (1 << (argument - X))) != 0;
+ }
+
+
+ /**
+ * Returns the value of the specified matched argument (wildcard or not).
+ */
+ public int matchedArgument(int argument)
+ {
+ int argumentIndex = argument - X;
+ return argumentIndex < 0 ?
+ argument :
+ matchedArguments[argumentIndex];
+ }
+
+
+ /**
+ * Returns the values of the specified matched arguments (wildcard or not).
+ */
+ public int[] matchedArguments(int[] arguments)
+ {
+ int[] matchedArguments = new int[arguments.length];
+
+ for (int index = 0; index < arguments.length; index++)
+ {
+ matchedArguments[index] = matchedArgument(arguments[index]);
+ }
+
+ return matchedArguments;
+ }
+
+
+ /**
+ * Returns the index of the specified matched constant (wildcard or not).
+ */
+ public int matchedConstantIndex(int constantIndex)
+ {
+ int argumentIndex = constantIndex - X;
+ return argumentIndex < 0 ?
+ matchedConstantIndices[constantIndex] :
+ matchedArguments[argumentIndex];
+ }
+
+
+ /**
+ * Returns the value of the specified matched branch offset (wildcard or
+ * not).
+ */
+ public int matchedBranchOffset(int offset, int branchOffset)
+ {
+ int argumentIndex = branchOffset - X;
+ return argumentIndex < 0 ?
+ branchOffset :
+ matchedArguments[argumentIndex] - offset;
+ }
+
+
+ /**
+ * Returns the values of the specified matched jump offsets (wildcard or
+ * not).
+ */
+ public int[] matchedJumpOffsets(int offset, int[] jumpOffsets)
+ {
+ int[] matchedJumpOffsets = new int[jumpOffsets.length];
+
+ for (int index = 0; index < jumpOffsets.length; index++)
+ {
+ matchedJumpOffsets[index] = matchedBranchOffset(offset,
+ jumpOffsets[index]);
+ }
+
+ return matchedJumpOffsets;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ Instruction patternInstruction = patternInstructions[patternInstructionIndex];
+
+ // Check if the instruction matches the next instruction in the sequence.
+ boolean condition =
+ matchingOpcodes(simpleInstruction, patternInstruction) &&
+ matchingArguments(simpleInstruction.constant,
+ ((SimpleInstruction)patternInstruction).constant);
+
+ // Check if the instruction sequence is matching now.
+ checkMatch(condition,
+ clazz,
+ method,
+ codeAttribute,
+ offset,
+ simpleInstruction);
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ Instruction patternInstruction = patternInstructions[patternInstructionIndex];
+
+ // Check if the instruction matches the next instruction in the sequence.
+ boolean condition =
+ matchingOpcodes(variableInstruction, patternInstruction) &&
+ matchingArguments(variableInstruction.variableIndex,
+ ((VariableInstruction)patternInstruction).variableIndex) &&
+ matchingArguments(variableInstruction.constant,
+ ((VariableInstruction)patternInstruction).constant);
+
+ // Check if the instruction sequence is matching now.
+ checkMatch(condition,
+ clazz,
+ method,
+ codeAttribute,
+ offset,
+ variableInstruction);
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ Instruction patternInstruction = patternInstructions[patternInstructionIndex];
+
+ // Check if the instruction matches the next instruction in the sequence.
+ boolean condition =
+ matchingOpcodes(constantInstruction, patternInstruction) &&
+ matchingConstantIndices(clazz,
+ constantInstruction.constantIndex,
+ ((ConstantInstruction)patternInstruction).constantIndex) &&
+ matchingArguments(constantInstruction.constant,
+ ((ConstantInstruction)patternInstruction).constant);
+
+ // Check if the instruction sequence is matching now.
+ checkMatch(condition,
+ clazz,
+ method,
+ codeAttribute,
+ offset,
+ constantInstruction);
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ Instruction patternInstruction = patternInstructions[patternInstructionIndex];
+
+ // Check if the instruction matches the next instruction in the from
+ // sequence.
+ boolean condition =
+ matchingOpcodes(branchInstruction, patternInstruction) &&
+ matchingBranchOffsets(offset,
+ branchInstruction.branchOffset,
+ ((BranchInstruction)patternInstruction).branchOffset);
+
+ // Check if the instruction sequence is matching now.
+ checkMatch(condition,
+ clazz,
+ method,
+ codeAttribute,
+ offset,
+ branchInstruction);
+ }
+
+
+ public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
+ {
+ Instruction patternInstruction = patternInstructions[patternInstructionIndex];
+
+ // Check if the instruction matches the next instruction in the sequence.
+ boolean condition =
+ matchingOpcodes(tableSwitchInstruction, patternInstruction) &&
+ matchingBranchOffsets(offset,
+ tableSwitchInstruction.defaultOffset,
+ ((TableSwitchInstruction)patternInstruction).defaultOffset) &&
+ matchingArguments(tableSwitchInstruction.lowCase,
+ ((TableSwitchInstruction)patternInstruction).lowCase) &&
+ matchingArguments(tableSwitchInstruction.highCase,
+ ((TableSwitchInstruction)patternInstruction).highCase) &&
+ matchingJumpOffsets(offset,
+ tableSwitchInstruction.jumpOffsets,
+ ((TableSwitchInstruction)patternInstruction).jumpOffsets);
+
+ // Check if the instruction sequence is matching now.
+ checkMatch(condition,
+ clazz,
+ method,
+ codeAttribute,
+ offset,
+ tableSwitchInstruction);
+ }
+
+
+ public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
+ {
+ Instruction patternInstruction = patternInstructions[patternInstructionIndex];
+
+ // Check if the instruction matches the next instruction in the sequence.
+ boolean condition =
+ matchingOpcodes(lookUpSwitchInstruction, patternInstruction) &&
+ matchingBranchOffsets(offset,
+ lookUpSwitchInstruction.defaultOffset,
+ ((LookUpSwitchInstruction)patternInstruction).defaultOffset) &&
+ matchingArguments(lookUpSwitchInstruction.cases,
+ ((LookUpSwitchInstruction)patternInstruction).cases) &&
+ matchingJumpOffsets(offset,
+ lookUpSwitchInstruction.jumpOffsets,
+ ((LookUpSwitchInstruction)patternInstruction).jumpOffsets);
+
+ // Check if the instruction sequence is matching now.
+ checkMatch(condition,
+ clazz,
+ method,
+ codeAttribute,
+ offset,
+ lookUpSwitchInstruction);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ IntegerConstant integerPatternConstant = (IntegerConstant)patternConstant;
+
+ // Compare the integer values.
+ matchingConstant = integerConstant.getValue() ==
+ integerPatternConstant.getValue();
+ }
+
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ LongConstant longPatternConstant = (LongConstant)patternConstant;
+
+ // Compare the long values.
+ matchingConstant = longConstant.getValue() ==
+ longPatternConstant.getValue();
+ }
+
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ FloatConstant floatPatternConstant = (FloatConstant)patternConstant;
+
+ // Compare the float values.
+ matchingConstant = floatConstant.getValue() ==
+ floatPatternConstant.getValue();
+ }
+
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ DoubleConstant doublePatternConstant = (DoubleConstant)patternConstant;
+
+ // Compare the double values.
+ matchingConstant = doubleConstant.getValue() ==
+ doublePatternConstant.getValue();
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ StringConstant stringPatternConstant = (StringConstant)patternConstant;
+
+ // Check the UTF-8 constant.
+ matchingConstant =
+ matchingConstantIndices(clazz,
+ stringConstant.u2stringIndex,
+ stringPatternConstant.u2stringIndex);
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ Utf8Constant utf8PatternConstant = (Utf8Constant)patternConstant;
+
+ // Compare the actual strings.
+ matchingConstant = utf8Constant.getString().equals(
+ utf8PatternConstant.getString());
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ InvokeDynamicConstant invokeDynamicPatternConstant = (InvokeDynamicConstant)patternConstant;
+
+ // Check the bootstrap method and the name and type.
+ matchingConstant =
+ matchingConstantIndices(clazz,
+ invokeDynamicConstant.getBootstrapMethodAttributeIndex(),
+ invokeDynamicPatternConstant.getBootstrapMethodAttributeIndex()) &&
+ matchingConstantIndices(clazz,
+ invokeDynamicConstant.getNameAndTypeIndex(),
+ invokeDynamicPatternConstant.getNameAndTypeIndex());
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ MethodHandleConstant methodHandlePatternConstant = (MethodHandleConstant)patternConstant;
+
+ // Check the handle type and the name and type.
+ matchingConstant =
+ matchingArguments(methodHandleConstant.getReferenceKind(),
+ methodHandlePatternConstant.getReferenceKind()) &&
+ matchingConstantIndices(clazz,
+ methodHandleConstant.getReferenceIndex(),
+ methodHandlePatternConstant.getReferenceIndex());
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ RefConstant refPatternConstant = (RefConstant)patternConstant;
+
+ // Check the class and the name and type.
+ matchingConstant =
+ matchingConstantIndices(clazz,
+ refConstant.getClassIndex(),
+ refPatternConstant.getClassIndex()) &&
+ matchingConstantIndices(clazz,
+ refConstant.getNameAndTypeIndex(),
+ refPatternConstant.getNameAndTypeIndex());
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ ClassConstant classPatternConstant = (ClassConstant)patternConstant;
+
+ // Check the class name.
+ matchingConstant =
+ matchingConstantIndices(clazz,
+ classConstant.u2nameIndex,
+ classPatternConstant.u2nameIndex);
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ MethodTypeConstant typePatternConstant = (MethodTypeConstant)patternConstant;
+
+ // Check the descriptor.
+ matchingConstant =
+ matchingConstantIndices(clazz,
+ methodTypeConstant.u2descriptorIndex,
+ typePatternConstant.u2descriptorIndex);
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ NameAndTypeConstant typePatternConstant = (NameAndTypeConstant)patternConstant;
+
+ // Check the name and the descriptor.
+ matchingConstant =
+ matchingConstantIndices(clazz,
+ nameAndTypeConstant.u2nameIndex,
+ typePatternConstant.u2nameIndex) &&
+ matchingConstantIndices(clazz,
+ nameAndTypeConstant.u2descriptorIndex,
+ typePatternConstant.u2descriptorIndex);
+ }
+
+
+ // Small utility methods.
+
+ private boolean matchingOpcodes(Instruction instruction1,
+ Instruction instruction2)
+ {
+ // Check the opcode.
+ return instruction1.opcode == instruction2.opcode ||
+ instruction1.canonicalOpcode() == instruction2.opcode;
+ }
+
+
+ private boolean matchingArguments(int argument1,
+ int argument2)
+ {
+ int argumentIndex = argument2 - X;
+ if (argumentIndex < 0)
+ {
+ // Check the literal argument.
+ return argument1 == argument2;
+ }
+ else if (!isMatchingArgumentIndex(argumentIndex))
+ {
+ // Store the wildcard argument.
+ setMatchingArgument(argumentIndex, argument1);
+
+ return true;
+ }
+ else
+ {
+ // Check the previously stored wildcard argument.
+ return matchedArguments[argumentIndex] == argument1;
+ }
+ }
+
+
+ /**
+ * Marks the specified argument (by index) as matching the specified
+ * argument value.
+ */
+ private void setMatchingArgument(int argumentIndex,
+ int argument)
+ {
+ matchedArguments[argumentIndex] = argument;
+ matchedArgumentFlags |= 1 << argumentIndex;
+ }
+
+
+ /**
+ * Returns whether the specified wildcard argument (by index) has been
+ * matched.
+ */
+ private boolean isMatchingArgumentIndex(int argumentIndex)
+ {
+ return (matchedArgumentFlags & (1 << argumentIndex)) != 0;
+ }
+
+
+ private boolean matchingArguments(int[] arguments1,
+ int[] arguments2)
+ {
+ if (arguments1.length != arguments2.length)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < arguments1.length; index++)
+ {
+ if (!matchingArguments(arguments1[index], arguments2[index]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ private boolean matchingConstantIndices(Clazz clazz,
+ int constantIndex1,
+ int constantIndex2)
+ {
+ if (constantIndex2 >= X)
+ {
+ // Remember that we are trying to match a constant.
+ constantFlags |= 1 << (constantIndex2 - X);
+
+ // Check the constant index.
+ return matchingArguments(constantIndex1, constantIndex2);
+ }
+ else if (!isMatchingConstantIndex(constantIndex2))
+ {
+ // Check the actual constant.
+ matchingConstant = false;
+ patternConstant = patternConstants[constantIndex2];
+
+ if (clazz.getTag(constantIndex1) == patternConstant.getTag())
+ {
+ clazz.constantPoolEntryAccept(constantIndex1, this);
+
+ if (matchingConstant)
+ {
+ // Store the constant index.
+ setMatchingConstant(constantIndex2, constantIndex1);
+ }
+ }
+
+ return matchingConstant;
+ }
+ else
+ {
+ // Check a previously stored constant index.
+ return matchedConstantIndices[constantIndex2] == constantIndex1;
+ }
+ }
+
+
+ /**
+ * Marks the specified constant (by index) as matching the specified
+ * constant index value.
+ */
+ private void setMatchingConstant(int constantIndex,
+ int constantIndex1)
+ {
+ matchedConstantIndices[constantIndex] = constantIndex1;
+ matchedConstantFlags[constantIndex / 64] |= 1L << constantIndex;
+ }
+
+
+ /**
+ * Returns whether the specified wildcard constant has been matched.
+ */
+ private boolean isMatchingConstantIndex(int constantIndex)
+ {
+ return (matchedConstantFlags[constantIndex / 64] & (1L << constantIndex)) != 0;
+ }
+
+
+ private boolean matchingBranchOffsets(int offset,
+ int branchOffset1,
+ int branchOffset2)
+ {
+ int argumentIndex = branchOffset2 - X;
+ if (argumentIndex < 0)
+ {
+ // Check the literal argument.
+ return branchOffset1 == branchOffset2;
+ }
+ else if (!isMatchingArgumentIndex(argumentIndex))
+ {
+ // Store a wildcard argument.
+ setMatchingArgument(argumentIndex, offset + branchOffset1);
+
+ return true;
+ }
+ else
+ {
+ // Check the previously stored wildcard argument.
+ return matchedArguments[argumentIndex] == offset + branchOffset1;
+ }
+ }
+
+
+ private boolean matchingJumpOffsets(int offset,
+ int[] jumpOffsets1,
+ int[] jumpOffsets2)
+ {
+ if (jumpOffsets1.length != jumpOffsets2.length)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < jumpOffsets1.length; index++)
+ {
+ if (!matchingBranchOffsets(offset,
+ jumpOffsets1[index],
+ jumpOffsets2[index]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ private void checkMatch(boolean condition,
+ Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int offset,
+ Instruction instruction)
+ {
+ if (DEBUG_MORE)
+ {
+ System.out.println("InstructionSequenceMatcher: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]: "+patternInstructions[patternInstructionIndex].toString(patternInstructionIndex)+(condition?"\t== ":"\t ")+instruction.toString(offset));
+ }
+
+ // Did the instruction match?
+ if (condition)
+ {
+ // Remember the offset of the matching instruction.
+ matchedInstructionOffsets[patternInstructionIndex] = offset;
+
+ // Try to match the next instruction next time.
+ patternInstructionIndex++;
+
+ // Did we match all instructions in the sequence?
+ matching = patternInstructionIndex == patternInstructions.length;
+
+ if (matching)
+ {
+ if (DEBUG)
+ {
+ System.out.println("InstructionSequenceMatcher: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ for (int index = 0; index < patternInstructionIndex; index++)
+ {
+ System.out.println(" "+InstructionFactory.create(codeAttribute.code, matchedInstructionOffsets[index]).toString(matchedInstructionOffsets[index]));
+ }
+ }
+
+ // Start matching from the first instruction again next time.
+ reset();
+ }
+ }
+ else
+ {
+ // The instruction didn't match.
+ matching = false;
+
+ // Is this a failed second instruction?
+ boolean retry = patternInstructionIndex == 1;
+
+ // Start matching from the first instruction next time.
+ reset();
+
+ // Retry a failed second instruction as a first instruction.
+ if (retry)
+ {
+ instruction.accept(clazz, method, codeAttribute, offset, this);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/InternalTypeEnumeration.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/InternalTypeEnumeration.java
new file mode 100644
index 0000000000..d1a41d969a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/InternalTypeEnumeration.java
@@ -0,0 +1,254 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.ClassConstants;
+
+
+/**
+ * An <code>InternalTypeEnumeration</code> provides an enumeration of all
+ * types listed in a given internal descriptor or signature of a class, a
+ * method, or a field.
+ *
+ * The leading formal type parameters, if any, can be retrieved separately.
+ *
+ * The return type of a method descriptor can also be retrieved separately.
+ *
+ * @author Eric Lafortune
+ */
+public class InternalTypeEnumeration
+{
+ private String descriptor;
+ private int formalTypeParametersIndex;
+ private int openIndex;
+ private int closeIndex;
+ private int index;
+
+
+ /**
+ * Creates a new InternalTypeEnumeration for the given method descriptor.
+ */
+ public InternalTypeEnumeration(String descriptor)
+ {
+ this.descriptor = descriptor;
+
+ // Find any formal type parameters.
+ if (descriptor.charAt(0) == ClassConstants.TYPE_GENERIC_START)
+ {
+ formalTypeParametersIndex = 1;
+
+ int nestingLevel = 1;
+ do
+ {
+ char c = descriptor.charAt(formalTypeParametersIndex++);
+ switch (c)
+ {
+ case ClassConstants.TYPE_GENERIC_START:
+ {
+ nestingLevel++;
+ break;
+ }
+ case ClassConstants.TYPE_GENERIC_END:
+ {
+ nestingLevel--;
+ break;
+ }
+ }
+ }
+ while (nestingLevel > 0);
+ }
+
+ this.openIndex = descriptor.indexOf(ClassConstants.METHOD_ARGUMENTS_OPEN,
+ formalTypeParametersIndex);
+
+ this.closeIndex = openIndex >= 0 ?
+ descriptor.indexOf(ClassConstants.METHOD_ARGUMENTS_CLOSE, openIndex) :
+ descriptor.length();
+
+ this.index = openIndex >= 0 ?
+ openIndex + 1 :
+ formalTypeParametersIndex;
+ }
+
+
+ /**
+ * Returns whether the descriptor has leading formal type parameters.
+ */
+ public boolean hasFormalTypeParameters()
+ {
+ return formalTypeParametersIndex > 0;
+ }
+
+
+ /**
+ * Returns the leading formal type parameters from the descriptor.
+ */
+ public String formalTypeParameters()
+ {
+ return descriptor.substring(0, formalTypeParametersIndex);
+ }
+
+
+ /**
+ * Returns whether the descriptor is a method signature.
+ */
+ public boolean isMethodSignature()
+ {
+ return openIndex >= 0;
+ }
+
+
+ /**
+ * Returns whether the enumeration can provide more types from the method
+ * descriptor.
+ */
+ public boolean hasMoreTypes()
+ {
+ return index < closeIndex;
+ }
+
+
+ /**
+ * Returns the next type from the method descriptor.
+ */
+ public String nextType()
+ {
+ int startIndex = index;
+
+ skipArray();
+
+ char c = descriptor.charAt(index++);
+ switch (c)
+ {
+ case ClassConstants.TYPE_CLASS_START:
+ case ClassConstants.TYPE_GENERIC_VARIABLE_START:
+ {
+ skipClass();
+ break;
+ }
+ case ClassConstants.TYPE_GENERIC_START:
+ {
+ skipGeneric();
+ break;
+ }
+ }
+
+ return descriptor.substring(startIndex, index);
+ }
+
+
+ /**
+ * Returns the return type from the descriptor, assuming it's a method
+ * descriptor.
+ */
+ public String returnType()
+ {
+ return descriptor.substring(closeIndex + 1);
+ }
+
+
+ // Small utility methods.
+
+ private void skipArray()
+ {
+ while (descriptor.charAt(index) == ClassConstants.TYPE_ARRAY)
+ {
+ index++;
+ }
+ }
+
+
+ private void skipClass()
+ {
+ while (true)
+ {
+ char c = descriptor.charAt(index++);
+ switch (c)
+ {
+ case ClassConstants.TYPE_GENERIC_START:
+ skipGeneric();
+ break;
+
+ case ClassConstants.TYPE_CLASS_END:
+ return;
+ }
+ }
+ }
+
+
+ private void skipGeneric()
+ {
+ int nestingLevel = 1;
+
+ do
+ {
+ char c = descriptor.charAt(index++);
+ switch (c)
+ {
+ case ClassConstants.TYPE_GENERIC_START:
+ nestingLevel++;
+ break;
+
+ case ClassConstants.TYPE_GENERIC_END:
+ nestingLevel--;
+ break;
+ }
+ }
+ while (nestingLevel > 0);
+ }
+
+
+ /**
+ * A main method for testing the type enumeration.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ for (int index = 0; index < args.length; index++)
+ {
+ String descriptor = args[index];
+
+ System.out.println("Descriptor ["+descriptor+"]");
+ InternalTypeEnumeration enumeration = new InternalTypeEnumeration(descriptor);
+
+ if (enumeration.hasFormalTypeParameters())
+ {
+ System.out.println(" Formal type parameters ["+enumeration.formalTypeParameters()+"]");
+ }
+
+ while (enumeration.hasMoreTypes())
+ {
+ System.out.println(" Type ["+enumeration.nextType()+"]");
+ }
+
+ if (enumeration.isMethodSignature())
+ {
+ System.out.println(" Return type ["+enumeration.returnType()+"]");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/MemberFinder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/MemberFinder.java
new file mode 100644
index 0000000000..d6eaa4ac58
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/MemberFinder.java
@@ -0,0 +1,197 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This class provides methods to find class members in a given class or in its
+ * hierarchy.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberFinder
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private static class MemberFoundException extends RuntimeException {}
+ private static final MemberFoundException MEMBER_FOUND = new MemberFoundException();
+
+ private Clazz clazz;
+ private Member member;
+
+
+ /**
+ * Finds the field with the given name and descriptor in the given
+ * class or its hierarchy.
+ */
+ public Field findField(Clazz referencingClass,
+ Clazz clazz,
+ String name,
+ String descriptor)
+ {
+ return (Field)findMember(referencingClass, clazz, name, descriptor, true);
+ }
+
+
+ /**
+ * Finds the method with the given name and descriptor in the given
+ * class or its hierarchy.
+ */
+ public Method findMethod(Clazz referencingClass,
+ Clazz clazz,
+ String name,
+ String descriptor)
+ {
+ return (Method)findMember(referencingClass, clazz, name, descriptor, false);
+ }
+
+
+ /**
+ * Finds the class member with the given name and descriptor in the given
+ * class or its hierarchy.
+ */
+ public Member findMember(Clazz referencingClass,
+ Clazz clazz,
+ String name,
+ String descriptor,
+ boolean isField)
+ {
+ // Organize a search in the hierarchy of superclasses and interfaces.
+ // The class member may be in a different class, if the code was
+ // compiled with "-target 1.2" or higher (the default in JDK 1.4).
+ try
+ {
+ this.clazz = null;
+ this.member = null;
+ clazz.hierarchyAccept(true, true, true, false, isField ?
+ (ClassVisitor)new NamedFieldVisitor(name, descriptor,
+ new MemberClassAccessFilter(referencingClass, this)) :
+ (ClassVisitor)new NamedMethodVisitor(name, descriptor,
+ new MemberClassAccessFilter(referencingClass, this)));
+ }
+ catch (MemberFoundException ex)
+ {
+ // We've found the member we were looking for.
+ }
+
+ return member;
+ }
+
+
+ /**
+ * Returns the corresponding class of the most recently found class
+ * member.
+ */
+ public Clazz correspondingClass()
+ {
+ return clazz;
+ }
+
+
+ /**
+ * Returns whether the given method is overridden anywhere down the class
+ * hierarchy.
+ */
+ public boolean isOverriden(Clazz clazz,
+ Method method)
+ {
+ String name = method.getName(clazz);
+ String descriptor = method.getDescriptor(clazz);
+
+ // Go looking for the method down the class hierarchy.
+ try
+ {
+ this.clazz = null;
+ this.member = null;
+
+ clazz.hierarchyAccept(false, false, false, true,
+ new NamedMethodVisitor(name, descriptor,
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, this)));
+ }
+ catch (MemberFoundException ex)
+ {
+ // We've found an overriding method.
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns whether the given field is shadowed anywhere down the class
+ * hierarchy.
+ */
+ public boolean isShadowed(Clazz clazz,
+ Field field)
+ {
+ String name = field.getName(clazz);
+ String descriptor = field.getDescriptor(clazz);
+
+ // Go looking for the field down the class hierarchy.
+ try
+ {
+ this.clazz = null;
+ this.member = null;
+ clazz.hierarchyAccept(false, false, false, true,
+ new NamedFieldVisitor(name, descriptor,
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, this)));
+ }
+ catch (MemberFoundException ex)
+ {
+ // We've found a shadowing field.
+ return true;
+ }
+
+ return false;
+ }
+
+
+// // Implementations for ClassVisitor.
+//
+// private void visitAnyClass(Clazz clazz)
+// {
+// if (member == null)
+// {
+// member = isField ?
+// (Member)clazz.findField(name, descriptor) :
+// (Member)clazz.findMethod(name, descriptor);
+//
+// if (member != null)
+// {
+// this.clazz = clazz;
+// }
+// }
+// }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ this.clazz = clazz;
+ this.member = member;
+
+ throw MEMBER_FOUND;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/MethodLinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/MethodLinker.java
new file mode 100644
index 0000000000..5eaa2d3ee1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/MethodLinker.java
@@ -0,0 +1,159 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.*;
+
+import java.util.*;
+
+/**
+ * This ClassVisitor links all corresponding non-private, non-static,
+ * non-initializer methods in the class hierarchies of all visited classes.
+ * Visited classes are typically all class files that are not being subclassed.
+ * Chains of links that have been created in previous invocations are merged
+ * with new chains of links, in order to create a consistent set of chains.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodLinker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor
+{
+ // An object that is reset and reused every time.
+ // The map: [class member name+' '+descriptor - class member info]
+ private final Map memberMap = new HashMap();
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ // Collect all non-private members in this class hierarchy.
+ clazz.hierarchyAccept(true, true, true, false,
+ new AllMethodVisitor(
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC,
+ this)));
+
+ // Clean up for the next class hierarchy.
+ memberMap.clear();
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ // Get the class member's name and descriptor.
+ String name = member.getName(clazz);
+ String descriptor = member.getDescriptor(clazz);
+
+ // Special cases: <clinit> and <init> are always kept unchanged.
+ // We can ignore them here.
+ if (ClassUtil.isInitializer(name))
+ {
+ return;
+ }
+
+ // See if we've already come across a method with the same name and
+ // descriptor.
+ String key = name + ' ' + descriptor;
+ Member otherMember = (Member)memberMap.get(key);
+
+ if (otherMember == null)
+ {
+ // Get the last method in the chain.
+ Member thisLastMember = lastMember(member);
+
+ // Store the new class method in the map.
+ memberMap.put(key, thisLastMember);
+ }
+ else
+ {
+ // Link both members.
+ link(member, otherMember);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Links the two given class members.
+ */
+ private static void link(Member member1, Member member2)
+ {
+ // Get the last methods in the both chains.
+ Member lastMember1 = lastMember(member1);
+ Member lastMember2 = lastMember(member2);
+
+ // Check if both link chains aren't already ending in the same element.
+ if (!lastMember1.equals(lastMember2))
+ {
+ // Merge the two chains, with the library members last.
+ if (lastMember2 instanceof LibraryMember)
+ {
+ lastMember1.setVisitorInfo(lastMember2);
+ }
+ else
+ {
+ lastMember2.setVisitorInfo(lastMember1);
+ }
+ }
+ }
+
+
+ /**
+ * Finds the last class member in the linked list of related class members.
+ * @param member the given class member.
+ * @return the last class member in the linked list.
+ */
+ public static Member lastMember(Member member)
+ {
+ Member lastMember = member;
+ while (lastMember.getVisitorInfo() != null &&
+ lastMember.getVisitorInfo() instanceof Member)
+ {
+ lastMember = (Member)lastMember.getVisitorInfo();
+ }
+
+ return lastMember;
+ }
+
+
+ /**
+ * Finds the last visitor accepter in the linked list of visitors.
+ * @param visitorAccepter the given method.
+ * @return the last method in the linked list.
+ */
+ public static VisitorAccepter lastVisitorAccepter(VisitorAccepter visitorAccepter)
+ {
+ VisitorAccepter lastVisitorAccepter = visitorAccepter;
+ while (lastVisitorAccepter.getVisitorInfo() != null &&
+ lastVisitorAccepter.getVisitorInfo() instanceof VisitorAccepter)
+ {
+ lastVisitorAccepter = (VisitorAccepter)lastVisitorAccepter.getVisitorInfo();
+ }
+
+ return lastVisitorAccepter;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/SimplifiedVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/SimplifiedVisitor.java
new file mode 100644
index 0000000000..c18135a045
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/SimplifiedVisitor.java
@@ -0,0 +1,1114 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.target.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.instruction.*;
+
+/**
+ * This abstract utility class allows to implement various visitor interfaces
+ * with simplified methods. The provided methods delegate to other versions
+ * with fewer arguments or more general arguments.
+ *
+ * @author Eric Lafortune
+ * @noinspection AbstractClassWithoutAbstractMethods
+ */
+public abstract class SimplifiedVisitor
+{
+ // Simplifications for ClassVisitor.
+
+ /**
+ * Visits any type of class member of the given class.
+ */
+ public void visitAnyClass(Clazz clazz)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ visitAnyClass(programClass);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ visitAnyClass(libraryClass);
+ }
+
+
+ // Simplifications for MemberVisitor.
+
+ /**
+ * Visits any type of class member of the given class.
+ */
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ /**
+ * Visits any type of class member of the given program class.
+ */
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ visitAnyMember(programClass, programMember);
+ }
+
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ visitProgramMember(programClass, programField);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ visitProgramMember(programClass, programMethod);
+ }
+
+
+ /**
+ * Visits any type of class member of the given library class.
+ */
+ public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)
+ {
+ visitAnyMember(libraryClass, libraryMember);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ visitLibraryMember(libraryClass, libraryField);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ visitLibraryMember(libraryClass, libraryMethod);
+ }
+
+
+ // Simplifications for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ visitAnyConstant(clazz, integerConstant);
+ }
+
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ visitAnyConstant(clazz, longConstant);
+ }
+
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ visitAnyConstant(clazz, floatConstant);
+ }
+
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ visitAnyConstant(clazz, doubleConstant);
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ visitAnyConstant(clazz, stringConstant);
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ visitAnyConstant(clazz, utf8Constant);
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ visitAnyConstant(clazz, invokeDynamicConstant);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ visitAnyConstant(clazz, methodHandleConstant);
+ }
+
+
+ /**
+ * Visits any type of RefConstant of the given class.
+ */
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ visitAnyConstant(clazz, refConstant);
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ visitAnyRefConstant(clazz, fieldrefConstant);
+ }
+
+
+ /**
+ * Visits any type of method RefConstant of the given class.
+ */
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ visitAnyRefConstant(clazz, refConstant);
+ }
+
+
+ public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
+ {
+ visitAnyMethodrefConstant(clazz, interfaceMethodrefConstant);
+ }
+
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ visitAnyMethodrefConstant(clazz, methodrefConstant);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ visitAnyConstant(clazz, classConstant);
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ visitAnyConstant(clazz, methodTypeConstant);
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ visitAnyConstant(clazz, nameAndTypeConstant);
+ }
+
+
+ // Simplifications for AttributeVisitor.
+
+ /**
+ * Visit any type of attribute.
+ */
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ visitAnyAttribute(clazz, unknownAttribute);
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ visitAnyAttribute(clazz, bootstrapMethodsAttribute);
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ visitAnyAttribute(clazz, sourceFileAttribute);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ visitAnyAttribute(clazz, sourceDirAttribute);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ visitAnyAttribute(clazz, innerClassesAttribute);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ visitAnyAttribute(clazz, enclosingMethodAttribute);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ visitAnyAttribute(clazz, deprecatedAttribute);
+ }
+
+
+ /**
+ * Visits the given DeprecatedAttribute of any type of class member.
+ */
+ public void visitDeprecatedAttribute(Clazz clazz, Member member, DeprecatedAttribute deprecatedAttribute)
+ {
+ visitDeprecatedAttribute(clazz, deprecatedAttribute);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute)
+ {
+ visitDeprecatedAttribute(clazz, (Member)field, deprecatedAttribute);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute)
+ {
+ visitDeprecatedAttribute(clazz, (Member)method, deprecatedAttribute);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ visitAnyAttribute(clazz, syntheticAttribute);
+ }
+
+
+ /**
+ * Visits the given SyntheticAttribute of any type of class member.
+ */
+ public void visitSyntheticAttribute(Clazz clazz, Member member, SyntheticAttribute syntheticAttribute)
+ {
+ visitSyntheticAttribute(clazz, syntheticAttribute);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute)
+ {
+ visitSyntheticAttribute(clazz, (Member)field, syntheticAttribute);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute)
+ {
+ visitSyntheticAttribute(clazz, (Member)method, syntheticAttribute);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ visitAnyAttribute(clazz, signatureAttribute);
+ }
+
+
+ /**
+ * Visits the given SignatureAttribute of any type of class member.
+ */
+ public void visitSignatureAttribute(Clazz clazz, Member member, SignatureAttribute signatureAttribute)
+ {
+ visitSignatureAttribute(clazz, signatureAttribute);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute signatureAttribute)
+ {
+ visitSignatureAttribute(clazz, (Member)field, signatureAttribute);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute)
+ {
+ visitSignatureAttribute(clazz, (Member)method, signatureAttribute);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ visitAnyAttribute(clazz, constantValueAttribute);
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ visitAnyAttribute(clazz, methodParametersAttribute);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ visitAnyAttribute(clazz, exceptionsAttribute);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ visitAnyAttribute(clazz, codeAttribute);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ visitAnyAttribute(clazz, stackMapAttribute);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ visitAnyAttribute(clazz, stackMapTableAttribute);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ visitAnyAttribute(clazz, lineNumberTableAttribute);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ visitAnyAttribute(clazz, localVariableTableAttribute);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ visitAnyAttribute(clazz, localVariableTypeTableAttribute);
+ }
+
+
+ /**
+ * Visits any type of AnnotationsAttribute of a class.
+ */
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ visitAnyAttribute(clazz, annotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ visitAnyAnnotationsAttribute(clazz, runtimeVisibleAnnotationsAttribute);
+ }
+
+
+ /**
+ * Visits the given RuntimeVisibleAnnotationsAttribute of any type of class member.
+ */
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Member member, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ visitRuntimeVisibleAnnotationsAttribute(clazz, runtimeVisibleAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ visitRuntimeVisibleAnnotationsAttribute(clazz, (Member)field, runtimeVisibleAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ visitRuntimeVisibleAnnotationsAttribute(clazz, (Member)method, runtimeVisibleAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ visitAnyAnnotationsAttribute(clazz, runtimeInvisibleAnnotationsAttribute);
+ }
+
+
+ /**
+ * Visits the given RuntimeInvisibleAnnotationsAttribute of any type of class member.
+ */
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Member member, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ visitRuntimeInvisibleAnnotationsAttribute(clazz, runtimeInvisibleAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ visitRuntimeInvisibleAnnotationsAttribute(clazz, (Member)field, runtimeInvisibleAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ visitRuntimeInvisibleAnnotationsAttribute(clazz, (Member)method, runtimeInvisibleAnnotationsAttribute);
+ }
+
+
+ /**
+ * Visits any type of ParameterAnnotationsAttribute.
+ */
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ visitAnyAttribute(clazz, parameterAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
+ {
+ visitAnyParameterAnnotationsAttribute(clazz, method, runtimeVisibleParameterAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
+ {
+ visitAnyParameterAnnotationsAttribute(clazz, method, runtimeInvisibleParameterAnnotationsAttribute);
+ }
+
+
+ /**
+ * Visits any type of TypeAnnotationsAttribute of a class.
+ */
+ public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute)
+ {
+ visitAnyAnnotationsAttribute(clazz, typeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ visitAnyTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute);
+ }
+
+
+ /**
+ * Visits the given RuntimeVisibleTypeAnnotationsAttribute of any type of class member.
+ */
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Member member, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ visitRuntimeVisibleTypeAnnotationsAttribute(clazz, (Member)field, runtimeVisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ visitRuntimeVisibleTypeAnnotationsAttribute(clazz, (Member)method, runtimeVisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ visitAnyTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+
+
+ /**
+ * Visits the given RuntimeInvisibleTypeAnnotationsAttribute of any type of class member.
+ */
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Member member, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, (Member)field, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, (Member)method, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ visitAnyAttribute(clazz, annotationDefaultAttribute);
+ }
+
+
+ // Simplifications for InstructionVisitor.
+
+ /**
+ * Visits any type of Instruction.
+ */
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ visitAnyInstruction(clazz, method, codeAttribute, offset, simpleInstruction);
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ visitAnyInstruction(clazz, method, codeAttribute, offset, variableInstruction);
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ visitAnyInstruction(clazz, method, codeAttribute, offset, constantInstruction);
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ visitAnyInstruction(clazz, method, codeAttribute, offset, branchInstruction);
+ }
+
+
+ /**
+ * Visits either type of SwitchInstruction.
+ */
+ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ {
+ visitAnyInstruction(clazz, method, codeAttribute, offset, switchInstruction);
+ }
+
+
+ public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
+ {
+ visitAnySwitchInstruction(clazz, method, codeAttribute, offset, tableSwitchInstruction);
+ }
+
+
+ public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
+ {
+ visitAnySwitchInstruction(clazz, method, codeAttribute, offset, lookUpSwitchInstruction);
+ }
+
+
+ // Simplifications for StackMapFrameVisitor.
+
+ /**
+ * Visits any type of VerificationType.
+ */
+ public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame)
+ {
+ visitAnyStackMapFrame(clazz, method, codeAttribute, offset, sameZeroFrame);
+ }
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ visitAnyStackMapFrame(clazz, method, codeAttribute, offset, sameOneFrame);
+ }
+
+
+ public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame)
+ {
+ visitAnyStackMapFrame(clazz, method, codeAttribute, offset, lessZeroFrame);
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ visitAnyStackMapFrame(clazz, method, codeAttribute, offset, moreZeroFrame);
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ visitAnyStackMapFrame(clazz, method, codeAttribute, offset, fullFrame);
+ }
+
+
+ // Simplifications for VerificationTypeVisitor.
+
+ /**
+ * Visits any type of VerificationType.
+ */
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ public void visitIntegerType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, IntegerType integerType)
+ {
+ visitAnyVerificationType(clazz, method, codeAttribute, offset, integerType);
+ }
+
+
+ public void visitFloatType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FloatType floatType)
+ {
+ visitAnyVerificationType(clazz, method, codeAttribute, offset, floatType);
+ }
+
+
+ public void visitLongType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LongType longType)
+ {
+ visitAnyVerificationType(clazz, method, codeAttribute, offset, longType);
+ }
+
+
+ public void visitDoubleType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, DoubleType doubleType)
+ {
+ visitAnyVerificationType(clazz, method, codeAttribute, offset, doubleType);
+ }
+
+
+ public void visitTopType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TopType topType)
+ {
+ visitAnyVerificationType(clazz, method, codeAttribute, offset, topType);
+ }
+
+
+ public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
+ {
+ visitAnyVerificationType(clazz, method, codeAttribute, offset, objectType);
+ }
+
+
+ public void visitNullType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, NullType nullType)
+ {
+ visitAnyVerificationType(clazz, method, codeAttribute, offset, nullType);
+ }
+
+
+ public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
+ {
+ visitAnyVerificationType(clazz, method, codeAttribute, offset, uninitializedType);
+ }
+
+
+ public void visitUninitializedThisType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedThisType uninitializedThisType)
+ {
+ visitAnyVerificationType(clazz, method, codeAttribute, offset, uninitializedThisType);
+ }
+
+
+ public void visitStackIntegerType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, IntegerType integerType)
+ {
+ visitIntegerType(clazz, method, codeAttribute, offset, integerType);
+ }
+
+
+ public void visitStackFloatType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, FloatType floatType)
+ {
+ visitFloatType(clazz, method, codeAttribute, offset, floatType);
+ }
+
+
+ public void visitStackLongType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, LongType longType)
+ {
+ visitLongType(clazz, method, codeAttribute, offset, longType);
+ }
+
+
+ public void visitStackDoubleType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, DoubleType doubleType)
+ {
+ visitDoubleType(clazz, method, codeAttribute, offset, doubleType);
+ }
+
+
+ public void visitStackTopType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, TopType topType)
+ {
+ visitTopType(clazz, method, codeAttribute, offset, topType);
+ }
+
+
+ public void visitStackObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, ObjectType objectType)
+ {
+ visitObjectType(clazz, method, codeAttribute, offset, objectType);
+ }
+
+
+ public void visitStackNullType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, NullType nullType)
+ {
+ visitNullType(clazz, method, codeAttribute, offset, nullType);
+ }
+
+
+ public void visitStackUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, UninitializedType uninitializedType)
+ {
+ visitUninitializedType(clazz, method, codeAttribute, offset, uninitializedType);
+ }
+
+
+ public void visitStackUninitializedThisType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, UninitializedThisType uninitializedThisType)
+ {
+ visitUninitializedThisType(clazz, method, codeAttribute, offset, uninitializedThisType);
+ }
+
+
+
+ public void visitVariablesIntegerType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, IntegerType integerType)
+ {
+ visitIntegerType(clazz, method, codeAttribute, offset, integerType);
+ }
+
+
+ public void visitVariablesFloatType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, FloatType floatType)
+ {
+ visitFloatType(clazz, method, codeAttribute, offset, floatType);
+ }
+
+
+ public void visitVariablesLongType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, LongType longType)
+ {
+ visitLongType(clazz, method, codeAttribute, offset, longType);
+ }
+
+
+ public void visitVariablesDoubleType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, DoubleType doubleType)
+ {
+ visitDoubleType(clazz, method, codeAttribute, offset, doubleType);
+ }
+
+
+ public void visitVariablesTopType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, TopType topType)
+ {
+ visitTopType(clazz, method, codeAttribute, offset, topType);
+ }
+
+
+ public void visitVariablesObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, ObjectType objectType)
+ {
+ visitObjectType(clazz, method, codeAttribute, offset, objectType);
+ }
+
+
+ public void visitVariablesNullType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, NullType nullType)
+ {
+ visitNullType(clazz, method, codeAttribute, offset, nullType);
+ }
+
+
+ public void visitVariablesUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, UninitializedType uninitializedType)
+ {
+ visitUninitializedType(clazz, method, codeAttribute, offset, uninitializedType);
+ }
+
+
+ public void visitVariablesUninitializedThisType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int index, UninitializedThisType uninitializedThisType)
+ {
+ visitUninitializedThisType(clazz, method, codeAttribute, offset, uninitializedThisType);
+ }
+
+
+ // Simplifications for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ /**
+ * Visits the given Annotation of any type of class member.
+ */
+ public void visitAnnotation(Clazz clazz, Member member, Annotation annotation)
+ {
+ visitAnnotation(clazz, annotation);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Field field, Annotation annotation)
+ {
+ visitAnnotation(clazz, (Member)field, annotation);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, Annotation annotation)
+ {
+ visitAnnotation(clazz, (Member)method, annotation);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, int parameterIndex, Annotation annotation)
+ {
+ visitAnnotation(clazz, method, annotation);
+ }
+
+
+ public void visitAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, Annotation annotation)
+ {
+ visitAnnotation(clazz, method, annotation);
+ }
+
+
+ // Simplifications for TypeAnnotationVisitor.
+
+ public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ /**
+ * Visits the given TypeAnnotation of any type of class member.
+ */
+ public void visitTypeAnnotation(Clazz clazz, Member member, TypeAnnotation typeAnnotation)
+ {
+ visitTypeAnnotation(clazz, typeAnnotation);
+ }
+
+
+ public void visitTypeAnnotation(Clazz clazz, Field field, TypeAnnotation typeAnnotation)
+ {
+ visitTypeAnnotation(clazz, (Member)field, typeAnnotation);
+ }
+
+
+ public void visitTypeAnnotation(Clazz clazz, Method method, TypeAnnotation typeAnnotation)
+ {
+ visitTypeAnnotation(clazz, (Member)method, typeAnnotation);
+ }
+
+
+ public void visitTypeAnnotation(Clazz clazz, Method method, int parameterIndex, TypeAnnotation typeAnnotation)
+ {
+ visitTypeAnnotation(clazz, method, typeAnnotation);
+ }
+
+
+ public void visitTypeAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation)
+ {
+ visitTypeAnnotation(clazz, method, typeAnnotation);
+ }
+
+
+ // Simplifications for TargetInfoVisitor.
+
+ /**
+ * Visits any type of TargetInfo.
+ */
+ public void visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo)
+ {
+ visitAnyTargetInfo(clazz, typeAnnotation, typeParameterTargetInfo);
+ }
+
+
+ public void visitTypeParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo)
+ {
+ visitTypeParameterTargetInfo(clazz, typeAnnotation, typeParameterTargetInfo);
+ }
+
+
+ public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo)
+ {
+ visitAnyTargetInfo(clazz, typeAnnotation, superTypeTargetInfo);
+ }
+
+
+ public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)
+ {
+ visitAnyTargetInfo(clazz, typeAnnotation, typeParameterBoundTargetInfo);
+ }
+
+
+ /**
+ * Visits the given TypeParameterBoundTargetInfo of any type of class member.
+ */
+ public void visitTypeParameterBoundTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)
+ {
+ visitTypeParameterBoundTargetInfo(clazz, typeAnnotation, typeParameterBoundTargetInfo);
+ }
+
+
+ public void visitTypeParameterBoundTargetInfo(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)
+ {
+ visitTypeParameterBoundTargetInfo(clazz, (Member)field, typeAnnotation, typeParameterBoundTargetInfo);
+ }
+
+
+ public void visitTypeParameterBoundTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)
+ {
+ visitTypeParameterBoundTargetInfo(clazz, (Member)method, typeAnnotation, typeParameterBoundTargetInfo);
+ }
+
+
+ /**
+ * Visits the given EmptyTargetInfo of any type of class member.
+ */
+ public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo)
+ {
+ visitAnyTargetInfo(clazz, typeAnnotation, emptyTargetInfo);
+ }
+
+
+ public void visitEmptyTargetInfo(Clazz clazz, Field field, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo)
+ {
+ visitEmptyTargetInfo(clazz, (Member)field, typeAnnotation, emptyTargetInfo);
+ }
+
+
+ public void visitEmptyTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo)
+ {
+ visitEmptyTargetInfo(clazz, (Member)method, typeAnnotation, emptyTargetInfo);
+ }
+
+
+ public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo)
+ {
+ visitAnyTargetInfo(clazz, typeAnnotation, formalParameterTargetInfo);
+ }
+
+
+ public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo)
+ {
+ visitAnyTargetInfo(clazz, typeAnnotation, throwsTargetInfo);
+ }
+
+
+ public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)
+ {
+ visitAnyTargetInfo(clazz, typeAnnotation, localVariableTargetInfo);
+ }
+
+
+ public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo)
+ {
+ visitAnyTargetInfo(clazz, typeAnnotation, catchTargetInfo);
+ }
+
+
+ public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo)
+ {
+ visitAnyTargetInfo(clazz, typeAnnotation, offsetTargetInfo);
+ }
+
+
+ public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo)
+ {
+ visitAnyTargetInfo(clazz, typeAnnotation, typeArgumentTargetInfo);
+ }
+
+
+ // Simplifications for TypePathInfoVisitor.
+
+ public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ /**
+ * Visits the given TypePathInfo of any type of class member.
+ */
+ public void visitTypePathInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)
+ {
+ visitTypePathInfo(clazz, typeAnnotation, typePathInfo);
+ }
+
+
+ public void visitTypePathInfo(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)
+ {
+ visitTypePathInfo(clazz, (Member)field, typeAnnotation, typePathInfo);
+ }
+
+
+ public void visitTypePathInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)
+ {
+ visitTypePathInfo(clazz, (Member)method, typeAnnotation, typePathInfo);
+ }
+
+
+ public void visitTypePathInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)
+ {
+ visitTypePathInfo(clazz, method, typeAnnotation, typePathInfo);
+ }
+
+
+ // Simplifications for ElementValueVisitor.
+
+ /**
+ * Visits any type of ElementValue.
+ */
+ public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue)
+ {
+ throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called");
+ }
+
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ visitAnyElementValue(clazz, annotation, constantElementValue);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ visitAnyElementValue(clazz, annotation, enumConstantElementValue);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ visitAnyElementValue(clazz, annotation, classElementValue);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ visitAnyElementValue(clazz, annotation, annotationElementValue);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ visitAnyElementValue(clazz, annotation, arrayElementValue);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/StringReferenceInitializer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/StringReferenceInitializer.java
new file mode 100644
index 0000000000..2cc1032554
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/StringReferenceInitializer.java
@@ -0,0 +1,90 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This ConstantVisitor initializes any class references of all string constants
+ * it visits. More specifically, it fills out the references of string constant
+ * pool entries that happen to refer to a class in the program class pool or in
+ * the library class pool.
+ *
+ * @author Eric Lafortune
+ */
+public class StringReferenceInitializer
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final ClassPool programClassPool;
+ private final ClassPool libraryClassPool;
+
+
+ /**
+ * Creates a new StringReferenceInitializer.
+ */
+ public StringReferenceInitializer(ClassPool programClassPool,
+ ClassPool libraryClassPool)
+ {
+ this.programClassPool = programClassPool;
+ this.libraryClassPool = libraryClassPool;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ if (stringConstant.referencedClass == null)
+ {
+ // See if we can find the referenced class.
+ stringConstant.referencedClass =
+ findClass(ClassUtil.internalClassName(
+ ClassUtil.externalBaseType(stringConstant.getString(clazz))));
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the class with the given name, either for the program class pool
+ * or from the library class pool, or <code>null</code> if it can't be found.
+ */
+ private Clazz findClass(String name)
+ {
+ // First look for the class in the program class pool.
+ Clazz clazz = programClassPool.getClass(name);
+
+ // Otherwise look for the class in the library class pool.
+ if (clazz == null)
+ {
+ clazz = libraryClassPool.getClass(name);
+ }
+
+ return clazz;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/StringSharer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/StringSharer.java
new file mode 100644
index 0000000000..d2d5023dfa
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/StringSharer.java
@@ -0,0 +1,172 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor shares strings in the class files that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class StringSharer
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor,
+ AttributeVisitor
+{
+ // A fields acting as an argument for the visitor methods.
+ private String name;
+ private String type;
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Replace name strings in the constant pool by shared strings.
+ programClass.constantPoolEntriesAccept(this);
+
+ // Replace attribute name strings in the constant pool by internalized
+ // strings.
+ programClass.attributesAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Replace the super class name string by the shared name string.
+ Clazz superClass = libraryClass.superClass;
+ if (superClass != null)
+ {
+ libraryClass.superClassName = superClass.getName();
+ }
+
+ // Replace the interface name strings by the shared name strings.
+ if (libraryClass.interfaceNames != null)
+ {
+ String[] interfaceNames = libraryClass.interfaceNames;
+ Clazz[] interfaceClasses = new Clazz[interfaceNames.length];
+
+ for (int index = 0; index < interfaceNames.length; index++)
+ {
+ // Keep a reference to the interface class.
+ Clazz interfaceClass = interfaceClasses[index];
+ if (interfaceClass != null)
+ {
+ interfaceNames[index] = interfaceClass.getName();
+ }
+ }
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ Member referencedMember = stringConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ Clazz referencedClass = stringConstant.referencedClass;
+
+ // Put the actual class member's name in the class pool.
+ name = referencedMember.getName(referencedClass);
+ clazz.constantPoolEntryAccept(stringConstant.u2stringIndex, this);
+ }
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ Clazz referencedClass = refConstant.referencedClass;
+
+ // Put the actual class member's name and type strings in the class
+ // pool.
+ name = referencedMember.getName(referencedClass);
+ type = referencedMember.getDescriptor(referencedClass);
+ clazz.constantPoolEntryAccept(refConstant.u2nameAndTypeIndex, this);
+ }
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ if (name != null)
+ {
+ // Put the actual class member's name and type strings in the class
+ // pool.
+ clazz.constantPoolEntryAccept(nameAndTypeConstant.u2nameIndex, this);
+ name = type;
+ clazz.constantPoolEntryAccept(nameAndTypeConstant.u2descriptorIndex, this);
+ }
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ Clazz referencedClass = classConstant.referencedClass;
+ if (referencedClass != null)
+ {
+ // Put the actual class's name string in the class pool.
+ name = referencedClass.getName();
+ clazz.constantPoolEntryAccept(classConstant.u2nameIndex, this);
+ }
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ // Do we have a new string to put into this constant?
+ if (name != null)
+ {
+ // Replace the string, if it's actually the same.
+ if (name.equals(utf8Constant.getString()))
+ {
+ utf8Constant.setString(name);
+ }
+
+ name = null;
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute)
+ {
+ // Put the internalized attribute's name string in the class pool.
+ name = attribute.getAttributeName(clazz).intern();
+ clazz.constantPoolEntryAccept(attribute.u2attributeNameIndex, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/WarningPrinter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/WarningPrinter.java
new file mode 100644
index 0000000000..c4bc232470
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/WarningPrinter.java
@@ -0,0 +1,136 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.util;
+
+import proguard.util.*;
+
+import java.io.PrintStream;
+import java.util.List;
+
+/**
+ * This class prints out and counts warnings.
+ *
+ * @author Eric Lafortune
+ */
+public class WarningPrinter
+{
+ private final PrintStream printStream;
+ private final StringMatcher classFilter;
+ private int warningCount;
+
+
+ /**
+ * Creates a new WarningPrinter that prints to the System.err print stream.
+ */
+ public WarningPrinter()
+ {
+ this(System.err);
+ }
+
+
+ /**
+ * Creates a new WarningPrinter that prints to the given print stream.
+ */
+ public WarningPrinter(PrintStream printStream)
+ {
+ this.printStream = printStream;
+ this.classFilter = null;
+ }
+
+
+ /**
+ * Creates a new WarningPrinter that prints to the given print stream,
+ * except if the names of any involved classes matches the given filter.
+ */
+ public WarningPrinter(PrintStream printStream, List classFilter)
+ {
+ this.printStream = printStream;
+ this.classFilter = classFilter == null ? null :
+ new ListParser(new ClassNameParser()).parse(classFilter);
+ }
+
+
+ /**
+ * Prints out the given warning and increments the warning count, if
+ * the given class name passes the class name filter.
+ */
+ public void print(String className, String warning)
+ {
+ if (accepts(className))
+ {
+ print(warning);
+ }
+ }
+
+
+ /**
+ * Returns whether the given class name passes the class name filter.
+ */
+ public boolean accepts(String className)
+ {
+ return classFilter == null ||
+ !classFilter.matches(className);
+ }
+
+
+ /**
+ * Prints out the given warning and increments the warning count, if
+ * the given class names pass the class name filter.
+ */
+ public void print(String className1, String className2, String warning)
+ {
+ if (accepts(className1, className2))
+ {
+ print(warning);
+ }
+ }
+
+
+ /**
+ * Returns whether the given class names pass the class name filter.
+ */
+ public boolean accepts(String className1, String className2)
+ {
+ return classFilter == null ||
+ !(classFilter.matches(className1) ||
+ classFilter.matches(className2));
+ }
+
+
+ /**
+ * Prints out the given warning and increments the warning count.
+ */
+ private void print(String warning)
+ {
+ printStream.println(warning);
+
+ warningCount++;
+ }
+
+
+ /**
+ * Returns the number of warnings printed so far.
+ */
+ public int getWarningCount()
+ {
+ return warningCount;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/package.html
new file mode 100644
index 0000000000..b1b881ec56
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/util/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains utility classes for processing class files.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllClassVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllClassVisitor.java
new file mode 100644
index 0000000000..e7f670fd48
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllClassVisitor.java
@@ -0,0 +1,47 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.ClassPool;
+
+
+/**
+ * This ClassPoolVisitor lets a given ClassVisitor visit all Clazz
+ * objects of the class pools it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllClassVisitor implements ClassPoolVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public AllClassVisitor(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ public void visitClassPool(ClassPool classPool)
+ {
+ classPool.classesAccept(classVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllFieldVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllFieldVisitor.java
new file mode 100644
index 0000000000..a449089d3b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllFieldVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This ClassVisitor lets a given MemberVisitor visit all FieldMember
+ * objects of the classes it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllFieldVisitor implements ClassVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ public AllFieldVisitor(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.fieldsAccept(memberVisitor);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ libraryClass.fieldsAccept(memberVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllMemberVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllMemberVisitor.java
new file mode 100644
index 0000000000..92e31d501f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllMemberVisitor.java
@@ -0,0 +1,57 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This ClassVisitor lets a given MemberVisitor visit all Member
+ * objects of the classes it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllMemberVisitor implements ClassVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ public AllMemberVisitor(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.fieldsAccept(memberVisitor);
+ programClass.methodsAccept(memberVisitor);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ libraryClass.fieldsAccept(memberVisitor);
+ libraryClass.methodsAccept(memberVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllMethodVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllMethodVisitor.java
new file mode 100644
index 0000000000..af34fea5c8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/AllMethodVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This ClassVisitor lets a given MemberVisitor visit all MethodMember
+ * objects of the classes it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AllMethodVisitor implements ClassVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ public AllMethodVisitor(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.methodsAccept(memberVisitor);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ libraryClass.methodsAccept(memberVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/BottomClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/BottomClassFilter.java
new file mode 100644
index 0000000000..89f2407161
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/BottomClassFilter.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to another given
+ * <code>ClassVisitor</code>, but only when visiting classes that don't
+ * have any subclasses.
+ *
+ * @author Eric Lafortune
+ */
+public class BottomClassFilter implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ProgramClassFilter.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits
+ * will be delegated.
+ */
+ public BottomClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Is this a bottom class in the class hierarchy?
+ if (programClass.subClasses == null)
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Is this a bottom class in the class hierarchy?
+ if (libraryClass.subClasses == null)
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassAccessFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassAccessFilter.java
new file mode 100644
index 0000000000..3637270d34
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassAccessFilter.java
@@ -0,0 +1,88 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to another given
+ * <code>ClassVisitor</code>, but only when the visited class
+ * has the proper access flags.
+ *
+ * @see ClassConstants
+ *
+ * @author Eric Lafortune
+ */
+public class ClassAccessFilter implements ClassVisitor
+{
+ private final int requiredSetAccessFlags;
+ private final int requiredUnsetAccessFlags;
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ClassAccessFilter.
+ * @param requiredSetAccessFlags the class access flags that should be
+ * set.
+ * @param requiredUnsetAccessFlags the class access flags that should be
+ * unset.
+ * @param classVisitor the <code>ClassVisitor</code> to
+ * which visits will be delegated.
+ */
+ public ClassAccessFilter(int requiredSetAccessFlags,
+ int requiredUnsetAccessFlags,
+ ClassVisitor classVisitor)
+ {
+ this.requiredSetAccessFlags = requiredSetAccessFlags;
+ this.requiredUnsetAccessFlags = requiredUnsetAccessFlags;
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (accepted(programClass.getAccessFlags()))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (accepted(libraryClass.getAccessFlags()))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean accepted(int accessFlags)
+ {
+ return (requiredSetAccessFlags & ~accessFlags) == 0 &&
+ (requiredUnsetAccessFlags & accessFlags) == 0;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCleaner.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCleaner.java
new file mode 100644
index 0000000000..dffe11820a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCleaner.java
@@ -0,0 +1,364 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.Constant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This <code>ClassVisitor</code> removes all visitor information of the
+ * classes it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassCleaner
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor,
+ MemberVisitor,
+ AttributeVisitor,
+ BootstrapMethodInfoVisitor,
+ ExceptionInfoVisitor,
+ InnerClassesInfoVisitor,
+ StackMapFrameVisitor,
+ VerificationTypeVisitor,
+ ParameterInfoVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ TypeAnnotationVisitor,
+ ElementValueVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ clean(programClass);
+
+ programClass.constantPoolEntriesAccept(this);
+
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ programClass.attributesAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ clean(libraryClass);
+
+ libraryClass.fieldsAccept(this);
+ libraryClass.methodsAccept(this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ clean(constant);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ clean(programMember);
+
+ programMember.attributesAccept(programClass, this);
+ }
+
+
+ public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)
+ {
+ clean(libraryMember);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute)
+ {
+ clean(attribute);
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ clean(bootstrapMethodsAttribute);
+
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ clean(innerClassesAttribute);
+
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ clean(methodParametersAttribute);
+
+ methodParametersAttribute.parametersAccept(clazz, method, this);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ clean(exceptionsAttribute);
+
+ exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ clean(codeAttribute);
+
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ clean(stackMapAttribute);
+
+ stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ clean(stackMapTableAttribute);
+
+ stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ clean(localVariableTableAttribute);
+
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ clean(localVariableTypeTableAttribute);
+
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ clean(annotationsAttribute);
+
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ clean(parameterAnnotationsAttribute);
+
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute)
+ {
+ clean(typeAnnotationsAttribute);
+
+ typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ clean(annotationDefaultAttribute);
+
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ clean(bootstrapMethodInfo);
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ clean(innerClassesInfo);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ clean(exceptionInfo);
+ }
+
+
+ // Implementations for StackMapFrameVisitor.
+
+ public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame)
+ {
+ clean(sameZeroFrame);
+ }
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ clean(sameOneFrame);
+
+ sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame)
+ {
+ clean(lessZeroFrame);
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ clean(moreZeroFrame);
+
+ moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ clean(fullFrame);
+
+ fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
+ fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType)
+ {
+ clean(verificationType);
+ }
+
+
+ // Implementations for ParameterInfoVisitor.
+
+ public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
+ {
+ clean(parameterInfo);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ clean(localVariableInfo);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ clean(localVariableTypeInfo);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ clean(annotation);
+
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for TypeAnnotationVisitor.
+
+ public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)
+ {
+ clean(typeAnnotation);
+
+ //typeAnnotation.targetInfoAccept(clazz, this);
+ //typeAnnotation.typePathInfosAccept(clazz, this);
+ typeAnnotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue)
+ {
+ clean(elementValue);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ clean(annotationElementValue);
+
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ clean(arrayElementValue);
+ }
+
+
+ // Small utility methods.
+
+ private void clean(VisitorAccepter visitorAccepter)
+ {
+ visitorAccepter.setVisitorInfo(null);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCollector.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCollector.java
new file mode 100644
index 0000000000..1a65fccb03
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCollector.java
@@ -0,0 +1,58 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.util.SimplifiedVisitor;
+
+import java.util.Set;
+
+/**
+ * This <code>ClassVisitor</code> collects the classes that it visits in the
+ * given collection.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassCollector
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final Set set;
+
+
+ /**
+ * Creates a new ClassCollector.
+ * @param set the <code>Set</code> in which all class names will be
+ * collected.
+ */
+ public ClassCollector(Set set)
+ {
+ this.set = set;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ set.add(clazz);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCounter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCounter.java
new file mode 100644
index 0000000000..850a64cf0f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassCounter.java
@@ -0,0 +1,56 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+/**
+ * This ClassVisitor counts the number of classes that has been visited.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassCounter implements ClassVisitor
+{
+ private int count;
+
+
+ /**
+ * Returns the number of classes that has been visited so far.
+ */
+ public int getCount()
+ {
+ return count;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ count++;
+ }
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ count++;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassHierarchyTraveler.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
new file mode 100644
index 0000000000..a14e1320c0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
@@ -0,0 +1,91 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This <code>ClassVisitor</code> lets a given <code>ClassVisitor</code>
+ * optionally travel to the visited class, its superclass, its interfaces, and
+ * its subclasses.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassHierarchyTraveler implements ClassVisitor
+{
+ private final boolean visitThisClass;
+ private final boolean visitSuperClass;
+ private final boolean visitInterfaces;
+ private final boolean visitSubclasses;
+
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ClassHierarchyTraveler.
+ * @param visitThisClass specifies whether to visit the originally visited
+ * classes.
+ * @param visitSuperClass specifies whether to visit the super classes of
+ * the visited classes.
+ * @param visitInterfaces specifies whether to visit the interfaces of
+ * the visited classes.
+ * @param visitSubclasses specifies whether to visit the subclasses of
+ * the visited classes.
+ * @param classVisitor the <code>ClassVisitor</code> to
+ * which visits will be delegated.
+ */
+ public ClassHierarchyTraveler(boolean visitThisClass,
+ boolean visitSuperClass,
+ boolean visitInterfaces,
+ boolean visitSubclasses,
+ ClassVisitor classVisitor)
+ {
+ this.visitThisClass = visitThisClass;
+ this.visitSuperClass = visitSuperClass;
+ this.visitInterfaces = visitInterfaces;
+ this.visitSubclasses = visitSubclasses;
+
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.hierarchyAccept(visitThisClass,
+ visitSuperClass,
+ visitInterfaces,
+ visitSubclasses,
+ classVisitor);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ libraryClass.hierarchyAccept(visitThisClass,
+ visitSuperClass,
+ visitInterfaces,
+ visitSubclasses,
+ classVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassNameFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassNameFilter.java
new file mode 100644
index 0000000000..297e8fa7f7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassNameFilter.java
@@ -0,0 +1,112 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.util.*;
+
+import java.util.List;
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to another given
+ * <code>ClassVisitor</code>, but only when the visited class has a name that
+ * matches a given regular expression.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassNameFilter implements ClassVisitor
+{
+ private final StringMatcher regularExpressionMatcher;
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ClassNameFilter.
+ * @param regularExpression the regular expression against which class names
+ * will be matched.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ClassNameFilter(String regularExpression,
+ ClassVisitor classVisitor)
+ {
+ this(new ListParser(new ClassNameParser()).parse(regularExpression),
+ classVisitor);
+ }
+
+
+ /**
+ * Creates a new ClassNameFilter.
+ * @param regularExpression the regular expression against which class names
+ * will be matched.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ClassNameFilter(List regularExpression,
+ ClassVisitor classVisitor)
+ {
+ this(new ListParser(new ClassNameParser()).parse(regularExpression),
+ classVisitor);
+ }
+
+
+ /**
+ * Creates a new ClassNameFilter.
+ * @param regularExpressionMatcher the string matcher against which
+ * class names will be matched.
+ * @param classVisitor the <code>ClassVisitor</code> to which
+ * visits will be delegated.
+ */
+ public ClassNameFilter(StringMatcher regularExpressionMatcher,
+ ClassVisitor classVisitor)
+ {
+ this.regularExpressionMatcher = regularExpressionMatcher;
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (accepted(programClass.getName()))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (accepted(libraryClass.getName()))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean accepted(String name)
+ {
+ return regularExpressionMatcher.matches(name);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolFiller.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolFiller.java
new file mode 100644
index 0000000000..b6c5352175
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolFiller.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+
+/**
+ * This ClassVisitor collects all the classes it visits in a given
+ * class pool.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassPoolFiller
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final ClassPool classPool;
+
+
+ /**
+ * Creates a new ClassPoolFiller.
+ */
+ public ClassPoolFiller(ClassPool classPool)
+ {
+ this.classPool = classPool;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ classPool.addClass(clazz);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolRemover.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolRemover.java
new file mode 100644
index 0000000000..71e421d8fe
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolRemover.java
@@ -0,0 +1,54 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This ClassVisitor removes all the classes it visits from a given
+ * class pool.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassPoolRemover
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final ClassPool classPool;
+
+
+ /**
+ * Creates a new ClassPoolFiller.
+ */
+ public ClassPoolRemover(ClassPool classPool)
+ {
+ this.classPool = classPool;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ classPool.removeClass(clazz);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolVisitor.java
new file mode 100644
index 0000000000..ae6a6ac6c4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPoolVisitor.java
@@ -0,0 +1,37 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.ClassPool;
+
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>ClassPool</code> objects. Note that there is only a single
+ * implementation of <code>ClassPool</code>, such that this interface
+ * is not strictly necessary as a visitor.
+ *
+ * @author Eric Lafortune
+ */
+public interface ClassPoolVisitor
+{
+ public void visitClassPool(ClassPool classPool);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPresenceFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPresenceFilter.java
new file mode 100644
index 0000000000..115b37ba9c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPresenceFilter.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to one of two
+ * <code>ClassVisitor</code> instances, depending on whether the name of
+ * the visited class file is present in a given <code>ClassPool</code> or not.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassPresenceFilter implements ClassVisitor
+{
+ private final ClassPool classPool;
+ private final ClassVisitor presentClassVisitor;
+ private final ClassVisitor missingClassVisitor;
+
+
+ /**
+ * Creates a new ClassPresenceFilter.
+ * @param classPool the <code>ClassPool</code> in which the
+ * presence will be tested.
+ * @param presentClassVisitor the <code>ClassVisitor</code> to which visits
+ * of present class files will be delegated.
+ * @param missingClassVisitor the <code>ClassVisitor</code> to which visits
+ * of missing class files will be delegated.
+ */
+ public ClassPresenceFilter(ClassPool classPool,
+ ClassVisitor presentClassVisitor,
+ ClassVisitor missingClassVisitor)
+ {
+ this.classPool = classPool;
+ this.presentClassVisitor = presentClassVisitor;
+ this.missingClassVisitor = missingClassVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ ClassVisitor classFileVisitor = classFileVisitor(programClass);
+
+ if (classFileVisitor != null)
+ {
+ classFileVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ ClassVisitor classFileVisitor = classFileVisitor(libraryClass);
+
+ if (classFileVisitor != null)
+ {
+ classFileVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the appropriate <code>ClassVisitor</code>.
+ */
+ private ClassVisitor classFileVisitor(Clazz clazz)
+ {
+ return classPool.getClass(clazz.getName()) != null ?
+ presentClassVisitor :
+ missingClassVisitor;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPrinter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPrinter.java
new file mode 100644
index 0000000000..c14a67d9a7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassPrinter.java
@@ -0,0 +1,1183 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.target.*;
+import proguard.classfile.attribute.annotation.target.visitor.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+
+import java.io.PrintStream;
+
+
+/**
+ * This <code>ClassVisitor</code> prints out the complete internal
+ * structure of the classes it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassPrinter
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor,
+ MemberVisitor,
+ AttributeVisitor,
+ BootstrapMethodInfoVisitor,
+ InnerClassesInfoVisitor,
+ ExceptionInfoVisitor,
+ StackMapFrameVisitor,
+ VerificationTypeVisitor,
+ LineNumberInfoVisitor,
+ ParameterInfoVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ TypeAnnotationVisitor,
+ TargetInfoVisitor,
+ LocalVariableTargetElementVisitor,
+ TypePathInfoVisitor,
+ ElementValueVisitor,
+ InstructionVisitor
+{
+ private static final String INDENTATION = " ";
+
+ private final PrintStream ps;
+
+ private int indentation;
+
+
+ /**
+ * Creates a new ClassPrinter that prints to <code>System.out</code>.
+ */
+ public ClassPrinter()
+ {
+ this(System.out);
+ }
+
+
+ /**
+ * Creates a new ClassPrinter that prints to the given
+ * <code>PrintStream</code>.
+ */
+ public ClassPrinter(PrintStream printStream)
+ {
+ ps = printStream;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ println("_____________________________________________________________________");
+ println(visitorInfo(programClass) + " " +
+ "Program class: " + programClass.getName());
+ indent();
+ println("Superclass: " + programClass.getSuperName());
+ println("Major version: 0x" + Integer.toHexString(ClassUtil.internalMajorClassVersion(programClass.u4version)));
+ println("Minor version: 0x" + Integer.toHexString(ClassUtil.internalMinorClassVersion(programClass.u4version)));
+ println(" = target " + ClassUtil.externalClassVersion(programClass.u4version));
+ println("Access flags: 0x" + Integer.toHexString(programClass.u2accessFlags));
+ println(" = " +
+ ((programClass.u2accessFlags & ClassConstants.ACC_ANNOTATTION) != 0 ? "@ " : "") +
+ ClassUtil.externalClassAccessFlags(programClass.u2accessFlags) +
+ ((programClass.u2accessFlags & ClassConstants.ACC_ENUM) != 0 ? "enum " :
+ (programClass.u2accessFlags & ClassConstants.ACC_INTERFACE) == 0 ? "class " :
+ "") +
+ ClassUtil.externalClassName(programClass.getName()) +
+ (programClass.u2superClass == 0 ? "" : " extends " +
+ ClassUtil.externalClassName(programClass.getSuperName())));
+ outdent();
+ println();
+
+ println("Interfaces (count = " + programClass.u2interfacesCount + "):");
+ indent();
+ programClass.interfaceConstantsAccept(this);
+ outdent();
+ println();
+
+ println("Constant Pool (count = " + programClass.u2constantPoolCount + "):");
+ indent();
+ programClass.constantPoolEntriesAccept(this);
+ outdent();
+ println();
+
+ println("Fields (count = " + programClass.u2fieldsCount + "):");
+ indent();
+ programClass.fieldsAccept(this);
+ outdent();
+ println();
+
+ println("Methods (count = " + programClass.u2methodsCount + "):");
+ indent();
+ programClass.methodsAccept(this);
+ outdent();
+ println();
+
+ println("Class file attributes (count = " + programClass.u2attributesCount + "):");
+ indent();
+ programClass.attributesAccept(this);
+ outdent();
+ println();
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ println("_____________________________________________________________________");
+ println(visitorInfo(libraryClass) + " " +
+ "Library class: " + libraryClass.getName());
+ indent();
+ println("Superclass: " + libraryClass.getSuperName());
+ println("Access flags: 0x" + Integer.toHexString(libraryClass.u2accessFlags));
+ println(" = " +
+ ((libraryClass.u2accessFlags & ClassConstants.ACC_ANNOTATTION) != 0 ? "@ " : "") +
+ ClassUtil.externalClassAccessFlags(libraryClass.u2accessFlags) +
+ ((libraryClass.u2accessFlags & ClassConstants.ACC_ENUM) != 0 ? "enum " :
+ (libraryClass.u2accessFlags & ClassConstants.ACC_INTERFACE) == 0 ? "class " :
+ "") +
+ ClassUtil.externalClassName(libraryClass.getName()) +
+ (libraryClass.getSuperName() == null ? "" : " extends " +
+ ClassUtil.externalClassName(libraryClass.getSuperName())));
+ outdent();
+ println();
+
+ println("Interfaces (count = " + libraryClass.interfaceClasses.length + "):");
+ for (int index = 0; index < libraryClass.interfaceClasses.length; index++)
+ {
+ Clazz interfaceClass = libraryClass.interfaceClasses[index];
+ if (interfaceClass != null)
+ {
+ println(" + " + interfaceClass.getName());
+ }
+ }
+
+ println("Fields (count = " + libraryClass.fields.length + "):");
+ libraryClass.fieldsAccept(this);
+
+ println("Methods (count = " + libraryClass.methods.length + "):");
+ libraryClass.methodsAccept(this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ println(visitorInfo(integerConstant) + " Integer [" +
+ integerConstant.getValue() + "]");
+ }
+
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ println(visitorInfo(longConstant) + " Long [" +
+ longConstant.getValue() + "]");
+ }
+
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ println(visitorInfo(floatConstant) + " Float [" +
+ floatConstant.getValue() + "]");
+ }
+
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ println(visitorInfo(doubleConstant) + " Double [" +
+ doubleConstant.getValue() + "]");
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ println(visitorInfo(stringConstant) + " String [" +
+ stringConstant.getString(clazz) + "]");
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ println(visitorInfo(utf8Constant) + " Utf8 [" +
+ utf8Constant.getString() + "]");
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ println(visitorInfo(invokeDynamicConstant) + " InvokeDynamic [bootstrap method index = " + invokeDynamicConstant.u2bootstrapMethodAttributeIndex + "]:");
+
+ indent();
+ clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this);
+ outdent();
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ println(visitorInfo(methodHandleConstant) + " MethodHandle [kind = " + methodHandleConstant.u1referenceKind + "]:");
+
+ indent();
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ outdent();
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ println(visitorInfo(fieldrefConstant) + " Fieldref [" +
+ clazz.getClassName(fieldrefConstant.u2classIndex) + "." +
+ clazz.getName(fieldrefConstant.u2nameAndTypeIndex) + " " +
+ clazz.getType(fieldrefConstant.u2nameAndTypeIndex) + "]");
+ }
+
+
+ public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
+ {
+ println(visitorInfo(interfaceMethodrefConstant) + " InterfaceMethodref [" +
+ clazz.getClassName(interfaceMethodrefConstant.u2classIndex) + "." +
+ clazz.getName(interfaceMethodrefConstant.u2nameAndTypeIndex) + " " +
+ clazz.getType(interfaceMethodrefConstant.u2nameAndTypeIndex) + "]");
+ }
+
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ println(visitorInfo(methodrefConstant) + " Methodref [" +
+ clazz.getClassName(methodrefConstant.u2classIndex) + "." +
+ clazz.getName(methodrefConstant.u2nameAndTypeIndex) + " " +
+ clazz.getType(methodrefConstant.u2nameAndTypeIndex) + "]");
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ println(visitorInfo(classConstant) + " Class [" +
+ classConstant.getName(clazz) + "]");
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ println(visitorInfo(methodTypeConstant) + " MethodType [" +
+ methodTypeConstant.getType(clazz) + "]");
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ println(visitorInfo(nameAndTypeConstant) + " NameAndType [" +
+ nameAndTypeConstant.getName(clazz) + " " +
+ nameAndTypeConstant.getType(clazz) + "]");
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ println(visitorInfo(programField) + " " +
+ "Field: " +
+ programField.getName(programClass) + " " +
+ programField.getDescriptor(programClass));
+
+ indent();
+ println("Access flags: 0x" + Integer.toHexString(programField.u2accessFlags));
+ println(" = " +
+ ClassUtil.externalFullFieldDescription(programField.u2accessFlags,
+ programField.getName(programClass),
+ programField.getDescriptor(programClass)));
+
+ visitMember(programClass, programField);
+ outdent();
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ println(visitorInfo(programMethod) + " " +
+ "Method: " +
+ programMethod.getName(programClass) +
+ programMethod.getDescriptor(programClass));
+
+ indent();
+ println("Access flags: 0x" + Integer.toHexString(programMethod.u2accessFlags));
+ println(" = " +
+ ClassUtil.externalFullMethodDescription(programClass.getName(),
+ programMethod.u2accessFlags,
+ programMethod.getName(programClass),
+ programMethod.getDescriptor(programClass)));
+
+ visitMember(programClass, programMethod);
+ outdent();
+ }
+
+
+ private void visitMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ if (programMember.u2attributesCount > 0)
+ {
+ println("Class member attributes (count = " + programMember.u2attributesCount + "):");
+ programMember.attributesAccept(programClass, this);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ println(visitorInfo(libraryField) + " " +
+ "Field: " +
+ libraryField.getName(libraryClass) + " " +
+ libraryField.getDescriptor(libraryClass));
+
+ indent();
+ println("Access flags: 0x" + Integer.toHexString(libraryField.u2accessFlags));
+ println(" = " +
+ ClassUtil.externalFullFieldDescription(libraryField.u2accessFlags,
+ libraryField.getName(libraryClass),
+ libraryField.getDescriptor(libraryClass)));
+ outdent();
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ println(visitorInfo(libraryMethod) + " " +
+ "Method: " +
+ libraryMethod.getName(libraryClass) + " " +
+ libraryMethod.getDescriptor(libraryClass));
+
+ indent();
+ println("Access flags: 0x" + Integer.toHexString(libraryMethod.u2accessFlags));
+ println(" = " +
+ ClassUtil.externalFullMethodDescription(libraryClass.getName(),
+ libraryMethod.u2accessFlags,
+ libraryMethod.getName(libraryClass),
+ libraryMethod.getDescriptor(libraryClass)));
+ outdent();
+ }
+
+
+ // Implementations for AttributeVisitor.
+ // Note that attributes are typically only referenced once, so we don't
+ // test if they are marked already.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ println(visitorInfo(unknownAttribute) +
+ " Unknown attribute (" + unknownAttribute.getAttributeName(clazz) + ")");
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ println(visitorInfo(bootstrapMethodsAttribute) +
+ " Bootstrap methods attribute (count = " + bootstrapMethodsAttribute.u2bootstrapMethodsCount + "):");
+
+ indent();
+ bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
+ outdent();
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ println(visitorInfo(sourceFileAttribute) +
+ " Source file attribute:");
+
+ indent();
+ clazz.constantPoolEntryAccept(sourceFileAttribute.u2sourceFileIndex, this);
+ outdent();
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ println(visitorInfo(sourceDirAttribute) +
+ " Source dir attribute:");
+
+ indent();
+ clazz.constantPoolEntryAccept(sourceDirAttribute.u2sourceDirIndex, this);
+ outdent();
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ println(visitorInfo(innerClassesAttribute) +
+ " Inner classes attribute (count = " + innerClassesAttribute.u2classesCount + ")");
+
+ indent();
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ outdent();
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ println(visitorInfo(enclosingMethodAttribute) +
+ " Enclosing method attribute:");
+
+ indent();
+ clazz.constantPoolEntryAccept(enclosingMethodAttribute.u2classIndex, this);
+
+ if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
+ {
+ clazz.constantPoolEntryAccept(enclosingMethodAttribute.u2nameAndTypeIndex, this);
+ }
+ outdent();
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ println(visitorInfo(deprecatedAttribute) +
+ " Deprecated attribute");
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ println(visitorInfo(syntheticAttribute) +
+ " Synthetic attribute");
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ println(visitorInfo(signatureAttribute) +
+ " Signature attribute:");
+
+ indent();
+ clazz.constantPoolEntryAccept(signatureAttribute.u2signatureIndex, this);
+ outdent();
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ println(visitorInfo(constantValueAttribute) +
+ " Constant value attribute:");
+
+ clazz.constantPoolEntryAccept(constantValueAttribute.u2constantValueIndex, this);
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ println(visitorInfo(methodParametersAttribute) +
+ " Method parameters attribute (count = " + methodParametersAttribute.u1parametersCount + ")");
+
+ indent();
+ methodParametersAttribute.parametersAccept(clazz, method, this);
+ outdent();
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ println(visitorInfo(exceptionsAttribute) +
+ " Exceptions attribute (count = " + exceptionsAttribute.u2exceptionIndexTableLength + ")");
+
+ indent();
+ exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this);
+ outdent();
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ println(visitorInfo(codeAttribute) +
+ " Code attribute instructions (code length = "+ codeAttribute.u4codeLength +
+ ", locals = "+ codeAttribute.u2maxLocals +
+ ", stack = "+ codeAttribute.u2maxStack + "):");
+
+ indent();
+
+ codeAttribute.instructionsAccept(clazz, method, this);
+
+ println("Code attribute exceptions (count = " +
+ codeAttribute.u2exceptionTableLength + "):");
+
+ codeAttribute.exceptionsAccept(clazz, method, this);
+
+ println("Code attribute attributes (attribute count = " +
+ codeAttribute.u2attributesCount + "):");
+
+ codeAttribute.attributesAccept(clazz, method, this);
+
+ outdent();
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ println(visitorInfo(codeAttribute) +
+ " Stack map attribute (count = "+
+ stackMapAttribute.u2stackMapFramesCount + "):");
+
+ indent();
+ stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ outdent();
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ println(visitorInfo(codeAttribute) +
+ " Stack map table attribute (count = "+
+ stackMapTableAttribute.u2stackMapFramesCount + "):");
+
+ indent();
+ stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ outdent();
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ println(visitorInfo(lineNumberTableAttribute) +
+ " Line number table attribute (count = " +
+ lineNumberTableAttribute.u2lineNumberTableLength + ")");
+
+ indent();
+ lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
+ outdent();
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ println(visitorInfo(localVariableTableAttribute) +
+ " Local variable table attribute (count = " +
+ localVariableTableAttribute.u2localVariableTableLength + ")");
+
+ indent();
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ outdent();
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ println(visitorInfo(localVariableTypeTableAttribute) +
+ " Local variable type table attribute (count = "+
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength + ")");
+
+ indent();
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ outdent();
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ println(visitorInfo(runtimeVisibleAnnotationsAttribute) +
+ " Runtime visible annotations attribute:");
+
+ indent();
+ runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, this);
+ outdent();
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ println(visitorInfo(runtimeInvisibleAnnotationsAttribute) +
+ " Runtime invisible annotations attribute:");
+
+ indent();
+ runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, this);
+ outdent();
+ }
+
+
+ public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
+ {
+ println(visitorInfo(runtimeVisibleParameterAnnotationsAttribute) +
+ " Runtime visible parameter annotations attribute (parameter count = " + runtimeVisibleParameterAnnotationsAttribute.u1parametersCount + "):");
+
+ indent();
+ runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ outdent();
+ }
+
+
+ public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
+ {
+ println(visitorInfo(runtimeInvisibleParameterAnnotationsAttribute) +
+ " Runtime invisible parameter annotations attribute (parameter count = " + runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount + "):");
+
+ indent();
+ runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ outdent();
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ println(visitorInfo(runtimeVisibleTypeAnnotationsAttribute) +
+ " Runtime visible type annotations attribute");
+
+ indent();
+ runtimeVisibleTypeAnnotationsAttribute.typeAnnotationsAccept(clazz, this);
+ outdent();
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ println(visitorInfo(runtimeInvisibleTypeAnnotationsAttribute) +
+ " Runtime invisible type annotations attribute");
+
+ indent();
+ runtimeInvisibleTypeAnnotationsAttribute.typeAnnotationsAccept(clazz, this);
+ outdent();
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ println(visitorInfo(annotationDefaultAttribute) +
+ " Annotation default attribute:");
+
+ indent();
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ outdent();
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ println(visitorInfo(bootstrapMethodInfo) +
+ " BootstrapMethodInfo (argument count = " +
+ bootstrapMethodInfo.u2methodArgumentCount+ "):");
+
+ indent();
+ clazz.constantPoolEntryAccept(bootstrapMethodInfo.u2methodHandleIndex, this);
+ bootstrapMethodInfo.methodArgumentsAccept(clazz, this);
+ outdent();
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ println(visitorInfo(innerClassesInfo) +
+ " InnerClassesInfo:");
+
+ indent();
+ println("Access flags: 0x" + Integer.toHexString(innerClassesInfo.u2innerClassAccessFlags) + " = " +
+ ClassUtil.externalClassAccessFlags(innerClassesInfo.u2innerClassAccessFlags));
+ innerClassesInfo.innerClassConstantAccept(clazz, this);
+ innerClassesInfo.outerClassConstantAccept(clazz, this);
+ innerClassesInfo.innerNameConstantAccept(clazz, this);
+ outdent();
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ println(instruction.toString(offset));
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ println(constantInstruction.toString(offset));
+
+ indent();
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ outdent();
+ }
+
+
+ public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
+ {
+ println(tableSwitchInstruction.toString(offset));
+
+ indent();
+
+ int[] jumpOffsets = tableSwitchInstruction.jumpOffsets;
+
+ for (int index = 0; index < jumpOffsets.length; index++)
+ {
+ int jumpOffset = jumpOffsets[index];
+ println(Integer.toString(tableSwitchInstruction.lowCase + index) + ": offset = " + jumpOffset + ", target = " + (offset + jumpOffset));
+ }
+
+ int defaultOffset = tableSwitchInstruction.defaultOffset;
+ println("default: offset = " + defaultOffset + ", target = "+ (offset + defaultOffset));
+
+ outdent();
+ }
+
+
+ public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
+ {
+ println(lookUpSwitchInstruction.toString(offset));
+
+ indent();
+
+ int[] cases = lookUpSwitchInstruction.cases;
+ int[] jumpOffsets = lookUpSwitchInstruction.jumpOffsets;
+
+ for (int index = 0; index < jumpOffsets.length; index++)
+ {
+ int jumpOffset = jumpOffsets[index];
+ println(Integer.toString(cases[index]) + ": offset = " + jumpOffset + ", target = " + (offset + jumpOffset));
+ }
+
+ int defaultOffset = lookUpSwitchInstruction.defaultOffset;
+ println("default: offset = " + defaultOffset + ", target = "+ (offset + defaultOffset));
+
+ outdent();
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ println(visitorInfo(exceptionInfo) +
+ " ExceptionInfo (" +
+ exceptionInfo.u2startPC + " -> " +
+ exceptionInfo.u2endPC + ": " +
+ exceptionInfo.u2handlerPC + "):");
+
+ if (exceptionInfo.u2catchType != 0)
+ {
+ clazz.constantPoolEntryAccept(exceptionInfo.u2catchType, this);
+ }
+ }
+
+
+ // Implementations for StackMapFrameVisitor.
+
+ public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame)
+ {
+ println(visitorInfo(sameZeroFrame) +
+ " [" + offset + "]" +
+ " Var: ..., Stack: (empty)");
+ }
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ print(visitorInfo(sameOneFrame) +
+ " [" + offset + "]" +
+ " Var: ..., Stack: ");
+
+ sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
+
+ println();
+ }
+
+
+ public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame)
+ {
+ println(visitorInfo(lessZeroFrame) +
+ " [" + offset + "]" +
+ " Var: -" + lessZeroFrame.choppedVariablesCount +
+ ", Stack: (empty)");
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ print(visitorInfo(moreZeroFrame) +
+ " [" + offset + "]" +
+ " Var: ...");
+
+ moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
+
+ ps.println(", Stack: (empty)");
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ print(visitorInfo(fullFrame) +
+ " [" + offset + "]" +
+ " Var: ");
+
+ fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
+
+ ps.print(", Stack: ");
+
+ fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
+
+ println();
+ }
+
+
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitIntegerType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, IntegerType integerType)
+ {
+ ps.print("[i]");
+ }
+
+
+ public void visitFloatType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FloatType floatType)
+ {
+ ps.print("[f]");
+ }
+
+
+ public void visitLongType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LongType longType)
+ {
+ ps.print("[l]");
+ }
+
+
+ public void visitDoubleType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, DoubleType doubleType)
+ {
+ ps.print("[d]");
+ }
+
+
+ public void visitTopType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TopType topType)
+ {
+ ps.print("[T]");
+ }
+
+
+ public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
+ {
+ ps.print("[a:" + clazz.getClassName(objectType.u2classIndex) + "]");
+ }
+
+
+ public void visitNullType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, NullType nullType)
+ {
+ ps.print("[n]");
+ }
+
+
+ public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
+ {
+ ps.print("[u:" + uninitializedType.u2newInstructionOffset + "]");
+ }
+
+
+ public void visitUninitializedThisType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedThisType uninitializedThisType)
+ {
+ ps.print("[u:this]");
+ }
+
+
+ // Implementations for LineNumberInfoVisitor.
+
+ public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
+ {
+ println("[" + lineNumberInfo.u2startPC + "] -> line " +
+ lineNumberInfo.u2lineNumber +
+ (lineNumberInfo.getSource() == null ? "" : " [" + lineNumberInfo.getSource() + "]"));
+ }
+
+
+ // Implementations for ParameterInfoVisitor.
+
+ public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
+ {
+ println("p" + parameterIndex + ": access flags: 0x" + Integer.toHexString(parameterInfo.u2accessFlags) + " = " +
+ ClassUtil.externalParameterAccessFlags(parameterInfo.u2accessFlags) +
+ (parameterInfo.u2nameIndex == 0 ? "" : " [" + parameterInfo.getName(clazz) + "]"));
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ println("v" + localVariableInfo.u2index + ": " +
+ localVariableInfo.u2startPC + " -> " +
+ (localVariableInfo.u2startPC + localVariableInfo.u2length) + " [" +
+ localVariableInfo.getDescriptor(clazz) + " " +
+ localVariableInfo.getName(clazz) + "]");
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ println("v" + localVariableTypeInfo.u2index + ": " +
+ localVariableTypeInfo.u2startPC + " -> " +
+ (localVariableTypeInfo.u2startPC + localVariableTypeInfo.u2length) + " [" +
+ localVariableTypeInfo.getSignature(clazz) + " " +
+ localVariableTypeInfo.getName(clazz) + "]");
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ println(visitorInfo(annotation) +
+ " Annotation [" + annotation.getType(clazz) + "]:");
+
+ indent();
+ annotation.elementValuesAccept(clazz, this);
+ outdent();
+ }
+
+
+ // Implementations for TypeAnnotationVisitor.
+
+ public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)
+ {
+ println(visitorInfo(typeAnnotation) +
+ " Type annotation [" + typeAnnotation.getType(clazz) + "]:");
+
+ indent();
+ typeAnnotation.targetInfoAccept(clazz, this);
+
+ println("Type path (count = " + typeAnnotation.typePath.length + "):");
+ indent();
+ typeAnnotation.typePathInfosAccept(clazz, this);
+ outdent();
+
+ typeAnnotation.elementValuesAccept(clazz, this);
+
+ outdent();
+ }
+
+
+ // Implementations for TargetInfoVisitor.
+
+ public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo)
+ {
+ println("Target (type = 0x" + Integer.toHexString(typeParameterTargetInfo.u1targetType) + "): Parameter #" +
+ typeParameterTargetInfo.u1typeParameterIndex);
+ }
+
+
+ public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo)
+ {
+ println("Target (type = 0x" + Integer.toHexString(superTypeTargetInfo.u1targetType) + "): " +
+ (superTypeTargetInfo.u2superTypeIndex == 0xffff ?
+ "super class" :
+ "interface #" + superTypeTargetInfo.u2superTypeIndex));
+ }
+
+
+ public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)
+ {
+ println("Target (type = 0x" + Integer.toHexString(typeParameterBoundTargetInfo.u1targetType) + "): parameter #" +
+ typeParameterBoundTargetInfo.u1typeParameterIndex + ", bound #" + typeParameterBoundTargetInfo.u1boundIndex);
+ }
+
+
+ public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo)
+ {
+ println("Target (type = 0x" + Integer.toHexString(emptyTargetInfo.u1targetType) + ")");
+ }
+
+
+ public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo)
+ {
+ println("Target (type = 0x" + Integer.toHexString(formalParameterTargetInfo.u1targetType) + "): formal parameter #" +
+ formalParameterTargetInfo.u1formalParameterIndex);
+ }
+
+
+ public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo)
+ {
+ println("Target (type = 0x" + Integer.toHexString(throwsTargetInfo.u1targetType) + "): throws #" +
+ throwsTargetInfo.u2throwsTypeIndex);
+ }
+
+
+ public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)
+ {
+ println("Target (type = 0x" + Integer.toHexString(localVariableTargetInfo.u1targetType) + "): local variables (count = " +
+ localVariableTargetInfo.u2tableLength + ")");
+
+ indent();
+ localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this);
+ outdent();
+ }
+
+
+ public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo)
+ {
+ println("Target (type = 0x" + Integer.toHexString(catchTargetInfo.u1targetType) + "): catch #" +
+ catchTargetInfo.u2exceptionTableIndex);
+ }
+
+
+ public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo)
+ {
+ println("Target (type = 0x" + Integer.toHexString(offsetTargetInfo.u1targetType) + "): offset " +
+ offsetTargetInfo.u2offset);
+ }
+
+
+ public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo)
+ {
+ println("Target (type = 0x" + Integer.toHexString(typeArgumentTargetInfo.u1targetType) + "): offset " +
+ typeArgumentTargetInfo.u2offset + ", type argument " +
+ typeArgumentTargetInfo.u1typeArgumentIndex);
+ }
+
+
+ // Implementations for TypePathInfoVisitor.
+
+ public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)
+ {
+ println("kind = " +
+ typePathInfo.u1typePathKind + ", argument index = " +
+ typePathInfo.u1typeArgumentIndex);
+ }
+
+
+ // Implementations for LocalVariableTargetElementVisitor.
+
+ public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)
+ {
+ println("v" +
+ localVariableTargetElement.u2index + ": " +
+ localVariableTargetElement.u2startPC + " -> " +
+ (localVariableTargetElement.u2startPC + localVariableTargetElement.u2length));
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ println(visitorInfo(constantElementValue) +
+ " Constant element value [" +
+ (constantElementValue.u2elementNameIndex == 0 ? "(default)" :
+ constantElementValue.getMethodName(clazz)) + " '" +
+ constantElementValue.u1tag + "']");
+
+ indent();
+ clazz.constantPoolEntryAccept(constantElementValue.u2constantValueIndex, this);
+ outdent();
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ println(visitorInfo(enumConstantElementValue) +
+ " Enum constant element value [" +
+ (enumConstantElementValue.u2elementNameIndex == 0 ? "(default)" :
+ enumConstantElementValue.getMethodName(clazz)) + ", " +
+ enumConstantElementValue.getTypeName(clazz) + ", " +
+ enumConstantElementValue.getConstantName(clazz) + "]");
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ println(visitorInfo(classElementValue) +
+ " Class element value [" +
+ (classElementValue.u2elementNameIndex == 0 ? "(default)" :
+ classElementValue.getMethodName(clazz)) + ", " +
+ classElementValue.getClassName(clazz) + "]");
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ println(visitorInfo(annotationElementValue) +
+ " Annotation element value [" +
+ (annotationElementValue.u2elementNameIndex == 0 ? "(default)" :
+ annotationElementValue.getMethodName(clazz)) + "]:");
+
+ indent();
+ annotationElementValue.annotationAccept(clazz, this);
+ outdent();
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ println(visitorInfo(arrayElementValue) +
+ " Array element value [" +
+ (arrayElementValue.u2elementNameIndex == 0 ? "(default)" :
+ arrayElementValue.getMethodName(clazz)) + "]:");
+
+ indent();
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ outdent();
+ }
+
+
+ // Small utility methods.
+
+ private void indent()
+ {
+ indentation++;
+ }
+
+ private void outdent()
+ {
+ indentation--;
+ }
+
+ private void println(String string)
+ {
+ print(string);
+ println();
+
+ }
+
+ private void print(String string)
+ {
+ for (int index = 0; index < indentation; index++)
+ {
+ ps.print(INDENTATION);
+ }
+
+ ps.print(string);
+ }
+
+ private void println()
+ {
+ ps.println();
+ }
+
+
+ private String visitorInfo(VisitorAccepter visitorAccepter)
+ {
+ return visitorAccepter.getVisitorInfo() == null ? "-" : "+";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVersionFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVersionFilter.java
new file mode 100644
index 0000000000..50c496172c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVersionFilter.java
@@ -0,0 +1,85 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to program classes to
+ * another given <code>ClassVisitor</code>, but only when the class version
+ * number of the visited program class lies in a given range.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassVersionFilter implements ClassVisitor
+{
+ private final int minimumClassVersion;
+ private final int maximumClassVersion;
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ClassVersionFilter.
+ * @param minimumClassVersion the minimum class version number.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ClassVersionFilter(int minimumClassVersion,
+ ClassVisitor classVisitor)
+ {
+ this(minimumClassVersion, Integer.MAX_VALUE, classVisitor);
+ }
+
+
+ /**
+ * Creates a new ClassVersionFilter.
+ * @param minimumClassVersion the minimum class version number.
+ * @param maximumClassVersion the maximum class version number.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ClassVersionFilter(int minimumClassVersion,
+ int maximumClassVersion,
+ ClassVisitor classVisitor)
+ {
+ this.minimumClassVersion = minimumClassVersion;
+ this.maximumClassVersion = maximumClassVersion;
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (programClass.u4version >= minimumClassVersion &&
+ programClass.u4version <= maximumClassVersion)
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Library classes don't have version numbers.
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVersionSetter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVersionSetter.java
new file mode 100644
index 0000000000..12e1c59eaf
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVersionSetter.java
@@ -0,0 +1,83 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+import java.util.Set;
+
+/**
+ * This <code>ClassVisitor</code> sets the version number of the program classes
+ * that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassVersionSetter implements ClassVisitor
+{
+ private final int classVersion;
+
+ private final Set newerClassVersions;
+
+
+ /**
+ * Creates a new ClassVersionSetter.
+ * @param classVersion the class version number.
+ */
+ public ClassVersionSetter(int classVersion)
+ {
+ this(classVersion, null);
+ }
+
+
+ /**
+ * Creates a new ClassVersionSetter that also stores any newer class version
+ * numbers that it encounters while visiting program classes.
+ * @param classVersion the class version number.
+ * @param newerClassVersions the <code>Set</code> in which newer class
+ * version numbers can be collected.
+ */
+ public ClassVersionSetter(int classVersion,
+ Set newerClassVersions)
+ {
+ this.classVersion = classVersion;
+ this.newerClassVersions = newerClassVersions;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (programClass.u4version > classVersion &&
+ newerClassVersions != null)
+ {
+ newerClassVersions.add(new Integer(programClass.u4version));
+ }
+
+ programClass.u4version = classVersion;
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Library classes don't have version numbers.
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVisitor.java
new file mode 100644
index 0000000000..6358b3b50a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ClassVisitor.java
@@ -0,0 +1,36 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>Clazz</code> objects.
+ *
+ * @author Eric Lafortune
+ */
+public interface ClassVisitor
+{
+ public void visitProgramClass(ProgramClass programClass);
+ public void visitLibraryClass(LibraryClass libraryClass);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java
new file mode 100644
index 0000000000..1169d8d291
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java
@@ -0,0 +1,100 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This <code>ClassVisitor</code> lets a given <code>ClassVisitor</code>
+ * travel to the first concrete subclasses down in its hierarchy of abstract
+ * classes and concrete classes.
+ *
+ * @author Eric Lafortune
+ */
+public class ConcreteClassDownTraveler
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ConcreteClassDownTraveler.
+ * @param classVisitor the <code>ClassVisitor</code> to
+ * which visits will be delegated.
+ */
+ public ConcreteClassDownTraveler(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Is this an abstract class or an interface?
+ if ((programClass.getAccessFlags() &
+ (ClassConstants.ACC_INTERFACE |
+ ClassConstants.ACC_ABSTRACT)) != 0)
+ {
+ // Travel down the hierarchy.
+ Clazz[] subClasses = programClass.subClasses;
+ if (subClasses != null)
+ {
+ for (int index = 0; index < subClasses.length; index++)
+ {
+ subClasses[index].accept(this);
+ }
+ }
+ }
+ else
+ {
+ // Visit the class. Don't descend any further.
+ programClass.accept(classVisitor);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Is this an abstract class or interface?
+ if ((libraryClass.getAccessFlags() &
+ (ClassConstants.ACC_INTERFACE |
+ ClassConstants.ACC_ABSTRACT)) != 0)
+ {
+ // Travel down the hierarchy.
+ Clazz[] subClasses = libraryClass.subClasses;
+ if (subClasses != null)
+ {
+ for (int index = 0; index < subClasses.length; index++)
+ {
+ subClasses[index].accept(this);
+ }
+ }
+ }
+ else
+ {
+ // Visit the class. Don't descend any further.
+ libraryClass.accept(classVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/DotClassClassVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/DotClassClassVisitor.java
new file mode 100644
index 0000000000..d861d33265
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/DotClassClassVisitor.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+
+/**
+ * This InstructionVisitor lets a given <code>ClassVisitor</code> visit all
+ * classes involved in any <code>.class</code> constructs that it visits.
+ * <p>
+ * Note that before JDK 1.5, <code>.class</code> constructs are actually
+ * compiled differently, using <code>Class.forName</code> constructs.
+ *
+ * @author Eric Lafortune
+ */
+public class DotClassClassVisitor
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ClassHierarchyTraveler.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits will
+ * be delegated.
+ */
+ public DotClassClassVisitor(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ byte opcode = constantInstruction.opcode;
+
+ // Could this instruction be a .class construct?
+ if (opcode == InstructionConstants.OP_LDC ||
+ opcode == InstructionConstants.OP_LDC_W)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ this);
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Visit the referenced class from the .class construct.
+ classConstant.referencedClassAccept(classVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/DynamicReturnedClassVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/DynamicReturnedClassVisitor.java
new file mode 100644
index 0000000000..8a23b02fe3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/DynamicReturnedClassVisitor.java
@@ -0,0 +1,68 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+
+/**
+ * This ConstantVisitor lets a given ClassVisitor visit all the referenced
+ * classes that are returned by the invoke dynamic constants that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class DynamicReturnedClassVisitor
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ protected final ClassVisitor classVisitor;
+
+
+ public DynamicReturnedClassVisitor(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Is the method returning a class type?
+ Clazz[] referencedClasses = invokeDynamicConstant.referencedClasses;
+ if (referencedClasses != null &&
+ referencedClasses.length > 0 &&
+ ClassUtil.isInternalClassType(ClassUtil.internalMethodReturnType(invokeDynamicConstant.getType(clazz))))
+ {
+ // Let the visitor visit the return type class, if any.
+ Clazz referencedClass = referencedClasses[referencedClasses.length - 1];
+ if (referencedClass != null)
+ {
+ referencedClass.accept(classVisitor);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptClassFilter.java
new file mode 100644
index 0000000000..9182a6f09d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptClassFilter.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to another given
+ * <code>ClassVisitor</code>, except for one given class.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptClassFilter implements ClassVisitor
+{
+ private final Clazz exceptClass;
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ClassNameFilter.
+ * @param exceptClass the class that will not be visited.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits will
+ * be delegated.
+ */
+ public ExceptClassFilter(Clazz exceptClass,
+ ClassVisitor classVisitor)
+ {
+ this.exceptClass = exceptClass;
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (!programClass.equals(exceptClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (!libraryClass.equals(exceptClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptClassesFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptClassesFilter.java
new file mode 100644
index 0000000000..35cf7c3e9b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptClassesFilter.java
@@ -0,0 +1,90 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to another given
+ * <code>ClassVisitor</code>, except for classes are in a given list.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptClassesFilter implements ClassVisitor
+{
+ private final Clazz[] exceptClasses;
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ExceptClassesFilter.
+ * @param exceptClasses the classes that will not be visited.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits will
+ * be delegated.
+ */
+ public ExceptClassesFilter(Clazz[] exceptClasses,
+ ClassVisitor classVisitor)
+ {
+ this.exceptClasses = exceptClasses;
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (!present(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (!present(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean present(Clazz clazz)
+ {
+ if (exceptClasses == null)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < exceptClasses.length; index++)
+ {
+ if (exceptClasses[index].equals(clazz))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionCounter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionCounter.java
new file mode 100644
index 0000000000..9a28816aea
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionCounter.java
@@ -0,0 +1,52 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.ExceptionInfoVisitor;
+
+/**
+ * This ExceptionInfoVisitor counts the number of exceptions that has been visited.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionCounter implements ExceptionInfoVisitor
+{
+ private int count;
+
+
+ /**
+ * Returns the number of exceptions that has been visited so far.
+ */
+ public int getCount()
+ {
+ return count;
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ count++;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java
new file mode 100644
index 0000000000..9f1ed68c18
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java
@@ -0,0 +1,64 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.ExceptionInfoVisitor;
+
+/**
+ * This <code>ExceptionInfoVisitor</code> delegates its visits to another given
+ * <code>ExceptionInfoVisitor</code>, but only when the visited exception
+ * does not cover the instruction at the given offset.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionExcludedOffsetFilter
+implements ExceptionInfoVisitor
+{
+ private final int instructionOffset;
+ private final ExceptionInfoVisitor exceptionInfoVisitor;
+
+
+ /**
+ * Creates a new ExceptionExcludedOffsetFilter.
+ * @param instructionOffset the instruction offset.
+ * @param exceptionInfoVisitor the ExceptionInfoVisitor to which visits
+ * will be delegated.
+ */
+ public ExceptionExcludedOffsetFilter(int instructionOffset,
+ ExceptionInfoVisitor exceptionInfoVisitor)
+ {
+ this.instructionOffset = instructionOffset;
+ this.exceptionInfoVisitor = exceptionInfoVisitor;
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ if (!exceptionInfo.isApplicable(instructionOffset))
+ {
+ exceptionInfoVisitor.visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java
new file mode 100644
index 0000000000..956b821b00
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionHandlerConstantVisitor.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.ExceptionInfoVisitor;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+
+/**
+ * This <code>ExceptionInfoVisitor</code> lets a given
+ * <code>ConstantVisitor</code> visit all catch class constants of exceptions
+ * that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionHandlerConstantVisitor
+implements ExceptionInfoVisitor
+{
+ private final ConstantVisitor constantVisitor;
+
+
+ /**
+ * Creates a new ExceptionHandlerConstantVisitor.
+ * @param constantVisitor the ConstantVisitor that will visit the catch
+ * class constants.
+ */
+ public ExceptionHandlerConstantVisitor(ConstantVisitor constantVisitor)
+ {
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ int catchType = exceptionInfo.u2catchType;
+ if (catchType != 0)
+ {
+ clazz.constantPoolEntryAccept(catchType, constantVisitor);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionHandlerFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionHandlerFilter.java
new file mode 100644
index 0000000000..87cd2ad602
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionHandlerFilter.java
@@ -0,0 +1,70 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.ExceptionInfoVisitor;
+
+/**
+ * This <code>ExceptionInfoVisitor</code> delegates its visits to another given
+ * <code>ExceptionInfoVisitor</code>, but only when the visited exception
+ * targets an instruction in the given range of offsets.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionHandlerFilter
+implements ExceptionInfoVisitor
+{
+ private final int startOffset;
+ private final int endOffset;
+ private final ExceptionInfoVisitor exceptionInfoVisitor;
+
+
+ /**
+ * Creates a new ExceptionHandlerFilter.
+ * @param startOffset the start of the instruction offset range.
+ * @param endOffset the end of the instruction offset range.
+ * @param exceptionInfoVisitor the ExceptionInfoVisitor to which visits
+ * will be delegated.
+ */
+ public ExceptionHandlerFilter(int startOffset,
+ int endOffset,
+ ExceptionInfoVisitor exceptionInfoVisitor)
+ {
+ this.startOffset = startOffset;
+ this.endOffset = endOffset;
+ this.exceptionInfoVisitor = exceptionInfoVisitor;
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ int handlerPC = exceptionInfo.u2handlerPC;
+ if (handlerPC >= startOffset &&
+ handlerPC < endOffset)
+ {
+ exceptionInfoVisitor.visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionOffsetFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
new file mode 100644
index 0000000000..d4865f2560
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
@@ -0,0 +1,64 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.ExceptionInfoVisitor;
+
+/**
+ * This <code>ExceptionInfoVisitor</code> delegates its visits to another given
+ * <code>ExceptionInfoVisitor</code>, but only when the visited exception
+ * covers the instruction at the given offset.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionOffsetFilter
+implements ExceptionInfoVisitor
+{
+ private final int instructionOffset;
+ private final ExceptionInfoVisitor exceptionInfoVisitor;
+
+
+ /**
+ * Creates a new ExceptionOffsetFilter.
+ * @param instructionOffset the instruction offset.
+ * @param exceptionInfoVisitor the ExceptionInfoVisitor to which visits
+ * will be delegated.
+ */
+ public ExceptionOffsetFilter(int instructionOffset,
+ ExceptionInfoVisitor exceptionInfoVisitor)
+ {
+ this.instructionOffset = instructionOffset;
+ this.exceptionInfoVisitor = exceptionInfoVisitor;
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ if (exceptionInfo.isApplicable(instructionOffset))
+ {
+ exceptionInfoVisitor.visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionRangeFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionRangeFilter.java
new file mode 100644
index 0000000000..f2e31b6cf4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ExceptionRangeFilter.java
@@ -0,0 +1,68 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.ExceptionInfoVisitor;
+
+/**
+ * This <code>ExceptionInfoVisitor</code> delegates its visits to another given
+ * <code>ExceptionInfoVisitor</code>, but only when the visited exception
+ * overlaps with the given instruction range.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionRangeFilter
+implements ExceptionInfoVisitor
+{
+ private final int startOffset;
+ private final int endOffset;
+ private final ExceptionInfoVisitor exceptionInfoVisitor;
+
+
+ /**
+ * Creates a new ExceptionRangeFilter.
+ * @param startOffset the start offset of the instruction range.
+ * @param endOffset the end offset of the instruction range.
+ * @param exceptionInfoVisitor the ExceptionInfoVisitor to which visits
+ * will be delegated.
+ */
+ public ExceptionRangeFilter(int startOffset,
+ int endOffset,
+ ExceptionInfoVisitor exceptionInfoVisitor)
+ {
+ this.startOffset = startOffset;
+ this.endOffset = endOffset;
+ this.exceptionInfoVisitor = exceptionInfoVisitor;
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ if (exceptionInfo.isApplicable(startOffset, endOffset))
+ {
+ exceptionInfoVisitor.visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java
new file mode 100644
index 0000000000..b9fd44be9e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This <code>ConstantVisitor</code> delegates its visits to class constants
+ * to another given <code>ConstantVisitor</code>, except for classes that
+ * extend or implement a given class. This exception includes the class itself.
+ *
+ * @author Eric Lafortune
+ */
+public class ImplementedClassConstantFilter
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final Clazz implementedClass;
+ private final ConstantVisitor constantVisitor;
+
+
+ /**
+ * Creates a new ImplementedClassConstantFilter.
+ * @param implementedClass the class whose implementations will not be
+ * visited.
+ * @param constantVisitor the <code>ConstantVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ImplementedClassConstantFilter(Clazz implementedClass,
+ ConstantVisitor constantVisitor)
+ {
+ this.implementedClass = implementedClass;
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ Clazz referencedClass = classConstant.referencedClass;
+ if (referencedClass == null ||
+ !referencedClass.extendsOrImplements(implementedClass))
+ {
+ constantVisitor.visitClassConstant(clazz, classConstant);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementedClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementedClassFilter.java
new file mode 100644
index 0000000000..74cbdf4af8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementedClassFilter.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to another given
+ * <code>ClassVisitor</code>, except for classes that extend or implement
+ * a given class.
+ *
+ * @author Eric Lafortune
+ */
+public class ImplementedClassFilter implements ClassVisitor
+{
+ private final Clazz implementedClass;
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ImplementedClassFilter.
+ * @param implementedClass the class whose implementations will not be
+ * visited.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits will
+ * be delegated.
+ */
+ public ImplementedClassFilter(Clazz implementedClass,
+ ClassVisitor classVisitor)
+ {
+ this.implementedClass = implementedClass;
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (!programClass.extendsOrImplements(implementedClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (!libraryClass.extendsOrImplements(implementedClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java
new file mode 100644
index 0000000000..471053da54
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java
@@ -0,0 +1,70 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This <code>ConstantVisitor</code> delegates its visits to class constants
+ * to another given <code>ConstantVisitor</code>, except for classes that
+ * are extended or implemented by a given class. This exception includes the
+ * class itself.
+ *
+ * @author Eric Lafortune
+ */
+public class ImplementingClassConstantFilter
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ private final Clazz implementingClass;
+ private final ConstantVisitor constantVisitor;
+
+
+ /**
+ * Creates a new ImplementingClassConstantFilter.
+ * @param implementingClass the class whose superclasses and interfaces will
+ * not be visited.
+ * @param constantVisitor the <code>ConstantVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ImplementingClassConstantFilter(Clazz implementingClass,
+ ConstantVisitor constantVisitor)
+ {
+ this.implementingClass = implementingClass;
+ this.constantVisitor = constantVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ Clazz referencedClass = classConstant.referencedClass;
+ if (referencedClass == null ||
+ !implementingClass.extendsOrImplements(referencedClass))
+ {
+ constantVisitor.visitClassConstant(clazz, classConstant);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/InitializerMethodFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/InitializerMethodFilter.java
new file mode 100644
index 0000000000..87f363fc6d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/InitializerMethodFilter.java
@@ -0,0 +1,108 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+
+/**
+ * This MemberVisitor delegates its visits to one of two other given
+ * MemberVisitor instances, depending on whether the visited method
+ * is a static initializer or instance initializer, or not.
+ *
+ * @author Eric Lafortune
+ */
+public class InitializerMethodFilter
+implements MemberVisitor
+{
+ private final MemberVisitor initializerMemberVisitor;
+ private final MemberVisitor otherMemberVisitor;
+
+
+ /**
+ * Creates a new InitializerMethodFilter.
+ * @param initializerMemberVisitor the member visitor to which visits to
+ * initializers will be delegated.
+ */
+ public InitializerMethodFilter(MemberVisitor initializerMemberVisitor)
+ {
+ this(initializerMemberVisitor, null);
+ }
+
+
+ /**
+ * Creates a new InitializerMethodFilter.
+ * @param initializerMemberVisitor the member visitor to which visits to
+ * initializers will be delegated.
+ * @param otherMemberVisitor the member visitor to which visits to
+ * non-initializer methods will be delegated.
+ */
+ public InitializerMethodFilter(MemberVisitor initializerMemberVisitor,
+ MemberVisitor otherMemberVisitor)
+ {
+ this.initializerMemberVisitor = initializerMemberVisitor;
+ this.otherMemberVisitor = otherMemberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField) {}
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ MemberVisitor memberVisitor =
+ applicableMemberVisitor(programClass, programMethod);
+
+ if (memberVisitor != null)
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ MemberVisitor memberVisitor =
+ applicableMemberVisitor(libraryClass, libraryMethod);
+
+ if (memberVisitor != null)
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the appropriate member visitor, depending on whether the
+ * given method is an initializer or not.
+ */
+ private MemberVisitor applicableMemberVisitor(Clazz clazz, Member method)
+ {
+ return ClassUtil.isInitializer(method.getName(clazz)) ?
+ initializerMemberVisitor :
+ otherMemberVisitor;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/LibraryClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/LibraryClassFilter.java
new file mode 100644
index 0000000000..f009206594
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/LibraryClassFilter.java
@@ -0,0 +1,60 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to another given
+ * <code>ClassVisitor</code>, but only when visiting library classes.
+ *
+ * @author Eric Lafortune
+ */
+public class LibraryClassFilter implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new LibraryClassFilter.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits
+ * will be delegated.
+ */
+ public LibraryClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Don't delegate visits to program classes.
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/LibraryMemberFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/LibraryMemberFilter.java
new file mode 100644
index 0000000000..739e262185
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/LibraryMemberFilter.java
@@ -0,0 +1,73 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to another given
+ * <code>MemberVisitor</code>, but only when visiting members of library
+ * classes.
+ *
+ * @author Eric Lafortune
+ */
+public class LibraryMemberFilter implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new ProgramMemberFilter.
+ * @param memberVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public LibraryMemberFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Don't delegate visits to program members.
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Don't delegate visits to program members.
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberAccessFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberAccessFilter.java
new file mode 100644
index 0000000000..4b049dfb97
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberAccessFilter.java
@@ -0,0 +1,122 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to another given
+ * <code>MemberVisitor</code>, but only when the visited member has the proper
+ * access flags.
+ * <p>
+ * If conflicting access flags (public/private/protected) are specified,
+ * having one of them set will be considered sufficient.
+ *
+ * @see ClassConstants
+ *
+ * @author Eric Lafortune
+ */
+public class MemberAccessFilter
+implements MemberVisitor
+{
+ // A mask of conflicting access flags. These are interpreted in a special
+ // way if more of them are required at the same time. In that case, one
+ // of them being set is sufficient.
+ private static final int ACCESS_MASK =
+ ClassConstants.ACC_PUBLIC |
+ ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_PROTECTED;
+
+ private final int requiredSetAccessFlags;
+ private final int requiredUnsetAccessFlags;
+ private final int requiredOneSetAccessFlags;
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new MemberAccessFilter.
+ * @param requiredSetAccessFlags the class access flags that should be
+ * set.
+ * @param requiredUnsetAccessFlags the class access flags that should be
+ * unset.
+ * @param memberVisitor the <code>MemberVisitor</code> to
+ * which visits will be delegated.
+ */
+ public MemberAccessFilter(int requiredSetAccessFlags,
+ int requiredUnsetAccessFlags,
+ MemberVisitor memberVisitor)
+ {
+ this.requiredSetAccessFlags = requiredSetAccessFlags & ~ACCESS_MASK;
+ this.requiredUnsetAccessFlags = requiredUnsetAccessFlags;
+ this.requiredOneSetAccessFlags = requiredSetAccessFlags & ACCESS_MASK;
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (accepted(programField.getAccessFlags()))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (accepted(programMethod.getAccessFlags()))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (accepted(libraryField.getAccessFlags()))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (accepted(libraryMethod.getAccessFlags()))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean accepted(int accessFlags)
+ {
+ return (requiredSetAccessFlags & ~accessFlags) == 0 &&
+ (requiredUnsetAccessFlags & accessFlags) == 0 &&
+ (requiredOneSetAccessFlags == 0 ||
+ (requiredOneSetAccessFlags & accessFlags) != 0);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberClassAccessFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberClassAccessFilter.java
new file mode 100644
index 0000000000..3dcbf951f0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberClassAccessFilter.java
@@ -0,0 +1,106 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to another given
+ * <code>MemberVisitor</code>, but only when the visited member is accessible
+ * from the given referencing class.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberClassAccessFilter
+implements MemberVisitor
+{
+ private final Clazz referencingClass;
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new MemberAccessFilter.
+ * @param referencingClass the class that is accessing the member.
+ * @param memberVisitor the <code>MemberVisitor</code> to which visits
+ * will be delegated.
+ */
+ public MemberClassAccessFilter(Clazz referencingClass,
+ MemberVisitor memberVisitor)
+ {
+ this.referencingClass = referencingClass;
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (accepted(programClass, programField.getAccessFlags()))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (accepted(programClass, programMethod.getAccessFlags()))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (accepted(libraryClass, libraryField.getAccessFlags()))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (accepted(libraryClass, libraryMethod.getAccessFlags()))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean accepted(Clazz clazz, int memberAccessFlags)
+ {
+ int accessLevel = AccessUtil.accessLevel(memberAccessFlags);
+
+ return
+ (accessLevel >= AccessUtil.PUBLIC ) ||
+ (accessLevel >= AccessUtil.PRIVATE && referencingClass.equals(clazz) ) ||
+ (accessLevel >= AccessUtil.PACKAGE_VISIBLE && (ClassUtil.internalPackageName(referencingClass.getName()).equals(
+ ClassUtil.internalPackageName(clazz.getName())))) ||
+ (accessLevel >= AccessUtil.PROTECTED && (referencingClass.extends_(clazz) ||
+ referencingClass.extendsOrImplements(clazz)) );
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberCollector.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberCollector.java
new file mode 100644
index 0000000000..5a344a0c93
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberCollector.java
@@ -0,0 +1,59 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+import java.util.Set;
+
+/**
+ * This MemberVisitor collects the concatenated name/descriptor strings of
+ * class members that have been visited.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberCollector
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final Set set;
+
+
+ /**
+ * Creates a new MemberCollector.
+ * @param set the <code>Set</code> in which all method names/descriptor
+ * strings will be collected.
+ */
+ public MemberCollector(Set set)
+ {
+ this.set = set;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ set.add(member.getName(clazz) + member.getDescriptor(clazz));
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberCounter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberCounter.java
new file mode 100644
index 0000000000..535bdeb58e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberCounter.java
@@ -0,0 +1,72 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+/**
+ * This MemberVisitor counts the number of class members that have been visited.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberCounter implements MemberVisitor
+{
+ private int count;
+
+
+ /**
+ * Returns the number of class members that has been visited so far.
+ */
+ public int getCount()
+ {
+ return count;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitLibraryField(LibraryClass libraryClass,
+ LibraryField libraryField)
+ {
+ count++;
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass,
+ LibraryMethod libraryMethod)
+ {
+ count++;
+ }
+
+
+ public void visitProgramField(ProgramClass programClass,
+ ProgramField programField)
+ {
+ count++;
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass,
+ ProgramMethod programMethod)
+ {
+ count++;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberDescriptorFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberDescriptorFilter.java
new file mode 100644
index 0000000000..8d2318b385
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberDescriptorFilter.java
@@ -0,0 +1,113 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.util.*;
+
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to another given
+ * <code>MemberVisitor</code>, but only when the visited member
+ * has a descriptor that matches a given regular expression.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberDescriptorFilter implements MemberVisitor
+{
+ private final StringMatcher regularExpressionMatcher;
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new MemberDescriptorFilter.
+ * @param regularExpression the regular expression against which member
+ * descriptors will be matched.
+ * @param memberVisitor the <code>MemberVisitor</code> to which visits
+ * will be delegated.
+ */
+ public MemberDescriptorFilter(String regularExpression,
+ MemberVisitor memberVisitor)
+ {
+ this(new ClassNameParser().parse(regularExpression), memberVisitor);
+ }
+
+
+ /**
+ * Creates a new MemberDescriptorFilter.
+ * @param regularExpressionMatcher the regular expression against which
+ * member descriptors will be matched.
+ * @param memberVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public MemberDescriptorFilter(StringMatcher regularExpressionMatcher,
+ MemberVisitor memberVisitor)
+ {
+ this.regularExpressionMatcher = regularExpressionMatcher;
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (accepted(programField.getDescriptor(programClass)))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (accepted(programMethod.getDescriptor(programClass)))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (accepted(libraryField.getDescriptor(libraryClass)))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (accepted(libraryMethod.getDescriptor(libraryClass)))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean accepted(String name)
+ {
+ return regularExpressionMatcher.matches(name);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberDescriptorReferencedClassVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberDescriptorReferencedClassVisitor.java
new file mode 100644
index 0000000000..6d7d37749d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberDescriptorReferencedClassVisitor.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This MemberVisitor lets a given ClassVisitor visit all the classes
+ * referenced by the descriptors of the class members that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberDescriptorReferencedClassVisitor
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public MemberDescriptorReferencedClassVisitor(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ // Let the visitor visit the classes referenced in the descriptor string.
+ programMember.referencedClassesAccept(classVisitor);
+ }
+
+
+ public void visitLibraryMember(LibraryClass programClass, LibraryMember libraryMember)
+ {
+ // Let the visitor visit the classes referenced in the descriptor string.
+ libraryMember.referencedClassesAccept(classVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberNameFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberNameFilter.java
new file mode 100644
index 0000000000..bca612020b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberNameFilter.java
@@ -0,0 +1,114 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.util.*;
+
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to another given
+ * <code>MemberVisitor</code>, but only when the visited member
+ * has a name that matches a given regular expression.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberNameFilter implements MemberVisitor
+{
+ private final StringMatcher regularExpressionMatcher;
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new MemberNameFilter.
+ * @param regularExpression the regular expression against which member
+ * names will be matched.
+ * @param memberVisitor the <code>MemberVisitor</code> to which visits
+ * will be delegated.
+ */
+ public MemberNameFilter(String regularExpression,
+ MemberVisitor memberVisitor)
+ {
+ this(new ListParser(new NameParser()).parse(regularExpression),
+ memberVisitor);
+ }
+
+
+ /**
+ * Creates a new MemberNameFilter.
+ * @param regularExpressionMatcher the regular expression against which
+ * member names will be matched.
+ * @param memberVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public MemberNameFilter(StringMatcher regularExpressionMatcher,
+ MemberVisitor memberVisitor)
+ {
+ this.regularExpressionMatcher = regularExpressionMatcher;
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (accepted(programField.getName(programClass)))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (accepted(programMethod.getName(programClass)))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (accepted(libraryField.getName(libraryClass)))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (accepted(libraryMethod.getName(libraryClass)))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean accepted(String name)
+ {
+ return regularExpressionMatcher.matches(name);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberToClassVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberToClassVisitor.java
new file mode 100644
index 0000000000..4f089f3d07
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberToClassVisitor.java
@@ -0,0 +1,90 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This MemberVisitor delegates all visits to a given ClassVisitor.
+ * The latter visits the class of each visited class member, although
+ * never twice in a row.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberToClassVisitor implements MemberVisitor
+{
+ private final ClassVisitor classVisitor;
+
+ private Clazz lastVisitedClass;
+
+
+ public MemberToClassVisitor(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (!programClass.equals(lastVisitedClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+
+ lastVisitedClass = programClass;
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (!programClass.equals(lastVisitedClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+
+ lastVisitedClass = programClass;
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (!libraryClass.equals(lastVisitedClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+
+ lastVisitedClass = libraryClass;
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (!libraryClass.equals(lastVisitedClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+
+ lastVisitedClass = libraryClass;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberVisitor.java
new file mode 100644
index 0000000000..1e14c9a720
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MemberVisitor.java
@@ -0,0 +1,40 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This interface specifies the methods for a visitor of
+ * <code>ProgramMember</code> objects and <code>LibraryMember</code>
+ * objects.
+ *
+ * @author Eric Lafortune
+ */
+public interface MemberVisitor
+{
+ public void visitProgramField( ProgramClass programClass, ProgramField programField);
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod);
+
+ public void visitLibraryField( LibraryClass libraryClass, LibraryField libraryField);
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MethodImplementationFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MethodImplementationFilter.java
new file mode 100644
index 0000000000..96d0a4e6fd
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MethodImplementationFilter.java
@@ -0,0 +1,70 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to methods to
+ * another given <code>MemberVisitor</code>, but only when the visited
+ * method may have implementations.
+ *
+ * @see Clazz#mayHaveImplementations(Method)
+ * @author Eric Lafortune
+ */
+public class MethodImplementationFilter
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new MethodImplementationFilter.
+ * @param memberVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public MethodImplementationFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (programClass.mayHaveImplementations(programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (libraryClass.mayHaveImplementations(libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MethodImplementationTraveler.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MethodImplementationTraveler.java
new file mode 100644
index 0000000000..1ff7b138dd
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MethodImplementationTraveler.java
@@ -0,0 +1,128 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This <code>MemberVisitor</code> lets a given <code>MemberVisitor</code>
+ * travel to all concrete and abstract implementations of the visited methods
+ * in their class hierarchies.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodImplementationTraveler
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final boolean visitThisMethod;
+ private final boolean visitSuperMethods;
+ private final boolean visitInterfaceMethods;
+ private final boolean visitOverridingMethods;
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new MethodImplementationTraveler.
+ * @param visitThisMethod specifies whether to visit the originally
+ * visited methods.
+ * @param visitSuperMethods specifies whether to visit the method in
+ * the super classes.
+ * @param visitInterfaceMethods specifies whether to visit the method in
+ * the interface classes.
+ * @param visitOverridingMethods specifies whether to visit the method in
+ * the subclasses.
+ * @param memberVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public MethodImplementationTraveler(boolean visitThisMethod,
+ boolean visitSuperMethods,
+ boolean visitInterfaceMethods,
+ boolean visitOverridingMethods,
+ MemberVisitor memberVisitor)
+ {
+ this.visitThisMethod = visitThisMethod;
+ this.visitSuperMethods = visitSuperMethods;
+ this.visitInterfaceMethods = visitInterfaceMethods;
+ this.visitOverridingMethods = visitOverridingMethods;
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (visitThisMethod)
+ {
+ programMethod.accept(programClass, memberVisitor);
+ }
+
+ if (!isSpecial(programClass, programMethod))
+ {
+ programClass.hierarchyAccept(false,
+ visitSuperMethods,
+ visitInterfaceMethods,
+ visitOverridingMethods,
+ new NamedMethodVisitor(programMethod.getName(programClass),
+ programMethod.getDescriptor(programClass),
+ new MemberAccessFilter(0,
+ ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC,
+ memberVisitor)));
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (visitThisMethod)
+ {
+ libraryMethod.accept(libraryClass, memberVisitor);
+ }
+
+ if (!isSpecial(libraryClass, libraryMethod))
+ {
+ libraryClass.hierarchyAccept(false,
+ visitSuperMethods,
+ visitInterfaceMethods,
+ visitOverridingMethods,
+ new NamedMethodVisitor(libraryMethod.getName(libraryClass),
+ libraryMethod.getDescriptor(libraryClass),
+ new MemberAccessFilter(0,
+ ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC,
+ memberVisitor)));
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean isSpecial(Clazz clazz, Method method)
+ {
+ return (method.getAccessFlags() &
+ (ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC)) != 0 ||
+ method.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiClassPoolVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiClassPoolVisitor.java
new file mode 100644
index 0000000000..5fb4cc89be
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiClassPoolVisitor.java
@@ -0,0 +1,88 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.ClassPool;
+
+
+/**
+ * This ClassPoolVisitor delegates all visits to each ClassPoolVisitor
+ * in a given list.
+ *
+ * @author Eric Lafortune
+ */
+public class MultiClassPoolVisitor implements ClassPoolVisitor
+{
+ private static final int ARRAY_SIZE_INCREMENT = 5;
+
+ private ClassPoolVisitor[] classPoolVisitors;
+ private int classPoolVisitorCount;
+
+
+ public MultiClassPoolVisitor()
+ {
+ }
+
+
+ public MultiClassPoolVisitor(ClassPoolVisitor[] classPoolVisitors)
+ {
+ this.classPoolVisitors = classPoolVisitors;
+ this.classPoolVisitorCount = classPoolVisitors.length;
+ }
+
+
+ public void addClassPoolVisitor(ClassPoolVisitor classPoolVisitor)
+ {
+ ensureArraySize();
+
+ classPoolVisitors[classPoolVisitorCount++] = classPoolVisitor;
+ }
+
+
+ private void ensureArraySize()
+ {
+ if (classPoolVisitors == null)
+ {
+ classPoolVisitors = new ClassPoolVisitor[ARRAY_SIZE_INCREMENT];
+ }
+ else if (classPoolVisitors.length == classPoolVisitorCount)
+ {
+ ClassPoolVisitor[] newClassPoolVisitors =
+ new ClassPoolVisitor[classPoolVisitorCount +
+ ARRAY_SIZE_INCREMENT];
+ System.arraycopy(classPoolVisitors, 0,
+ newClassPoolVisitors, 0,
+ classPoolVisitorCount);
+ classPoolVisitors = newClassPoolVisitors;
+ }
+ }
+
+
+ // Implementations for ClassPoolVisitor.
+
+ public void visitClassPool(ClassPool classPool)
+ {
+ for (int index = 0; index < classPoolVisitorCount; index++)
+ {
+ classPoolVisitors[index].visitClassPool(classPool);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiClassVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiClassVisitor.java
new file mode 100644
index 0000000000..379b16a8b0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiClassVisitor.java
@@ -0,0 +1,97 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This ClassVisitor delegates all visits to each ClassVisitor
+ * in a given list.
+ *
+ * @author Eric Lafortune
+ */
+public class MultiClassVisitor implements ClassVisitor
+{
+ private static final int ARRAY_SIZE_INCREMENT = 5;
+
+ private ClassVisitor[] classVisitors;
+ private int classVisitorCount;
+
+
+ public MultiClassVisitor()
+ {
+ }
+
+
+ public MultiClassVisitor(ClassVisitor[] classVisitors)
+ {
+ this.classVisitors = classVisitors;
+ this.classVisitorCount = classVisitors.length;
+ }
+
+
+ public void addClassVisitor(ClassVisitor classVisitor)
+ {
+ ensureArraySize();
+
+ classVisitors[classVisitorCount++] = classVisitor;
+ }
+
+
+ private void ensureArraySize()
+ {
+ if (classVisitors == null)
+ {
+ classVisitors = new ClassVisitor[ARRAY_SIZE_INCREMENT];
+ }
+ else if (classVisitors.length == classVisitorCount)
+ {
+ ClassVisitor[] newClassVisitors =
+ new ClassVisitor[classVisitorCount +
+ ARRAY_SIZE_INCREMENT];
+ System.arraycopy(classVisitors, 0,
+ newClassVisitors, 0,
+ classVisitorCount);
+ classVisitors = newClassVisitors;
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ for (int index = 0; index < classVisitorCount; index++)
+ {
+ classVisitors[index].visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ for (int index = 0; index < classVisitorCount; index++)
+ {
+ classVisitors[index].visitLibraryClass(libraryClass);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiMemberVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiMemberVisitor.java
new file mode 100644
index 0000000000..dde3f37225
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/MultiMemberVisitor.java
@@ -0,0 +1,113 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This MemberVisitor delegates all visits to each MemberVisitor
+ * in a given list.
+ *
+ * @author Eric Lafortune
+ */
+public class MultiMemberVisitor implements MemberVisitor
+{
+ private static final int ARRAY_SIZE_INCREMENT = 5;
+
+ private MemberVisitor[] memberVisitors;
+ private int memberVisitorCount;
+
+
+ public MultiMemberVisitor()
+ {
+ }
+
+
+ public MultiMemberVisitor(MemberVisitor[] memberVisitors)
+ {
+ this.memberVisitors = memberVisitors;
+ this.memberVisitorCount = memberVisitors.length;
+ }
+
+
+ public void addMemberVisitor(MemberVisitor memberVisitor)
+ {
+ ensureArraySize();
+
+ memberVisitors[memberVisitorCount++] = memberVisitor;
+ }
+
+
+ private void ensureArraySize()
+ {
+ if (memberVisitors == null)
+ {
+ memberVisitors = new MemberVisitor[ARRAY_SIZE_INCREMENT];
+ }
+ else if (memberVisitors.length == memberVisitorCount)
+ {
+ MemberVisitor[] newMemberVisitors =
+ new MemberVisitor[memberVisitorCount +
+ ARRAY_SIZE_INCREMENT];
+ System.arraycopy(memberVisitors, 0,
+ newMemberVisitors, 0,
+ memberVisitorCount);
+ memberVisitors = newMemberVisitors;
+ }
+ }
+
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ for (int index = 0; index < memberVisitorCount; index++)
+ {
+ memberVisitors[index].visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ for (int index = 0; index < memberVisitorCount; index++)
+ {
+ memberVisitors[index].visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ for (int index = 0; index < memberVisitorCount; index++)
+ {
+ memberVisitors[index].visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ for (int index = 0; index < memberVisitorCount; index++)
+ {
+ memberVisitors[index].visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedClassVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedClassVisitor.java
new file mode 100644
index 0000000000..2daeba24fa
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedClassVisitor.java
@@ -0,0 +1,49 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.ClassPool;
+
+
+/**
+ * This class visits Clazz objects with the given name.
+ *
+ * @author Eric Lafortune
+ */
+public class NamedClassVisitor implements ClassPoolVisitor
+{
+ private final ClassVisitor classVisitor;
+ private final String name;
+
+
+ public NamedClassVisitor(ClassVisitor classVisitor,
+ String name)
+ {
+ this.classVisitor = classVisitor;
+ this.name = name;
+ }
+
+
+ public void visitClassPool(ClassPool classPool)
+ {
+ classPool.classAccept(name, classVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedFieldVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedFieldVisitor.java
new file mode 100644
index 0000000000..ed8df14963
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedFieldVisitor.java
@@ -0,0 +1,61 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This class visits ProgramMember objects referring to fields, identified by
+ * a name and descriptor pair.
+ *
+ * @author Eric Lafortune
+ */
+public class NamedFieldVisitor implements ClassVisitor
+{
+ private final String name;
+ private final String descriptor;
+ private final MemberVisitor memberVisitor;
+
+
+ public NamedFieldVisitor(String name,
+ String descriptor,
+ MemberVisitor memberVisitor)
+ {
+ this.name = name;
+ this.descriptor = descriptor;
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.fieldAccept(name, descriptor, memberVisitor);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ libraryClass.fieldAccept(name, descriptor, memberVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedMethodVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedMethodVisitor.java
new file mode 100644
index 0000000000..817e969b1e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/NamedMethodVisitor.java
@@ -0,0 +1,61 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This class visits ProgramMember objects referring to methods, identified by
+ * a name and descriptor pair.
+ *
+ * @author Eric Lafortune
+ */
+public class NamedMethodVisitor implements ClassVisitor
+{
+ private final String name;
+ private final String descriptor;
+ private final MemberVisitor memberVisitor;
+
+
+ public NamedMethodVisitor(String name,
+ String descriptor,
+ MemberVisitor memberVisitor)
+ {
+ this.name = name;
+ this.descriptor = descriptor;
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.methodAccept(name, descriptor, memberVisitor);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ libraryClass.methodAccept(name, descriptor, memberVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ParameterVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ParameterVisitor.java
new file mode 100644
index 0000000000..805e1de086
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ParameterVisitor.java
@@ -0,0 +1,56 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+/**
+ * This interface specifies the methods for a visitor of method parameters or
+ * field types (which can be considered parameters when storing values). The
+ * parameters do not include or count the 'this' parameter or the method return
+ * value.
+ *
+ * @author Eric Lafortune
+ */
+public interface ParameterVisitor
+{
+ /**
+ * Visits the given parameter.
+ * @param clazz the class of the method.
+ * @param member the field or method of the parameter.
+ * @param parameterIndex the index of the parameter.
+ * @param parameterCount the total number of parameters.
+ * @param parameterOffset the offset of the parameter, accounting for
+ * longs and doubles taking up two entries.
+ * @param parameterSize the total size of the parameters, accounting for
+ * longs and doubles taking up two entries.
+ * @param parameterType the parameter type.
+ * @param referencedClass the class contained in the parameter type, if any.
+ */
+ public void visitParameter(Clazz clazz,
+ Member member,
+ int parameterIndex,
+ int parameterCount,
+ int parameterOffset,
+ int parameterSize,
+ String parameterType,
+ Clazz referencedClass);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ProgramClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ProgramClassFilter.java
new file mode 100644
index 0000000000..088da872e4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ProgramClassFilter.java
@@ -0,0 +1,60 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to another given
+ * <code>ClassVisitor</code>, but only when visiting program classes.
+ *
+ * @author Eric Lafortune
+ */
+public class ProgramClassFilter implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ProgramClassFilter.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits
+ * will be delegated.
+ */
+ public ProgramClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Don't delegate visits to library classes.
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ProgramMemberFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ProgramMemberFilter.java
new file mode 100644
index 0000000000..25299f429c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ProgramMemberFilter.java
@@ -0,0 +1,73 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to another given
+ * <code>MemberVisitor</code>, but only when visiting members of program
+ * classes.
+ *
+ * @author Eric Lafortune
+ */
+public class ProgramMemberFilter implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new ProgramMemberFilter.
+ * @param memberVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public ProgramMemberFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ // Don't delegate visits to library members.
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ // Don't delegate visits to library members.
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ReferencedClassVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ReferencedClassVisitor.java
new file mode 100644
index 0000000000..f60c06da42
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ReferencedClassVisitor.java
@@ -0,0 +1,269 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This ClassVisitor, MemberVisitor, ConstantVisitor, AttributeVisitor, etc.
+ * lets a given ClassVisitor visit all the referenced classes of the elements
+ * that it visits. Only downstream elements are considered (in order to avoid
+ * loops and repeated visits).
+ *
+ * @author Eric Lafortune
+ */
+public class ReferencedClassVisitor
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ ConstantVisitor,
+ AttributeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor
+{
+ protected final ClassVisitor classVisitor;
+
+
+ public ReferencedClassVisitor(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Visit the constant pool entries.
+ programClass.constantPoolEntriesAccept(this);
+
+ // Visit the fields and methods.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ // Visit the attributes.
+ programClass.attributesAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Visit the superclass and interfaces.
+ libraryClass.superClassAccept(classVisitor);
+ libraryClass.interfacesAccept(classVisitor);
+
+ // Visit the fields and methods.
+ libraryClass.fieldsAccept(this);
+ libraryClass.methodsAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ // Let the visitor visit the classes referenced in the descriptor string.
+ programMember.referencedClassesAccept(classVisitor);
+
+ // Visit the attributes.
+ programMember.attributesAccept(programClass, this);
+ }
+
+
+ public void visitLibraryMember(LibraryClass programClass, LibraryMember libraryMember)
+ {
+ // Let the visitor visit the classes referenced in the descriptor string.
+ libraryMember.referencedClassesAccept(classVisitor);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Let the visitor visit the class referenced in the string constant.
+ stringConstant.referencedClassAccept(classVisitor);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Let the visitor visit the class referenced in the reference constant.
+ refConstant.referencedClassAccept(classVisitor);
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Let the visitor visit the class referenced in the reference constant.
+ invokeDynamicConstant.referencedClassesAccept(classVisitor);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Let the visitor visit the class referenced in the class constant.
+ classConstant.referencedClassAccept(classVisitor);
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ // Let the visitor visit the classes referenced in the method type constant.
+ methodTypeConstant.referencedClassesAccept(classVisitor);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ // Let the visitor visit the class of the enclosing method.
+ enclosingMethodAttribute.referencedClassAccept(classVisitor);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Visit the attributes of the code attribute.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Visit the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Visit the local variable types.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ // Let the visitor visit the classes referenced in the signature string.
+ signatureAttribute.referencedClassesAccept(classVisitor);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ // Visit the annotations.
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Visit the parameter annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Visit the default element value.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Let the visitor visit the class referenced in the local variable.
+ localVariableInfo.referencedClassAccept(classVisitor);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Let the visitor visit the classes referenced in the local variable type.
+ localVariableTypeInfo.referencedClassesAccept(classVisitor);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ // Let the visitor visit the classes referenced in the annotation.
+ annotation.referencedClassesAccept(classVisitor);
+
+ // Visit the element values.
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) {}
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ // Let the visitor visit the classes referenced in the constant element value.
+ enumConstantElementValue.referencedClassesAccept(classVisitor);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ // Let the visitor visit the classes referenced in the class element value.
+ classElementValue.referencedClassesAccept(classVisitor);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ // Visit the contained annotation.
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ // Visit the element values.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ReferencedMemberVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
new file mode 100644
index 0000000000..768bdf49eb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
@@ -0,0 +1,73 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This ConstantVisitor and ElementValueVisitor lets a given MemberVisitor
+ * visit all the referenced class members of the elements that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class ReferencedMemberVisitor
+extends SimplifiedVisitor
+implements ConstantVisitor,
+ ElementValueVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ public ReferencedMemberVisitor(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ stringConstant.referencedMemberAccept(memberVisitor);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ refConstant.referencedMemberAccept(memberVisitor);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue)
+ {
+ elementValue.referencedMethodAccept(memberVisitor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SimilarMemberVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SimilarMemberVisitor.java
new file mode 100644
index 0000000000..21abb2f943
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SimilarMemberVisitor.java
@@ -0,0 +1,125 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+/**
+ * This <code>MemberVisitor</code> lets a given <code>MemberVisitor</code>
+ * visit all members that have the same name and type as the visited methods
+ * in the class hierarchy of a given target class.
+ *
+ * @author Eric Lafortune
+ */
+public class SimilarMemberVisitor
+implements MemberVisitor
+{
+ private final Clazz targetClass;
+ private final boolean visitThisMember;
+ private final boolean visitSuperMembers;
+ private final boolean visitInterfaceMembers;
+ private final boolean visitOverridingMembers;
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new SimilarMemberVisitor.
+ * @param targetClass the class in whose hierarchy to look for
+ * the visited class members.
+ * @param visitThisMember specifies whether to visit the class
+ * members in the target class itself.
+ * @param visitSuperMembers specifies whether to visit the class
+ * members in the super classes of the target
+ * class.
+ * @param visitInterfaceMembers specifies whether to visit the class
+ * members in the interface classes of the
+ * target class.
+ * @param visitOverridingMembers specifies whether to visit the class
+ * members in the subclasses of the target
+ * class.
+ * @param memberVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public SimilarMemberVisitor(Clazz targetClass,
+ boolean visitThisMember,
+ boolean visitSuperMembers,
+ boolean visitInterfaceMembers,
+ boolean visitOverridingMembers,
+ MemberVisitor memberVisitor)
+ {
+ this.targetClass = targetClass;
+ this.visitThisMember = visitThisMember;
+ this.visitSuperMembers = visitSuperMembers;
+ this.visitInterfaceMembers = visitInterfaceMembers;
+ this.visitOverridingMembers = visitOverridingMembers;
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ targetClass.hierarchyAccept(visitThisMember,
+ visitSuperMembers,
+ visitInterfaceMembers,
+ visitOverridingMembers,
+ new NamedFieldVisitor(programField.getName(programClass),
+ programField.getDescriptor(programClass),
+ memberVisitor));
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ targetClass.hierarchyAccept(visitThisMember,
+ visitSuperMembers,
+ visitInterfaceMembers,
+ visitOverridingMembers,
+ new NamedFieldVisitor(libraryField.getName(libraryClass),
+ libraryField.getDescriptor(libraryClass),
+ memberVisitor));
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ targetClass.hierarchyAccept(visitThisMember,
+ visitSuperMembers,
+ visitInterfaceMembers,
+ visitOverridingMembers,
+ new NamedMethodVisitor(programMethod.getName(programClass),
+ programMethod.getDescriptor(programClass),
+ memberVisitor));
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ targetClass.hierarchyAccept(visitThisMember,
+ visitSuperMembers,
+ visitInterfaceMembers,
+ visitOverridingMembers,
+ new NamedMethodVisitor(libraryMethod.getName(libraryClass),
+ libraryMethod.getDescriptor(libraryClass),
+ memberVisitor));
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SimpleClassPrinter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SimpleClassPrinter.java
new file mode 100644
index 0000000000..9ee92fc11f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SimpleClassPrinter.java
@@ -0,0 +1,167 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+
+import java.io.PrintStream;
+
+
+/**
+ * This <code>ClassVisitor</code> and <code>MemberVisitor</code>
+ * prints out the class names of the classes it visits, and the full class
+ * member descriptions of the class members it visits. The names are printed
+ * in a readable, Java-like format. The access modifiers can be included or not.
+ *
+ * @author Eric Lafortune
+ */
+public class SimpleClassPrinter
+implements ClassVisitor,
+ MemberVisitor
+{
+ private final boolean printAccessModifiers;
+ private final PrintStream ps;
+
+
+ /**
+ * Creates a new SimpleClassPrinter that prints to
+ * <code>System.out</code>, including the access modifiers.
+ */
+ public SimpleClassPrinter()
+ {
+ this(true);
+ }
+
+ /**
+ * Creates a new SimpleClassPrinter that prints to
+ * <code>System.out</code>, with or without the access modifiers.
+ */
+ public SimpleClassPrinter(boolean printAccessModifiers)
+ {
+ this(printAccessModifiers, System.out);
+ }
+
+ /**
+ * Creates a new SimpleClassPrinter that prints to the given
+ * <code>PrintStream</code>, with or without the access modifiers.
+ */
+ public SimpleClassPrinter(boolean printAccessModifiers,
+ PrintStream printStream)
+ {
+ this.printAccessModifiers = printAccessModifiers;
+ this.ps = printStream;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ ps.println(ClassUtil.externalFullClassDescription(
+ printAccessModifiers ?
+ programClass.getAccessFlags() :
+ 0,
+ programClass.getName()));
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ ps.println(ClassUtil.externalFullClassDescription(
+ printAccessModifiers ?
+ libraryClass.getAccessFlags() :
+ 0,
+ libraryClass.getName()));
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ ps.println(ClassUtil.externalFullClassDescription(
+ printAccessModifiers ?
+ programClass.getAccessFlags() :
+ 0,
+ programClass.getName()) +
+ ": " +
+ ClassUtil.externalFullFieldDescription(
+ printAccessModifiers ?
+ programField.getAccessFlags() :
+ 0,
+ programField.getName(programClass),
+ programField.getDescriptor(programClass)));
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ ps.println(ClassUtil.externalFullClassDescription(
+ printAccessModifiers ?
+ programClass.getAccessFlags() :
+ 0,
+ programClass.getName()) +
+ ": " +
+ ClassUtil.externalFullMethodDescription(
+ programClass.getName(),
+ printAccessModifiers ?
+ programMethod.getAccessFlags() :
+ 0,
+ programMethod.getName(programClass),
+ programMethod.getDescriptor(programClass)));
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ ps.println(ClassUtil.externalFullClassDescription(
+ printAccessModifiers ?
+ libraryClass.getAccessFlags() :
+ 0,
+ libraryClass.getName()) +
+ ": " +
+ ClassUtil.externalFullFieldDescription(
+ printAccessModifiers ?
+ libraryField.getAccessFlags() :
+ 0,
+ libraryField.getName(libraryClass),
+ libraryField.getDescriptor(libraryClass)));
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ ps.println(ClassUtil.externalFullClassDescription(
+ printAccessModifiers ?
+ libraryClass.getAccessFlags() :
+ 0,
+ libraryClass.getName()) +
+ ": " +
+ ClassUtil.externalFullMethodDescription(
+ libraryClass.getName(),
+ printAccessModifiers ?
+ libraryMethod.getAccessFlags() :
+ 0,
+ libraryMethod.getName(libraryClass),
+ libraryMethod.getDescriptor(libraryClass)));
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SubclassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SubclassFilter.java
new file mode 100644
index 0000000000..3ae644f6c6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SubclassFilter.java
@@ -0,0 +1,91 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to another given
+ * <code>ClassVisitor</code>, except for classes that have a given class as
+ * direct subclass.
+ *
+ * @author Eric Lafortune
+ */
+public class SubclassFilter implements ClassVisitor
+{
+ private final Clazz subclass;
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new SubclassFilter.
+ * @param subclass the class whose superclasses will not be visited.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits will
+ * be delegated.
+ */
+ public SubclassFilter(Clazz subclass,
+ ClassVisitor classVisitor)
+ {
+ this.subclass = subclass;
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (!present(programClass.subClasses))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (!present(libraryClass.subClasses))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean present(Clazz[] subclasses)
+ {
+ if (subclasses == null)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < subclasses.length; index++)
+ {
+ if (subclasses[index].equals(subclass))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SubclassTraveler.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SubclassTraveler.java
new file mode 100644
index 0000000000..e3ee6b72ed
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/SubclassTraveler.java
@@ -0,0 +1,60 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This <code>ClassVisitor</code> lets a given <code>ClassVisitor</code>
+ * travel to direct subclasses of the visited class.
+ *
+ * @author Eric Lafortune
+ */
+public class SubclassTraveler implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new ClassHierarchyTraveler.
+ * @param classVisitor the <code>ClassVisitor</code> to
+ * which visits will be delegated.
+ */
+ public SubclassTraveler(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.subclassesAccept(classVisitor);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ libraryClass.subclassesAccept(classVisitor);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/VariableClassVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/VariableClassVisitor.java
new file mode 100644
index 0000000000..31dc216b84
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/VariableClassVisitor.java
@@ -0,0 +1,78 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This ClassVisitor delegates all method calls to a ClassVisitor
+ * that can be changed at any time.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableClassVisitor implements ClassVisitor
+{
+ private ClassVisitor classVisitor;
+
+
+ public VariableClassVisitor()
+ {
+ this(null);
+ }
+
+
+ public VariableClassVisitor(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ public void setClassVisitor(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+ public ClassVisitor getClassVisitor()
+ {
+ return classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (classVisitor != null)
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (classVisitor != null)
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/VariableMemberVisitor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/VariableMemberVisitor.java
new file mode 100644
index 0000000000..91d6b060cf
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/VariableMemberVisitor.java
@@ -0,0 +1,96 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.visitor;
+
+import proguard.classfile.*;
+
+
+/**
+ * This MemberVisitor delegates all method calls to a MemberVisitor
+ * that can be changed at any time.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableMemberVisitor implements MemberVisitor
+{
+ private MemberVisitor memberVisitor;
+
+
+ public VariableMemberVisitor()
+ {
+ this(null);
+ }
+
+
+ public VariableMemberVisitor(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ public void setMemberVisitor(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+ public MemberVisitor getMemberVisitor()
+ {
+ return memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (memberVisitor != null)
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (memberVisitor != null)
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (memberVisitor != null)
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (memberVisitor != null)
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/package.html
new file mode 100644
index 0000000000..d3be40c09e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/classfile/visitor/package.html
@@ -0,0 +1,40 @@
+<body>
+This package contains interfaces and classes for processing class files from
+the <code>{@link proguard.classfile proguard.classfile}</code> package using
+the <i>visitor pattern</i>. Cfr., for instance, "Design Patterns, Elements of
+Reusable OO Software", by Gamma, Helm, Johnson, and Vlissider.
+<p>
+Why the visitor pattern? Class files frequently contain lists of elements of
+various mixed types: class items, constant pool entries, attributes,...
+These lists and types are largely fixed; they won't change much in future
+releases of the Java class file specifications. On the other hand, the kinds
+of operations that we may wish to perform on the class files may change and
+expand. We want to separate the objects and the operations performed upon them.
+This is a good place to use the visitor pattern.
+<p>
+Visitor interfaces avoid having to do series of <code>instanceof</code> tests
+on the elements of a list, followed by type casts and the proper operations.
+Every list element is a visitor accepter. When its <code>accept</code> method
+is called by a visitor, it calls its corresponding <code>visitX</code> method
+in the visitor, passing itself as an argument. This technique is called
+double-dispatch.
+<p>
+As already mentioned, the main advantage is avoiding lots of
+<code>instanceof</code> tests and type casts. Also, implementing a visitor
+interface ensures you're handling all possible visitor accepter types. Each
+type has its own method, which you simply have to implement.
+<p>
+A disadvantage is that the visitor methods always get the same names, specified
+by the visitor interface. These names aren't descriptive at all, making code
+harder to read. It's the visitor classes that describe the operations now.
+<p>
+Also, the visitor methods always have the same parameters and return values, as
+specified by the visitor interfaces. Passing additional parameters is done by
+means of extra fields in the visitor, which is somewhat of a kludge.
+<p>
+Because objects (the visitor accepters) and the operations performed upon them
+(the visitors) are now separated, it becomes harder to associate some state
+with the objects. For convenience, we always provide an extra <i>visitor
+info</i> field in visitor accepters, in which visitors can put any temporary
+information they want.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BasicBranchUnit.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BasicBranchUnit.java
new file mode 100644
index 0000000000..ae07632f74
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BasicBranchUnit.java
@@ -0,0 +1,126 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.evaluation.value.InstructionOffsetValue;
+
+/**
+ * This BranchUnit remembers the branch unit commands that are invoked on it.
+ * I doesn't consider conditions when branching.
+ *
+ * @author Eric Lafortune
+ */
+public class BasicBranchUnit
+implements BranchUnit
+{
+ private boolean wasCalled;
+ private InstructionOffsetValue traceBranchTargets;
+
+
+ /**
+ * Resets the flag that tells whether any of the branch unit commands was
+ * called.
+ */
+ public void resetCalled()
+ {
+ wasCalled = false;
+ }
+
+ /**
+ * Sets the flag that tells whether any of the branch unit commands was
+ * called.
+ */
+ protected void setCalled()
+ {
+ wasCalled = true;
+ }
+
+ /**
+ * Returns whether any of the branch unit commands was called.
+ */
+ public boolean wasCalled()
+ {
+ return wasCalled;
+ }
+
+
+ /**
+ * Sets the initial branch targets, which will be updated as the branch
+ * methods of the branch unit are called.
+ */
+ public void setTraceBranchTargets(InstructionOffsetValue branchTargets)
+ {
+ this.traceBranchTargets = branchTargets;
+ }
+
+ public InstructionOffsetValue getTraceBranchTargets()
+ {
+ return traceBranchTargets;
+ }
+
+
+ // Implementations for BranchUnit.
+
+ public void branch(Clazz clazz,
+ CodeAttribute codeAttribute,
+ int offset,
+ int branchTarget)
+ {
+ // Override the branch targets.
+ traceBranchTargets = new InstructionOffsetValue(branchTarget);
+
+ wasCalled = true;
+ }
+
+
+ public void branchConditionally(Clazz clazz,
+ CodeAttribute codeAttribute,
+ int offset,
+ int branchTarget,
+ int conditional)
+ {
+ // Accumulate the branch targets.
+ traceBranchTargets =
+ traceBranchTargets.generalize(new InstructionOffsetValue(branchTarget)).instructionOffsetValue();
+
+ wasCalled = true;
+ }
+
+
+ public void returnFromMethod()
+ {
+ // Stop processing this block.
+ traceBranchTargets = InstructionOffsetValue.EMPTY_VALUE;
+
+ wasCalled = true;
+ }
+
+
+ public void throwException()
+ {
+ // Stop processing this block.
+ traceBranchTargets = InstructionOffsetValue.EMPTY_VALUE;
+
+ wasCalled = true;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BasicInvocationUnit.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BasicInvocationUnit.java
new file mode 100644
index 0000000000..08eaaf95eb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BasicInvocationUnit.java
@@ -0,0 +1,426 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.evaluation.value.*;
+
+/**
+ * This InvocationUnit sets up the variables for entering a method,
+ * and it updates the stack for the invocation of a class member,
+ * using simple values.
+ *
+ * @author Eric Lafortune
+ */
+public class BasicInvocationUnit
+extends SimplifiedVisitor
+implements InvocationUnit,
+ ConstantVisitor,
+ MemberVisitor
+{
+ protected final ValueFactory valueFactory;
+
+ // Fields acting as parameters between the visitor methods.
+ private boolean isStatic;
+ private boolean isLoad;
+ private Stack stack;
+ private Clazz returnTypeClass;
+
+
+ /**
+ * Creates a new BasicInvocationUnit with the given value factory.
+ */
+ public BasicInvocationUnit(ValueFactory valueFactory)
+ {
+ this.valueFactory = valueFactory;
+ }
+
+
+ // Implementations for InvocationUnit.
+
+ public void enterMethod(Clazz clazz, Method method, Variables variables)
+ {
+ String descriptor = method.getDescriptor(clazz);
+
+ // Initialize the parameters.
+ boolean isStatic =
+ (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0;
+
+ // Count the number of parameters, taking into account their categories.
+ int parameterSize = ClassUtil.internalMethodParameterSize(descriptor, isStatic);
+
+ // Reuse the existing parameters object, ensuring the right size.
+ variables.reset(parameterSize);
+
+ // Go over the parameters again.
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(descriptor);
+
+ int parameterIndex = 0;
+ int variableIndex = 0;
+
+ // Put the 'this' reference in variable 0.
+ if (!isStatic)
+ {
+ // Get the reference value.
+ Value value = getMethodParameterValue(clazz,
+ method,
+ parameterIndex++,
+ ClassUtil.internalTypeFromClassName(clazz.getName()),
+ clazz);
+
+ // Store the value in variable 0.
+ variables.store(variableIndex++, value);
+ }
+
+ Clazz[] referencedClasses = ((ProgramMethod)method).referencedClasses;
+ int referencedClassIndex = 0;
+
+ // Set up the variables corresponding to the parameter types and values.
+ while (internalTypeEnumeration.hasMoreTypes())
+ {
+ String type = internalTypeEnumeration.nextType();
+
+ Clazz referencedClass =
+ referencedClasses != null &&
+ ClassUtil.isInternalClassType(type) ?
+ referencedClasses[referencedClassIndex++] :
+ null;
+
+ // Get the parameter value.
+ Value value = getMethodParameterValue(clazz,
+ method,
+ parameterIndex++,
+ type,
+ referencedClass);
+
+ // Store the value in the corresponding variable.
+ variables.store(variableIndex++, value);
+
+ // Increment the variable index again for Category 2 values.
+ if (value.isCategory2())
+ {
+ variableIndex++;
+ }
+ }
+ }
+
+
+ public void exitMethod(Clazz clazz, Method method, Value returnValue)
+ {
+ setMethodReturnValue(clazz, method, returnValue);
+ }
+
+
+ public void invokeMember(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction, Stack stack)
+ {
+ int constantIndex = constantInstruction.constantIndex;
+
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_GETSTATIC:
+ isStatic = true;
+ isLoad = true;
+ break;
+
+ case InstructionConstants.OP_PUTSTATIC:
+ isStatic = true;
+ isLoad = false;
+ break;
+
+ case InstructionConstants.OP_GETFIELD:
+ isStatic = false;
+ isLoad = true;
+ break;
+
+ case InstructionConstants.OP_PUTFIELD:
+ isStatic = false;
+ isLoad = false;
+ break;
+
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ isStatic = true;
+ break;
+
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ isStatic = false;
+ break;
+ }
+
+ // Pop the parameters and push the return value.
+ this.stack = stack;
+ clazz.constantPoolEntryAccept(constantIndex, this);
+ this.stack = null;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ // Pop the field value, if applicable.
+ if (!isLoad)
+ {
+ setFieldValue(clazz, fieldrefConstant, stack.pop());
+ }
+
+ // Pop the reference value, if applicable.
+ if (!isStatic)
+ {
+ setFieldClassValue(clazz, fieldrefConstant, stack.apop());
+ }
+
+ // Push the field value, if applicable.
+ if (isLoad)
+ {
+ String type = fieldrefConstant.getType(clazz);
+
+ stack.push(getFieldValue(clazz, fieldrefConstant, type));
+ }
+ }
+
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant methodrefConstant)
+ {
+ String type = methodrefConstant.getType(clazz);
+
+ // Count the number of parameters.
+ int parameterCount = ClassUtil.internalMethodParameterCount(type);
+ if (!isStatic)
+ {
+ parameterCount++;
+ }
+
+ // Pop the parameters and the class reference, in reverse order.
+ for (int parameterIndex = parameterCount-1; parameterIndex >= 0; parameterIndex--)
+ {
+ setMethodParameterValue(clazz, methodrefConstant, parameterIndex, stack.pop());
+ }
+
+ // Push the return value, if applicable.
+ String returnType = ClassUtil.internalMethodReturnType(type);
+ if (returnType.charAt(0) != ClassConstants.TYPE_VOID)
+ {
+ stack.push(getMethodReturnValue(clazz, methodrefConstant, returnType));
+ }
+ }
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ String type = invokeDynamicConstant.getType(clazz);
+
+ // Count the number of parameters.
+ int parameterCount = ClassUtil.internalMethodParameterCount(type);
+ if (!isStatic)
+ {
+ parameterCount++;
+ }
+
+ // Pop the parameters and the class reference, in reverse order.
+ for (int parameterIndex = parameterCount-1; parameterIndex >= 0; parameterIndex--)
+ {
+ stack.pop();
+ }
+
+ // Push the return value, if applicable.
+ String returnType = ClassUtil.internalMethodReturnType(type);
+ if (returnType.charAt(0) != ClassConstants.TYPE_VOID)
+ {
+ stack.push(getMethodReturnValue(clazz, invokeDynamicConstant, returnType));
+ }
+ }
+
+
+ /**
+ * Sets the class through which the specified field is accessed.
+ */
+ protected void setFieldClassValue(Clazz clazz,
+ RefConstant refConstant,
+ ReferenceValue value)
+ {
+ // We don't care about the new value.
+ }
+
+
+ /**
+ * Returns the class though which the specified field is accessed.
+ */
+ protected Value getFieldClassValue(Clazz clazz,
+ RefConstant refConstant,
+ String type)
+ {
+ // Try to figure out the class of the return type.
+ returnTypeClass = null;
+ refConstant.referencedMemberAccept(this);
+
+ return valueFactory.createValue(type,
+ returnTypeClass,
+ true);
+ }
+
+
+ /**
+ * Sets the value of the specified field.
+ */
+ protected void setFieldValue(Clazz clazz,
+ RefConstant refConstant,
+ Value value)
+ {
+ // We don't care about the new field value.
+ }
+
+
+ /**
+ * Returns the value of the specified field.
+ */
+ protected Value getFieldValue(Clazz clazz,
+ RefConstant refConstant,
+ String type)
+ {
+ // Try to figure out the class of the return type.
+ returnTypeClass = null;
+ refConstant.referencedMemberAccept(this);
+
+ return valueFactory.createValue(type,
+ returnTypeClass,
+ true);
+ }
+
+
+ /**
+ * Sets the value of the specified method parameter.
+ */
+ protected void setMethodParameterValue(Clazz clazz,
+ RefConstant refConstant,
+ int parameterIndex,
+ Value value)
+ {
+ // We don't care about the parameter value.
+ }
+
+
+ /**
+ * Returns the value of the specified method parameter.
+ */
+ protected Value getMethodParameterValue(Clazz clazz,
+ Method method,
+ int parameterIndex,
+ String type,
+ Clazz referencedClass)
+ {
+ return valueFactory.createValue(type, referencedClass, true);
+ }
+
+
+ /**
+ * Sets the return value of the specified method.
+ */
+ protected void setMethodReturnValue(Clazz clazz,
+ Method method,
+ Value value)
+ {
+ // We don't care about the return value.
+ }
+
+
+ /**
+ * Returns the return value of the specified method.
+ */
+ protected Value getMethodReturnValue(Clazz clazz,
+ RefConstant refConstant,
+ String type)
+ {
+ // Try to figure out the class of the return type.
+ returnTypeClass = null;
+ refConstant.referencedMemberAccept(this);
+
+ return valueFactory.createValue(type,
+ returnTypeClass,
+ true);
+ }
+
+
+ /**
+ * Returns the return value of the specified method.
+ */
+ protected Value getMethodReturnValue(Clazz clazz,
+ InvokeDynamicConstant invokeDynamicConstant,
+ String type)
+ {
+ // Try to figure out the class of the return type.
+ Clazz[] referencedClasses = invokeDynamicConstant.referencedClasses;
+
+ Clazz referencedClass =
+ referencedClasses != null &&
+ ClassUtil.isInternalClassType(type) ?
+ referencedClasses[referencedClasses.length - 1] :
+ null;
+
+ return valueFactory.createValue(type,
+ referencedClass,
+ true);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ returnTypeClass = programField.referencedClass;
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ Clazz[] referencedClasses = programMethod.referencedClasses;
+ if (referencedClasses != null &&
+ ClassUtil.isInternalClassType(programMethod.getDescriptor(programClass)))
+ {
+ returnTypeClass = referencedClasses[referencedClasses.length - 1];
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass programClass, LibraryField programField)
+ {
+ returnTypeClass = programField.referencedClass;
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ Clazz[] referencedClasses = libraryMethod.referencedClasses;
+ if (referencedClasses != null &&
+ ClassUtil.isInternalClassType(libraryMethod.getDescriptor(libraryClass)))
+ {
+ returnTypeClass = referencedClasses[referencedClasses.length - 1];
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BranchTargetFinder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BranchTargetFinder.java
new file mode 100644
index 0000000000..4b08773a5f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BranchTargetFinder.java
@@ -0,0 +1,763 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.optimize.evaluation.PartialEvaluator;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor finds all instruction offsets, branch targets,
+ * exception offsets, and subroutine offsets in the CodeAttribute instances
+ * that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class BranchTargetFinder
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ExceptionInfoVisitor,
+ ConstantVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("btf") != null;
+ //*/
+
+ public static final int NONE = PartialEvaluator.NONE;
+
+ // We'll explicitly mark instructions that are not part of a subroutine,
+ // with NO_SUBROUTINE. Subroutines may just branch back into normal code
+ // (e.g. due to a break instruction in Java code), and we want to avoid
+ // marking such normal code as subroutine. The first mark wins, so we're
+ // assuming that such code is marked as normal code before it is marked
+ // as subroutine.
+ public static final int UNKNOWN = -1;
+ public static final int NO_SUBROUTINE = -2;
+
+ private static final short INSTRUCTION = 1 << 0;
+ private static final short BRANCH_ORIGIN = 1 << 1;
+ private static final short BRANCH_TARGET = 1 << 2;
+ private static final short AFTER_BRANCH = 1 << 3;
+ private static final short EXCEPTION_START = 1 << 4;
+ private static final short EXCEPTION_END = 1 << 5;
+ private static final short EXCEPTION_HANDLER = 1 << 6;
+ private static final short SUBROUTINE_INVOCATION = 1 << 7;
+ private static final short SUBROUTINE_RETURNING = 1 << 8;
+
+ private static final int MAXIMUM_CREATION_OFFSETS = 32;
+
+
+ private short[] instructionMarks = new short[ClassConstants.TYPICAL_CODE_LENGTH + 1];
+ private int[] subroutineStarts = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int[] subroutineEnds = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int[] creationOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int[] initializationOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int superInitializationOffset;
+ private boolean containsSubroutines;
+
+ private boolean repeat;
+ private int currentSubroutineStart;
+ private int[] recentCreationOffsets = new int[MAXIMUM_CREATION_OFFSETS];
+ private int recentCreationOffsetIndex;
+ private boolean isInitializer;
+
+
+ /**
+ * Returns whether there is an instruction at the given offset in the
+ * CodeAttribute that was visited most recently.
+ */
+ public boolean isInstruction(int offset)
+ {
+ return (instructionMarks[offset] & INSTRUCTION) != 0;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is the target of
+ * any kind in the CodeAttribute that was visited most recently.
+ */
+ public boolean isTarget(int offset)
+ {
+ return offset == 0 ||
+ (instructionMarks[offset] & (BRANCH_TARGET |
+ EXCEPTION_START |
+ EXCEPTION_END |
+ EXCEPTION_HANDLER)) != 0;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is the origin of a
+ * branch instruction in the CodeAttribute that was visited most recently.
+ */
+ public boolean isBranchOrigin(int offset)
+ {
+ return (instructionMarks[offset] & BRANCH_ORIGIN) != 0;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is the target of a
+ * branch instruction in the CodeAttribute that was visited most recently.
+ */
+ public boolean isBranchTarget(int offset)
+ {
+ return (instructionMarks[offset] & BRANCH_TARGET) != 0;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset comes right after a
+ * definite branch instruction in the CodeAttribute that was visited most
+ * recently.
+ */
+ public boolean isAfterBranch(int offset)
+ {
+ return (instructionMarks[offset] & AFTER_BRANCH) != 0;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is the start of an
+ * exception try block in the CodeAttribute that was visited most recently.
+ */
+ public boolean isExceptionStart(int offset)
+ {
+ return (instructionMarks[offset] & EXCEPTION_START) != 0;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is the end of an
+ * exception try block in the CodeAttribute that was visited most recently.
+ */
+ public boolean isExceptionEnd(int offset)
+ {
+ return (instructionMarks[offset] & EXCEPTION_END) != 0;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is the start of an
+ * exception catch block in the CodeAttribute that was visited most recently.
+ */
+ public boolean isExceptionHandler(int offset)
+ {
+ return (instructionMarks[offset] & EXCEPTION_HANDLER) != 0;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is a subroutine
+ * invocation in the CodeAttribute that was visited most recently.
+ */
+ public boolean isSubroutineInvocation(int offset)
+ {
+ return (instructionMarks[offset] & SUBROUTINE_INVOCATION) != 0;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is the start of a
+ * subroutine in the CodeAttribute that was visited most recently.
+ */
+ public boolean isSubroutineStart(int offset)
+ {
+ return subroutineStarts[offset] == offset;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is part of a
+ * subroutine in the CodeAttribute that was visited most recently.
+ */
+ public boolean isSubroutine(int offset)
+ {
+ return subroutineStarts[offset] >= 0;
+ }
+
+
+ /**
+ * Returns whether the subroutine at the given offset is ever returning
+ * by means of a regular 'ret' instruction.
+ */
+ public boolean isSubroutineReturning(int offset)
+ {
+ return (instructionMarks[offset] & SUBROUTINE_RETURNING) != 0;
+ }
+
+
+ /**
+ * Returns the start offset of the subroutine at the given offset, in the
+ * CodeAttribute that was visited most recently.
+ */
+ public int subroutineStart(int offset)
+ {
+ return subroutineStarts[offset];
+ }
+
+
+ /**
+ * Returns the offset after the subroutine at the given offset, in the
+ * CodeAttribute that was visited most recently.
+ */
+ public int subroutineEnd(int offset)
+ {
+ return subroutineEnds[offset];
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is a 'new'
+ * instruction, in the CodeAttribute that was visited most recently.
+ */
+ public boolean isNew(int offset)
+ {
+ return initializationOffsets[offset] != NONE;
+ }
+
+
+ /**
+ * Returns the instruction offset at which the object instance that is
+ * created at the given 'new' instruction offset is initialized, or
+ * <code>NONE</code> if it is not being created.
+ */
+ public int initializationOffset(int offset)
+ {
+ return initializationOffsets[offset];
+ }
+
+
+ /**
+ * Returns whether the method is an instance initializer, in the
+ * CodeAttribute that was visited most recently.
+ */
+ public boolean isInitializer()
+ {
+ return superInitializationOffset != NONE;
+ }
+
+
+ /**
+ * Returns the instruction offset at which this initializer is calling
+ * the "super" or "this" initializer method, or <code>NONE</code> if it is
+ * not an initializer.
+ */
+ public int superInitializationOffset()
+ {
+ return superInitializationOffset;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is the special
+ * invocation of an instance initializer, in the CodeAttribute that was
+ * visited most recently.
+ */
+ public boolean isInitializer(int offset)
+ {
+ return creationOffsets[offset] != NONE;
+ }
+
+
+ /**
+ * Returns the offset of the 'new' instruction that corresponds to the
+ * invocation of the instance initializer at the given offset, or
+ * <code>AT_METHOD_ENTRY</code> if the invocation is calling the "super" or
+ * "this" initializer method, , or <code>NONE</code> if it is not a 'new'
+ * instruction.
+ */
+ public int creationOffset(int offset)
+ {
+ return creationOffsets[offset];
+ }
+
+
+ /**
+ * Returns whether the method contains subroutines, in the CodeAttribute
+ * that was visited most recently.
+ */
+ public boolean containsSubroutines()
+ {
+ return containsSubroutines;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ // Make sure there are sufficiently large arrays.
+ int codeLength = codeAttribute.u4codeLength;
+ if (subroutineStarts.length < codeLength)
+ {
+ // Create new arrays.
+ instructionMarks = new short[codeLength + 1];
+ subroutineStarts = new int[codeLength];
+ subroutineEnds = new int[codeLength];
+ creationOffsets = new int[codeLength];
+ initializationOffsets = new int[codeLength];
+
+ // Reset the arrays.
+ Arrays.fill(subroutineStarts, 0, codeLength, UNKNOWN);
+ Arrays.fill(subroutineEnds, 0, codeLength, UNKNOWN);
+ Arrays.fill(creationOffsets, 0, codeLength, NONE);
+ Arrays.fill(initializationOffsets, 0, codeLength, NONE);
+ }
+ else
+ {
+ // Reset the arrays.
+ Arrays.fill(instructionMarks, 0, codeLength, (short)0);
+ Arrays.fill(subroutineStarts, 0, codeLength, UNKNOWN);
+ Arrays.fill(subroutineEnds, 0, codeLength, UNKNOWN);
+ Arrays.fill(creationOffsets, 0, codeLength, NONE);
+ Arrays.fill(initializationOffsets, 0, codeLength, NONE);
+
+ instructionMarks[codeLength] = 0;
+ }
+
+ superInitializationOffset = NONE;
+ containsSubroutines = false;
+
+ // Iterate until all subroutines have been fully marked.
+ do
+ {
+ repeat = false;
+ currentSubroutineStart = NO_SUBROUTINE;
+ recentCreationOffsetIndex = 0;
+
+ // Mark branch targets by going over all instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
+
+ // Mark branch targets in the exception table.
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ }
+ while (repeat);
+
+ // The end of the code is a branch target sentinel.
+ instructionMarks[codeLength] = BRANCH_TARGET;
+
+ if (containsSubroutines)
+ {
+ // Set the subroutine returning flag and the subroutine end at each
+ // subroutine start.
+ int previousSubroutineStart = NO_SUBROUTINE;
+
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (isInstruction(offset))
+ {
+ int subroutineStart = subroutineStarts[offset];
+
+ if (subroutineStart >= 0 &&
+ isSubroutineReturning(offset))
+ {
+ instructionMarks[subroutineStart] |= SUBROUTINE_RETURNING;
+ }
+
+ if (previousSubroutineStart >= 0)
+ {
+ subroutineEnds[previousSubroutineStart] = offset;
+ }
+
+ previousSubroutineStart = subroutineStart;
+ }
+ }
+
+ if (previousSubroutineStart >= 0)
+ {
+ subroutineEnds[previousSubroutineStart] = codeLength;
+ }
+
+ // Set the subroutine returning flag and the subroutine end at each
+ // subroutine instruction, based on the marks at the subroutine
+ // start.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (isSubroutine(offset))
+ {
+ int subroutineStart = subroutineStarts[offset];
+
+ if (isSubroutineReturning(subroutineStart))
+ {
+ instructionMarks[offset] |= SUBROUTINE_RETURNING;
+ }
+
+ subroutineEnds[offset] = subroutineEnds[subroutineStart];
+ }
+ }
+ }
+
+ if (DEBUG)
+ {
+ System.out.println();
+ System.out.println("Branch targets: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+
+ for (int index = 0; index < codeLength; index++)
+ {
+ if (isInstruction(index))
+ {
+ System.out.println("" +
+ (isBranchOrigin(index) ? 'B' : '-') +
+ (isAfterBranch(index) ? 'b' : '-') +
+ (isBranchTarget(index) ? 'T' : '-') +
+ (isExceptionStart(index) ? 'E' : '-') +
+ (isExceptionEnd(index) ? 'e' : '-') +
+ (isExceptionHandler(index) ? 'H' : '-') +
+ (isSubroutineInvocation(index) ? 'J' : '-') +
+ (isSubroutineStart(index) ? 'S' : '-') +
+ (isSubroutineReturning(index) ? 'r' : '-') +
+ (isSubroutine(index) ? " ["+subroutineStart(index)+" -> "+subroutineEnd(index)+"]" : "") +
+ (isNew(index) ? " ["+initializationOffset(index)+"] " : " ---- ") +
+ InstructionFactory.create(codeAttribute.code, index).toString(index));
+ }
+ }
+ }
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ // Mark the instruction.
+ instructionMarks[offset] |= INSTRUCTION;
+
+ // Check if this is an instruction of a subroutine.
+ checkSubroutine(offset);
+
+ byte opcode = simpleInstruction.opcode;
+ if (opcode == InstructionConstants.OP_IRETURN ||
+ opcode == InstructionConstants.OP_LRETURN ||
+ opcode == InstructionConstants.OP_FRETURN ||
+ opcode == InstructionConstants.OP_DRETURN ||
+ opcode == InstructionConstants.OP_ARETURN ||
+ opcode == InstructionConstants.OP_ATHROW)
+ {
+ // Mark the branch origin.
+ markBranchOrigin(offset);
+
+ // Mark the next instruction.
+ markAfterBranchOrigin(offset + simpleInstruction.length(offset));
+ }
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ // Mark the instruction.
+ instructionMarks[offset] |= INSTRUCTION;
+
+ // Check if this is an instruction of a subroutine.
+ checkSubroutine(offset);
+
+ byte opcode = constantInstruction.opcode;
+ if (opcode == InstructionConstants.OP_NEW)
+ {
+ // Push the 'new' instruction offset on the stack.
+ recentCreationOffsets[recentCreationOffsetIndex++] = offset;
+ }
+ else if (opcode == InstructionConstants.OP_INVOKESPECIAL)
+ {
+ // Is it calling an instance initializer?
+ isInitializer = false;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ if (isInitializer)
+ {
+ // Do we have any 'new' instruction offsets on the stack?
+ if (recentCreationOffsetIndex > 0)
+ {
+ // Pop the 'new' instruction offset from the stack.
+ int recentCreationOffset = recentCreationOffsets[--recentCreationOffsetIndex];
+
+ // Link the creation offset and the initialization offset.
+ // TODO: There could be multiple initialization offsets.
+ creationOffsets[offset] = recentCreationOffset;
+
+ initializationOffsets[recentCreationOffset] = offset;
+ }
+ else
+ {
+ // Remember the super initialization offset.
+ // TODO: There could be multiple initialization offsets.
+ // For instance, in the constructor of the generated class
+ // groovy.inspect.swingui.GeneratedBytecodeAwareGroovyClassLoader
+ // in groovy-all-2.2.1.jar.
+ superInitializationOffset = offset;
+ }
+ }
+ }
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ // Mark the instruction.
+ instructionMarks[offset] |= INSTRUCTION;
+
+ // Check if this is an instruction of a subroutine.
+ checkSubroutine(offset);
+
+ if (variableInstruction.opcode == InstructionConstants.OP_RET)
+ {
+ // Mark the method.
+ containsSubroutines = true;
+
+ // Mark the branch origin.
+ markBranchOrigin(offset);
+
+ // Mark the subroutine return at its return instruction.
+ instructionMarks[offset] |= SUBROUTINE_RETURNING;
+
+ // Mark the next instruction.
+ markAfterBranchOrigin(offset + variableInstruction.length(offset));
+ }
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ int branchOffset = branchInstruction.branchOffset;
+ int targetOffset = offset + branchOffset;
+
+ // Mark the branch origin.
+ markBranchOrigin(offset);
+
+ // Check if this is an instruction of a subroutine.
+ checkSubroutine(offset);
+
+ // Mark the branch target.
+ markBranchTarget(offset, branchOffset);
+
+ byte opcode = branchInstruction.opcode;
+ if (opcode == InstructionConstants.OP_JSR ||
+ opcode == InstructionConstants.OP_JSR_W)
+ {
+ // Mark the method.
+ containsSubroutines = true;
+
+ // Mark the subroutine invocation.
+ instructionMarks[offset] |= SUBROUTINE_INVOCATION;
+
+ // Mark the new subroutine start.
+ markBranchSubroutineStart(offset, branchOffset, targetOffset);
+ }
+ else if (currentSubroutineStart != UNKNOWN)
+ {
+ // Mark the continued subroutine start.
+ markBranchSubroutineStart(offset, branchOffset, currentSubroutineStart);
+ }
+
+ if (opcode == InstructionConstants.OP_GOTO ||
+ opcode == InstructionConstants.OP_GOTO_W)
+ {
+ // Mark the next instruction.
+ markAfterBranchOrigin(offset + branchInstruction.length(offset));
+ }
+ }
+
+
+ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ {
+ // Mark the branch origin.
+ markBranchOrigin(offset);
+
+ // Check if this is an instruction of a subroutine.
+ checkSubroutine(offset);
+
+ // Mark the branch targets of the default jump offset.
+ markBranch(offset, switchInstruction.defaultOffset);
+
+ // Mark the branch targets of the jump offsets.
+ markBranches(offset, switchInstruction.jumpOffsets);
+
+ // Mark the next instruction.
+ markAfterBranchOrigin(offset + switchInstruction.length(offset));
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ // Remember whether the method is an initializer.
+ isInitializer = methodrefConstant.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ int startPC = exceptionInfo.u2startPC;
+ int endPC = exceptionInfo.u2endPC;
+ int handlerPC = exceptionInfo.u2handlerPC;
+
+ // Mark the exception offsets.
+ instructionMarks[startPC] |= EXCEPTION_START;
+ instructionMarks[endPC] |= EXCEPTION_END;
+ instructionMarks[handlerPC] |= EXCEPTION_HANDLER;
+
+ // Mark the handler as part of a subroutine if necessary.
+ if (subroutineStarts[handlerPC] == UNKNOWN &&
+ subroutineStarts[startPC] != UNKNOWN)
+ {
+ subroutineStarts[handlerPC] = subroutineStarts[startPC];
+
+ // We'll have to go over all instructions again.
+ repeat = true;
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the branch targets and their subroutine starts at the given
+ * offsets.
+ */
+ private void markBranches(int offset, int[] jumpOffsets)
+ {
+ for (int index = 0; index < jumpOffsets.length; index++)
+ {
+ markBranch(offset, jumpOffsets[index]);
+ }
+ }
+
+
+ /**
+ * Marks the branch target and its subroutine start at the given offset.
+ */
+ private void markBranch(int offset, int jumpOffset)
+ {
+ markBranchTarget(offset, jumpOffset);
+
+ if (currentSubroutineStart != UNKNOWN)
+ {
+ markBranchSubroutineStart(offset, jumpOffset, currentSubroutineStart);
+ }
+ }
+
+ /**
+ * Marks the branch origin at the given offset.
+ */
+ private void markBranchOrigin(int offset)
+ {
+ instructionMarks[offset] |= INSTRUCTION | BRANCH_ORIGIN;
+ }
+
+
+ /**
+ * Marks the branch target at the given offset.
+ */
+ private void markBranchTarget(int offset, int jumpOffset)
+ {
+ int targetOffset = offset + jumpOffset;
+
+ instructionMarks[targetOffset] |= BRANCH_TARGET;
+ }
+
+
+ /**
+ * Marks the subroutine start at the given offset, if applicable.
+ */
+ private void markBranchSubroutineStart(int offset,
+ int jumpOffset,
+ int subroutineStart)
+ {
+ int targetOffset = offset + jumpOffset;
+
+ // Are we marking a subroutine and branching to an offset that hasn't
+ // been marked yet?
+ if (subroutineStarts[targetOffset] == UNKNOWN)
+ {
+ // Is it a backward branch?
+ if (jumpOffset < 0)
+ {
+ // Remember the smallest subroutine start.
+ if (subroutineStart > targetOffset)
+ {
+ subroutineStart = targetOffset;
+ }
+
+ // We'll have to go over all instructions again.
+ repeat = true;
+ }
+
+ // Mark the subroutine start of the target.
+ subroutineStarts[targetOffset] = subroutineStart;
+ }
+ }
+
+
+ /**
+ * Marks the instruction at the given offset, after a branch.
+ */
+ private void markAfterBranchOrigin(int nextOffset)
+ {
+ instructionMarks[nextOffset] |= AFTER_BRANCH;
+
+ // Stop marking a subroutine.
+ currentSubroutineStart = UNKNOWN;
+ }
+
+
+ /**
+ * Checks if the specified instruction is inside a subroutine.
+ */
+ private void checkSubroutine(int offset)
+ {
+ // Are we inside a previously marked subroutine?
+ if (subroutineStarts[offset] != UNKNOWN)
+ {
+ // Start marking a subroutine.
+ currentSubroutineStart = subroutineStarts[offset];
+ }
+
+ // Are we marking a subroutine?
+ else if (currentSubroutineStart != UNKNOWN)
+ {
+ // Mark the subroutine start.
+ subroutineStarts[offset] = currentSubroutineStart;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BranchUnit.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BranchUnit.java
new file mode 100644
index 0000000000..fb26fc9338
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/BranchUnit.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.CodeAttribute;
+
+/**
+ * This InstructionVisitor evaluates the instructions that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public interface BranchUnit
+{
+ /**
+ * Sets the new instruction offset.
+ */
+ public void branch(Clazz clazz,
+ CodeAttribute codeAttribute,
+ int offset,
+ int branchTarget);
+
+
+ /**
+ * Sets the new instruction offset, depending on the certainty of the
+ * conditional branch.
+ */
+ public void branchConditionally(Clazz clazz,
+ CodeAttribute codeAttribute,
+ int offset,
+ int branchTarget,
+ int conditional);
+
+
+ /**
+ * Returns from the method with the given value.
+ */
+ public void returnFromMethod();
+
+
+ /**
+ * Handles the throwing of an exception.
+ */
+ public void throwException();
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/ClassConstantValueFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/ClassConstantValueFactory.java
new file mode 100644
index 0000000000..a4e13ce2ce
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/ClassConstantValueFactory.java
@@ -0,0 +1,51 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.ClassConstant;
+import proguard.evaluation.value.ValueFactory;
+
+/**
+ * This class creates java.lang.Class ReferenceValue instances that correspond
+ * to specified constant pool entries.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassConstantValueFactory
+extends ConstantValueFactory
+{
+ public ClassConstantValueFactory(ValueFactory valueFactory)
+ {
+ super(valueFactory);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Create a Class reference instead of a reference to the class.
+ value = valueFactory.createReferenceValue(ClassConstants.NAME_JAVA_LANG_CLASS,
+ classConstant.javaLangClassClass,
+ false);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/ConstantValueFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/ConstantValueFactory.java
new file mode 100644
index 0000000000..6c6dce0b90
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/ConstantValueFactory.java
@@ -0,0 +1,113 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.evaluation.value.*;
+
+/**
+ * This class creates Value instance that correspond to specified constant pool
+ * entries.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantValueFactory
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ protected final ValueFactory valueFactory;
+
+ // Field acting as a parameter for the ConstantVisitor methods.
+ protected Value value;
+
+
+ public ConstantValueFactory(ValueFactory valueFactory)
+ {
+ this.valueFactory = valueFactory;
+ }
+
+
+ /**
+ * Returns the Value of the constant pool element at the given index.
+ */
+ public Value constantValue(Clazz clazz,
+ int constantIndex)
+ {
+ // Visit the constant pool entry to get its return value.
+ clazz.constantPoolEntryAccept(constantIndex, this);
+
+ return value;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ value = valueFactory.createIntegerValue(integerConstant.getValue());
+ }
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ value = valueFactory.createLongValue(longConstant.getValue());
+ }
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ value = valueFactory.createFloatValue(floatConstant.getValue());
+ }
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ value = valueFactory.createDoubleValue(doubleConstant.getValue());
+ }
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ value = valueFactory.createReferenceValue(ClassConstants.NAME_JAVA_LANG_STRING,
+ stringConstant.javaLangStringClass,
+ false);
+ }
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ value = valueFactory.createReferenceValue(ClassConstants.NAME_JAVA_LANG_INVOKE_METHOD_HANDLE,
+ methodHandleConstant.javaLangInvokeMethodHandleClass,
+ false);
+ }
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ value = valueFactory.createReferenceValue(classConstant.getName(clazz),
+ classConstant.referencedClass,
+ false);
+ }
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ value = valueFactory.createReferenceValue(ClassConstants.NAME_JAVA_LANG_INVOKE_METHOD_TYPE,
+ methodTypeConstant.javaLangInvokeMethodTypeClass,
+ false);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/InvocationUnit.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/InvocationUnit.java
new file mode 100644
index 0000000000..20cd92164f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/InvocationUnit.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.ConstantInstruction;
+import proguard.evaluation.value.Value;
+
+/**
+ * This interface sets up the variables for entering a method,
+ * and it updates the stack for the invocation of a class member.
+ *
+ * @author Eric Lafortune
+ */
+public interface InvocationUnit
+{
+ /**
+ * Sets up the given variables for entering the given method.
+ */
+ public void enterMethod(Clazz clazz,
+ Method method,
+ Variables variables);
+
+
+ /**
+ * Exits the given method with the given return value.
+ */
+ public void exitMethod(Clazz clazz,
+ Method method,
+ Value returnValue);
+
+
+ /**
+ * Updates the given stack corresponding to the execution of the given
+ * field or method reference instruction.
+ */
+ public void invokeMember(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int offset,
+ ConstantInstruction constantInstruction,
+ Stack stack);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Processor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Processor.java
new file mode 100644
index 0000000000..30f5322c12
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Processor.java
@@ -0,0 +1,927 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.evaluation.value.*;
+
+/**
+ * This InstructionVisitor executes the instructions that it visits on a given
+ * local variable frame and stack.
+ *
+ * @author Eric Lafortune
+ */
+public class Processor
+implements InstructionVisitor
+{
+ private final Variables variables;
+ private final Stack stack;
+ private final ValueFactory valueFactory;
+ private final BranchUnit branchUnit;
+ private final InvocationUnit invocationUnit;
+ private final boolean alwaysCast;
+
+ private final ConstantValueFactory constantValueFactory;
+ private final ClassConstantValueFactory classConstantValueFactory;
+
+
+ /**
+ * Creates a new processor that operates on the given environment.
+ * @param variables the local variable frame.
+ * @param stack the local stack.
+ * @param branchUnit the class that can affect the program counter.
+ * @param invocationUnit the class that can access other program members.
+ * @param alwaysCast a flag that specifies whether downcasts or casts
+ * of null values should always be performed.
+ */
+ public Processor(Variables variables,
+ Stack stack,
+ ValueFactory valueFactory,
+ BranchUnit branchUnit,
+ InvocationUnit invocationUnit,
+ boolean alwaysCast)
+ {
+ this.variables = variables;
+ this.stack = stack;
+ this.valueFactory = valueFactory;
+ this.branchUnit = branchUnit;
+ this.invocationUnit = invocationUnit;
+ this.alwaysCast = alwaysCast;
+
+ constantValueFactory = new ConstantValueFactory(valueFactory);
+ classConstantValueFactory = new ClassConstantValueFactory(valueFactory);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ switch (simpleInstruction.opcode)
+ {
+ case InstructionConstants.OP_NOP:
+ break;
+
+ case InstructionConstants.OP_ACONST_NULL:
+ stack.push(valueFactory.createReferenceValueNull());
+ break;
+
+ case InstructionConstants.OP_ICONST_M1:
+ case InstructionConstants.OP_ICONST_0:
+ case InstructionConstants.OP_ICONST_1:
+ case InstructionConstants.OP_ICONST_2:
+ case InstructionConstants.OP_ICONST_3:
+ case InstructionConstants.OP_ICONST_4:
+ case InstructionConstants.OP_ICONST_5:
+ case InstructionConstants.OP_BIPUSH:
+ case InstructionConstants.OP_SIPUSH:
+ stack.push(valueFactory.createIntegerValue(simpleInstruction.constant));
+ break;
+
+ case InstructionConstants.OP_LCONST_0:
+ case InstructionConstants.OP_LCONST_1:
+ stack.push(valueFactory.createLongValue(simpleInstruction.constant));
+ break;
+
+ case InstructionConstants.OP_FCONST_0:
+ case InstructionConstants.OP_FCONST_1:
+ case InstructionConstants.OP_FCONST_2:
+ stack.push(valueFactory.createFloatValue((float)simpleInstruction.constant));
+ break;
+
+ case InstructionConstants.OP_DCONST_0:
+ case InstructionConstants.OP_DCONST_1:
+ stack.push(valueFactory.createDoubleValue((double)simpleInstruction.constant));
+ break;
+
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+ {
+ IntegerValue arrayIndex = stack.ipop();
+ ReferenceValue arrayReference = stack.apop();
+ stack.push(arrayReference.integerArrayLoad(arrayIndex, valueFactory));
+ break;
+ }
+ case InstructionConstants.OP_LALOAD:
+ {
+ IntegerValue arrayIndex = stack.ipop();
+ ReferenceValue arrayReference = stack.apop();
+ stack.push(arrayReference.longArrayLoad(arrayIndex, valueFactory));
+ break;
+ }
+ case InstructionConstants.OP_FALOAD:
+ {
+ IntegerValue arrayIndex = stack.ipop();
+ ReferenceValue arrayReference = stack.apop();
+ stack.push(arrayReference.floatArrayLoad(arrayIndex, valueFactory));
+ break;
+ }
+ case InstructionConstants.OP_DALOAD:
+ {
+ IntegerValue arrayIndex = stack.ipop();
+ ReferenceValue arrayReference = stack.apop();
+ stack.push(arrayReference.doubleArrayLoad(arrayIndex, valueFactory));
+ break;
+ }
+ case InstructionConstants.OP_AALOAD:
+ {
+ IntegerValue arrayIndex = stack.ipop();
+ ReferenceValue arrayReference = stack.apop();
+ stack.push(arrayReference.referenceArrayLoad(arrayIndex, valueFactory));
+ break;
+ }
+ case InstructionConstants.OP_IASTORE:
+ case InstructionConstants.OP_BASTORE:
+ case InstructionConstants.OP_CASTORE:
+ case InstructionConstants.OP_SASTORE:
+ {
+ Value value = stack.ipop();
+ IntegerValue arrayIndex = stack.ipop();
+ ReferenceValue arrayReference = stack.apop();
+ arrayReference.arrayStore(arrayIndex, value);
+ break;
+ }
+ case InstructionConstants.OP_LASTORE:
+ {
+ Value value = stack.lpop();
+ IntegerValue arrayIndex = stack.ipop();
+ ReferenceValue arrayReference = stack.apop();
+ arrayReference.arrayStore(arrayIndex, value);
+ break;
+ }
+ case InstructionConstants.OP_FASTORE:
+ {
+ Value value = stack.fpop();
+ IntegerValue arrayIndex = stack.ipop();
+ ReferenceValue arrayReference = stack.apop();
+ arrayReference.arrayStore(arrayIndex, value);
+ break;
+ }
+ case InstructionConstants.OP_DASTORE:
+ {
+ Value value = stack.dpop();
+ IntegerValue arrayIndex = stack.ipop();
+ ReferenceValue arrayReference = stack.apop();
+ arrayReference.arrayStore(arrayIndex, value);
+ break;
+ }
+ case InstructionConstants.OP_AASTORE:
+ {
+ Value value = stack.apop();
+ IntegerValue arrayIndex = stack.ipop();
+ ReferenceValue arrayReference = stack.apop();
+ arrayReference.arrayStore(arrayIndex, value);
+ break;
+ }
+ case InstructionConstants.OP_POP:
+ stack.pop1();
+ break;
+
+ case InstructionConstants.OP_POP2:
+ stack.pop2();
+ break;
+
+ case InstructionConstants.OP_DUP:
+ stack.dup();
+ break;
+
+ case InstructionConstants.OP_DUP_X1:
+ stack.dup_x1();
+ break;
+
+ case InstructionConstants.OP_DUP_X2:
+ stack.dup_x2();
+ break;
+
+ case InstructionConstants.OP_DUP2:
+ stack.dup2();
+ break;
+
+ case InstructionConstants.OP_DUP2_X1:
+ stack.dup2_x1();
+ break;
+
+ case InstructionConstants.OP_DUP2_X2:
+ stack.dup2_x2();
+ break;
+
+ case InstructionConstants.OP_SWAP:
+ stack.swap();
+ break;
+
+ case InstructionConstants.OP_IADD:
+ stack.push(stack.ipop().add(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_LADD:
+ stack.push(stack.lpop().add(stack.lpop()));
+ break;
+
+ case InstructionConstants.OP_FADD:
+ stack.push(stack.fpop().add(stack.fpop()));
+ break;
+
+ case InstructionConstants.OP_DADD:
+ stack.push(stack.dpop().add(stack.dpop()));
+ break;
+
+ case InstructionConstants.OP_ISUB:
+ stack.push(stack.ipop().subtractFrom(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_LSUB:
+ stack.push(stack.lpop().subtractFrom(stack.lpop()));
+ break;
+
+ case InstructionConstants.OP_FSUB:
+ stack.push(stack.fpop().subtractFrom(stack.fpop()));
+ break;
+
+ case InstructionConstants.OP_DSUB:
+ stack.push(stack.dpop().subtractFrom(stack.dpop()));
+ break;
+
+ case InstructionConstants.OP_IMUL:
+ stack.push(stack.ipop().multiply(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_LMUL:
+ stack.push(stack.lpop().multiply(stack.lpop()));
+ break;
+
+ case InstructionConstants.OP_FMUL:
+ stack.push(stack.fpop().multiply(stack.fpop()));
+ break;
+
+ case InstructionConstants.OP_DMUL:
+ stack.push(stack.dpop().multiply(stack.dpop()));
+ break;
+
+ case InstructionConstants.OP_IDIV:
+ try
+ {
+ stack.push(stack.ipop().divideOf(stack.ipop()));
+ }
+ catch (ArithmeticException ex)
+ {
+ stack.push(valueFactory.createIntegerValue());
+ // TODO: Forward ArithmeticExceptions.
+ //stack.clear();
+ //stack.push(valueFactory.createReference(false));
+ //branchUnit.throwException();
+ }
+ break;
+
+ case InstructionConstants.OP_LDIV:
+ try
+ {
+ stack.push(stack.lpop().divideOf(stack.lpop()));
+ }
+ catch (ArithmeticException ex)
+ {
+ stack.push(valueFactory.createLongValue());
+ // TODO: Forward ArithmeticExceptions.
+ //stack.clear();
+ //stack.push(valueFactory.createReference(false));
+ //branchUnit.throwException();
+ }
+ break;
+
+ case InstructionConstants.OP_FDIV:
+ stack.push(stack.fpop().divideOf(stack.fpop()));
+ break;
+
+ case InstructionConstants.OP_DDIV:
+ stack.push(stack.dpop().divideOf(stack.dpop()));
+ break;
+
+ case InstructionConstants.OP_IREM:
+ try
+ {
+ stack.push(stack.ipop().remainderOf(stack.ipop()));
+ }
+ catch (ArithmeticException ex)
+ {
+ stack.push(valueFactory.createIntegerValue());
+ // TODO: Forward ArithmeticExceptions.
+ //stack.clear();
+ //stack.push(valueFactory.createReference(false));
+ //branchUnit.throwException();
+ }
+ break;
+
+ case InstructionConstants.OP_LREM:
+ try
+ {
+ stack.push(stack.lpop().remainderOf(stack.lpop()));
+ }
+ catch (ArithmeticException ex)
+ {
+ stack.push(valueFactory.createLongValue());
+ // TODO: Forward ArithmeticExceptions.
+ //stack.clear();
+ //stack.push(valueFactory.createReference(false));
+ //branchUnit.throwException();
+ }
+ break;
+
+ case InstructionConstants.OP_FREM:
+ stack.push(stack.fpop().remainderOf(stack.fpop()));
+ break;
+
+ case InstructionConstants.OP_DREM:
+ stack.push(stack.dpop().remainderOf(stack.dpop()));
+ break;
+
+ case InstructionConstants.OP_INEG:
+ stack.push(stack.ipop().negate());
+ break;
+
+ case InstructionConstants.OP_LNEG:
+ stack.push(stack.lpop().negate());
+ break;
+
+ case InstructionConstants.OP_FNEG:
+ stack.push(stack.fpop().negate());
+ break;
+
+ case InstructionConstants.OP_DNEG:
+ stack.push(stack.dpop().negate());
+ break;
+
+ case InstructionConstants.OP_ISHL:
+ stack.push(stack.ipop().shiftLeftOf(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_LSHL:
+ stack.push(stack.ipop().shiftLeftOf(stack.lpop()));
+ break;
+
+ case InstructionConstants.OP_ISHR:
+ stack.push(stack.ipop().shiftRightOf(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_LSHR:
+ stack.push(stack.ipop().shiftRightOf(stack.lpop()));
+ break;
+
+ case InstructionConstants.OP_IUSHR:
+ stack.push(stack.ipop().unsignedShiftRightOf(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_LUSHR:
+ stack.push(stack.ipop().unsignedShiftRightOf(stack.lpop()));
+ break;
+
+ case InstructionConstants.OP_IAND:
+ stack.push(stack.ipop().and(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_LAND:
+ stack.push(stack.lpop().and(stack.lpop()));
+ break;
+
+ case InstructionConstants.OP_IOR:
+ stack.push(stack.ipop().or(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_LOR:
+ stack.push(stack.lpop().or(stack.lpop()));
+ break;
+
+ case InstructionConstants.OP_IXOR:
+ stack.push(stack.ipop().xor(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_LXOR:
+ stack.push(stack.lpop().xor(stack.lpop()));
+ break;
+
+ case InstructionConstants.OP_I2L:
+ stack.push(stack.ipop().convertToLong());
+ break;
+
+ case InstructionConstants.OP_I2F:
+ stack.push(stack.ipop().convertToFloat());
+ break;
+
+ case InstructionConstants.OP_I2D:
+ stack.push(stack.ipop().convertToDouble());
+ break;
+
+ case InstructionConstants.OP_L2I:
+ stack.push(stack.lpop().convertToInteger());
+ break;
+
+ case InstructionConstants.OP_L2F:
+ stack.push(stack.lpop().convertToFloat());
+ break;
+
+ case InstructionConstants.OP_L2D:
+ stack.push(stack.lpop().convertToDouble());
+ break;
+
+ case InstructionConstants.OP_F2I:
+ stack.push(stack.fpop().convertToInteger());
+ break;
+
+ case InstructionConstants.OP_F2L:
+ stack.push(stack.fpop().convertToLong());
+ break;
+
+ case InstructionConstants.OP_F2D:
+ stack.push(stack.fpop().convertToDouble());
+ break;
+
+ case InstructionConstants.OP_D2I:
+ stack.push(stack.dpop().convertToInteger());
+ break;
+
+ case InstructionConstants.OP_D2L:
+ stack.push(stack.dpop().convertToLong());
+ break;
+
+ case InstructionConstants.OP_D2F:
+ stack.push(stack.dpop().convertToFloat());
+ break;
+
+ case InstructionConstants.OP_I2B:
+ stack.push(stack.ipop().convertToByte());
+ break;
+
+ case InstructionConstants.OP_I2C:
+ stack.push(stack.ipop().convertToCharacter());
+ break;
+
+ case InstructionConstants.OP_I2S:
+ stack.push(stack.ipop().convertToShort());
+ break;
+
+ case InstructionConstants.OP_LCMP:
+// stack.push(stack.lpop().compareReverse(stack.lpop()));
+
+ LongValue longValue1 = stack.lpop();
+ LongValue longValue2 = stack.lpop();
+ stack.push(longValue2.compare(longValue1));
+ break;
+
+ case InstructionConstants.OP_FCMPL:
+ FloatValue floatValue1 = stack.fpop();
+ FloatValue floatValue2 = stack.fpop();
+ stack.push(floatValue2.compare(floatValue1));
+ break;
+
+ case InstructionConstants.OP_FCMPG:
+ stack.push(stack.fpop().compareReverse(stack.fpop()));
+ break;
+
+ case InstructionConstants.OP_DCMPL:
+ DoubleValue doubleValue1 = stack.dpop();
+ DoubleValue doubleValue2 = stack.dpop();
+ stack.push(doubleValue2.compare(doubleValue1));
+ break;
+
+ case InstructionConstants.OP_DCMPG:
+ stack.push(stack.dpop().compareReverse(stack.dpop()));
+ break;
+
+ case InstructionConstants.OP_IRETURN:
+ invocationUnit.exitMethod(clazz, method, stack.ipop());
+ branchUnit.returnFromMethod();
+ break;
+
+ case InstructionConstants.OP_LRETURN:
+ invocationUnit.exitMethod(clazz, method, stack.lpop());
+ branchUnit.returnFromMethod();
+ break;
+
+ case InstructionConstants.OP_FRETURN:
+ invocationUnit.exitMethod(clazz, method, stack.fpop());
+ branchUnit.returnFromMethod();
+ break;
+
+ case InstructionConstants.OP_DRETURN:
+ invocationUnit.exitMethod(clazz, method, stack.dpop());
+ branchUnit.returnFromMethod();
+ break;
+
+ case InstructionConstants.OP_ARETURN:
+ invocationUnit.exitMethod(clazz, method, stack.apop());
+ branchUnit.returnFromMethod();
+ break;
+
+ case InstructionConstants.OP_RETURN:
+ branchUnit.returnFromMethod();
+ break;
+
+ case InstructionConstants.OP_NEWARRAY:
+ IntegerValue arrayLength = stack.ipop();
+ stack.push(valueFactory.createArrayReferenceValue(String.valueOf(InstructionUtil.internalTypeFromArrayType((byte)simpleInstruction.constant)),
+ null,
+ arrayLength));
+ break;
+
+ case InstructionConstants.OP_ARRAYLENGTH:
+ ReferenceValue referenceValue = stack.apop();
+ stack.push(referenceValue.arrayLength(valueFactory));
+ break;
+
+ case InstructionConstants.OP_ATHROW:
+ ReferenceValue exceptionReferenceValue = stack.apop();
+ stack.clear();
+ stack.push(exceptionReferenceValue);
+ branchUnit.throwException();
+ break;
+
+ case InstructionConstants.OP_MONITORENTER:
+ case InstructionConstants.OP_MONITOREXIT:
+ stack.apop();
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown simple instruction ["+simpleInstruction.opcode+"]");
+ }
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ int constantIndex = constantInstruction.constantIndex;
+
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_LDC:
+ case InstructionConstants.OP_LDC_W:
+ case InstructionConstants.OP_LDC2_W:
+ stack.push(classConstantValueFactory.constantValue(clazz, constantIndex));
+ break;
+
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_GETFIELD:
+ case InstructionConstants.OP_PUTFIELD:
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ invocationUnit.invokeMember(clazz, method, codeAttribute, offset, constantInstruction, stack);
+ break;
+
+ case InstructionConstants.OP_NEW:
+ stack.push(constantValueFactory.constantValue(clazz, constantIndex).referenceValue());
+ break;
+
+ case InstructionConstants.OP_ANEWARRAY:
+ {
+ ReferenceValue referenceValue = constantValueFactory.constantValue(clazz, constantIndex).referenceValue();
+
+ stack.push(valueFactory.createArrayReferenceValue(referenceValue.internalType(),
+ referenceValue.getReferencedClass(),
+ stack.ipop()));
+ break;
+ }
+
+ case InstructionConstants.OP_CHECKCAST:
+ // TODO: Check cast.
+ ReferenceValue castValue = stack.apop();
+ ReferenceValue castResultValue =
+ !alwaysCast &&
+ castValue.isNull() == Value.ALWAYS ? castValue :
+ castValue.isNull() == Value.NEVER ? constantValueFactory.constantValue(clazz, constantIndex).referenceValue() :
+ constantValueFactory.constantValue(clazz, constantIndex).referenceValue().generalize(valueFactory.createReferenceValueNull());
+ stack.push(castResultValue);
+ break;
+
+ case InstructionConstants.OP_INSTANCEOF:
+ {
+ ReferenceValue referenceValue = constantValueFactory.constantValue(clazz, constantIndex).referenceValue();
+
+ int instanceOf = stack.apop().instanceOf(referenceValue.getType(),
+ referenceValue.getReferencedClass());
+
+ stack.push(instanceOf == Value.NEVER ? valueFactory.createIntegerValue(0) :
+ instanceOf == Value.ALWAYS ? valueFactory.createIntegerValue(1) :
+ valueFactory.createIntegerValue());
+ break;
+ }
+
+ case InstructionConstants.OP_MULTIANEWARRAY:
+ {
+ int dimensionCount = constantInstruction.constant;
+ for (int dimension = 0; dimension < dimensionCount; dimension++)
+ {
+ // TODO: Use array lengths.
+ IntegerValue arrayLength = stack.ipop();
+ }
+
+ stack.push(constantValueFactory.constantValue(clazz, constantIndex).referenceValue());
+ break;
+ }
+
+ default:
+ throw new IllegalArgumentException("Unknown constant pool instruction ["+constantInstruction.opcode+"]");
+ }
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ int variableIndex = variableInstruction.variableIndex;
+
+ switch (variableInstruction.opcode)
+ {
+ case InstructionConstants.OP_ILOAD:
+ case InstructionConstants.OP_ILOAD_0:
+ case InstructionConstants.OP_ILOAD_1:
+ case InstructionConstants.OP_ILOAD_2:
+ case InstructionConstants.OP_ILOAD_3:
+ stack.push(variables.iload(variableIndex));
+ break;
+
+ case InstructionConstants.OP_LLOAD:
+ case InstructionConstants.OP_LLOAD_0:
+ case InstructionConstants.OP_LLOAD_1:
+ case InstructionConstants.OP_LLOAD_2:
+ case InstructionConstants.OP_LLOAD_3:
+ stack.push(variables.lload(variableIndex));
+ break;
+
+ case InstructionConstants.OP_FLOAD:
+ case InstructionConstants.OP_FLOAD_0:
+ case InstructionConstants.OP_FLOAD_1:
+ case InstructionConstants.OP_FLOAD_2:
+ case InstructionConstants.OP_FLOAD_3:
+ stack.push(variables.fload(variableIndex));
+ break;
+
+ case InstructionConstants.OP_DLOAD:
+ case InstructionConstants.OP_DLOAD_0:
+ case InstructionConstants.OP_DLOAD_1:
+ case InstructionConstants.OP_DLOAD_2:
+ case InstructionConstants.OP_DLOAD_3:
+ stack.push(variables.dload(variableIndex));
+ break;
+
+ case InstructionConstants.OP_ALOAD:
+ case InstructionConstants.OP_ALOAD_0:
+ case InstructionConstants.OP_ALOAD_1:
+ case InstructionConstants.OP_ALOAD_2:
+ case InstructionConstants.OP_ALOAD_3:
+ stack.push(variables.aload(variableIndex));
+ break;
+
+ case InstructionConstants.OP_ISTORE:
+ case InstructionConstants.OP_ISTORE_0:
+ case InstructionConstants.OP_ISTORE_1:
+ case InstructionConstants.OP_ISTORE_2:
+ case InstructionConstants.OP_ISTORE_3:
+ variables.store(variableIndex, stack.ipop());
+ break;
+
+ case InstructionConstants.OP_LSTORE:
+ case InstructionConstants.OP_LSTORE_0:
+ case InstructionConstants.OP_LSTORE_1:
+ case InstructionConstants.OP_LSTORE_2:
+ case InstructionConstants.OP_LSTORE_3:
+ variables.store(variableIndex, stack.lpop());
+ break;
+
+ case InstructionConstants.OP_FSTORE:
+ case InstructionConstants.OP_FSTORE_0:
+ case InstructionConstants.OP_FSTORE_1:
+ case InstructionConstants.OP_FSTORE_2:
+ case InstructionConstants.OP_FSTORE_3:
+ variables.store(variableIndex, stack.fpop());
+ break;
+
+ case InstructionConstants.OP_DSTORE:
+ case InstructionConstants.OP_DSTORE_0:
+ case InstructionConstants.OP_DSTORE_1:
+ case InstructionConstants.OP_DSTORE_2:
+ case InstructionConstants.OP_DSTORE_3:
+ variables.store(variableIndex, stack.dpop());
+ break;
+
+ case InstructionConstants.OP_ASTORE:
+ case InstructionConstants.OP_ASTORE_0:
+ case InstructionConstants.OP_ASTORE_1:
+ case InstructionConstants.OP_ASTORE_2:
+ case InstructionConstants.OP_ASTORE_3:
+ // The operand on the stack can be a reference or a return
+ // address, so we'll relax the pop operation.
+ //variables.store(variableIndex, stack.apop());
+ variables.store(variableIndex, stack.pop());
+ break;
+
+ case InstructionConstants.OP_IINC:
+ variables.store(variableIndex,
+ variables.iload(variableIndex).add(
+ valueFactory.createIntegerValue(variableInstruction.constant)));
+ break;
+
+ case InstructionConstants.OP_RET:
+ // The return address should be in the last offset of the
+ // given instruction offset variable (even though there may
+ // be other offsets).
+ InstructionOffsetValue instructionOffsetValue = variables.oload(variableIndex);
+ branchUnit.branch(clazz,
+ codeAttribute,
+ offset,
+ instructionOffsetValue.instructionOffset(instructionOffsetValue.instructionOffsetCount()-1));
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown variable instruction ["+variableInstruction.opcode+"]");
+ }
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ int branchTarget = offset + branchInstruction.branchOffset;
+
+ switch (branchInstruction.opcode)
+ {
+ case InstructionConstants.OP_IFEQ:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().equal(valueFactory.createIntegerValue(0)));
+ break;
+
+ case InstructionConstants.OP_IFNE:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().notEqual(valueFactory.createIntegerValue(0)));
+ break;
+
+ case InstructionConstants.OP_IFLT:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().lessThan(valueFactory.createIntegerValue(0)));
+ break;
+
+ case InstructionConstants.OP_IFGE:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().greaterThanOrEqual(valueFactory.createIntegerValue(0)));
+ break;
+
+ case InstructionConstants.OP_IFGT:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().greaterThan(valueFactory.createIntegerValue(0)));
+ break;
+
+ case InstructionConstants.OP_IFLE:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().lessThanOrEqual(valueFactory.createIntegerValue(0)));
+ break;
+
+
+ case InstructionConstants.OP_IFICMPEQ:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().equal(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_IFICMPNE:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().notEqual(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_IFICMPLT:
+ // Note that the stack entries are popped in reverse order.
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().greaterThan(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_IFICMPGE:
+ // Note that the stack entries are popped in reverse order.
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().lessThanOrEqual(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_IFICMPGT:
+ // Note that the stack entries are popped in reverse order.
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().lessThan(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_IFICMPLE:
+ // Note that the stack entries are popped in reverse order.
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.ipop().greaterThanOrEqual(stack.ipop()));
+ break;
+
+ case InstructionConstants.OP_IFACMPEQ:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.apop().equal(stack.apop()));
+ break;
+
+ case InstructionConstants.OP_IFACMPNE:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.apop().notEqual(stack.apop()));
+ break;
+
+ case InstructionConstants.OP_GOTO:
+ case InstructionConstants.OP_GOTO_W:
+ branchUnit.branch(clazz, codeAttribute, offset, branchTarget);
+ break;
+
+
+ case InstructionConstants.OP_JSR:
+ case InstructionConstants.OP_JSR_W:
+ stack.push(new InstructionOffsetValue(offset +
+ branchInstruction.length(offset)));
+ branchUnit.branch(clazz, codeAttribute, offset, branchTarget);
+ break;
+
+ case InstructionConstants.OP_IFNULL:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.apop().isNull());
+ break;
+
+ case InstructionConstants.OP_IFNONNULL:
+ branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
+ stack.apop().isNotNull());
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown branch instruction ["+branchInstruction.opcode+"]");
+ }
+ }
+
+
+ public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
+ {
+ IntegerValue indexValue = stack.ipop();
+
+ // If there is no definite branch in any of the cases below,
+ // branch to the default offset.
+ branchUnit.branch(clazz, codeAttribute,
+ offset,
+ offset + tableSwitchInstruction.defaultOffset);
+
+ for (int index = 0; index < tableSwitchInstruction.jumpOffsets.length; index++)
+ {
+ int conditional = indexValue.equal(valueFactory.createIntegerValue(
+ tableSwitchInstruction.lowCase + index));
+ branchUnit.branchConditionally(clazz, codeAttribute,
+ offset,
+ offset + tableSwitchInstruction.jumpOffsets[index],
+ conditional);
+
+ // If this branch is always taken, we can skip the rest.
+ if (conditional == Value.ALWAYS)
+ {
+ break;
+ }
+ }
+ }
+
+
+ public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
+ {
+ IntegerValue indexValue = stack.ipop();
+
+ // If there is no definite branch in any of the cases below,
+ // branch to the default offset.
+ branchUnit.branch(clazz, codeAttribute,
+ offset,
+ offset + lookUpSwitchInstruction.defaultOffset);
+
+ for (int index = 0; index < lookUpSwitchInstruction.jumpOffsets.length; index++)
+ {
+ int conditional = indexValue.equal(valueFactory.createIntegerValue(
+ lookUpSwitchInstruction.cases[index]));
+ branchUnit.branchConditionally(clazz, codeAttribute,
+ offset,
+ offset + lookUpSwitchInstruction.jumpOffsets[index],
+ conditional);
+
+ // If this branch is always taken, we can skip the rest.
+ if (conditional == Value.ALWAYS)
+ {
+ break;
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Stack.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Stack.java
new file mode 100644
index 0000000000..8bac0b5cf3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Stack.java
@@ -0,0 +1,560 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.evaluation.value.*;
+
+import java.util.Arrays;
+
+/**
+ * This class represents an operand stack that contains <code>Value</code>
+ * objects.
+ *
+ * @author Eric Lafortune
+ */
+public class Stack
+{
+ private static final TopValue TOP_VALUE = new TopValue();
+
+
+ protected Value[] values;
+ protected int currentSize;
+ protected int actualMaxSize;
+
+
+ /**
+ * Creates a new Stack with a given maximum size, accounting for the double
+ * space required by Category 2 values.
+ */
+ public Stack(int maxSize)
+ {
+ values = new Value[maxSize];
+ }
+
+
+ /**
+ * Creates a Stack that is a copy of the given Stack.
+ */
+ public Stack(Stack stack)
+ {
+ // Create the values array.
+ this(stack.values.length);
+
+ // Copy the stack contents.
+ copy(stack);
+ }
+
+
+ /**
+ * Returns the actual maximum stack size that was required for all stack
+ * operations, accounting for the double space required by Category 2 values.
+ */
+ public int getActualMaxSize()
+ {
+ return actualMaxSize;
+ }
+
+
+ /**
+ * Resets this Stack, so that it can be reused.
+ */
+ public void reset(int maxSize)
+ {
+ // Is the values array large enough?
+ if (values.length < maxSize)
+ {
+ // Create a new one.
+ values = new Value[maxSize];
+ }
+
+ // Clear the sizes.
+ clear();
+
+ actualMaxSize = 0;
+ }
+
+
+ /**
+ * Copies the values of the given Stack into this Stack.
+ */
+ public void copy(Stack other)
+ {
+ // Is the values array large enough?
+ if (values.length < other.values.length)
+ {
+ // Create a new one.
+ values = new Value[other.values.length];
+ }
+
+ // Copy the stack contents.
+ System.arraycopy(other.values, 0, this.values, 0, other.currentSize);
+
+ // Copy the sizes.
+ currentSize = other.currentSize;
+ actualMaxSize = other.actualMaxSize;
+ }
+
+
+ /**
+ * Generalizes the values of this Stack with the values of the given Stack.
+ * The stacks must have the same current sizes.
+ * @return whether the generalization has made any difference.
+ */
+ public boolean generalize(Stack other)
+ {
+ if (this.currentSize != other.currentSize)
+ {
+ throw new IllegalArgumentException("Stacks have different current sizes ["+this.currentSize+"] and ["+other.currentSize+"]");
+ }
+
+ boolean changed = false;
+
+ // Generalize the stack values.
+ for (int index = 0; index < currentSize; index++)
+ {
+ Value thisValue = this.values[index];
+
+ if (thisValue != null)
+ {
+ Value newValue = null;
+
+ Value otherValue = other.values[index];
+
+ if (otherValue != null)
+ {
+ newValue = thisValue.generalize(otherValue);
+ }
+
+ changed = changed || !thisValue.equals(newValue);
+
+ values[index] = newValue;
+ }
+ }
+
+ // Check if the other stack extends beyond this one.
+ if (this.actualMaxSize < other.actualMaxSize)
+ {
+ this.actualMaxSize = other.actualMaxSize;
+ }
+
+ return changed;
+ }
+
+
+ /**
+ * Clears the stack.
+ */
+ public void clear()
+ {
+ // Clear the stack contents.
+ Arrays.fill(values, 0, currentSize, null);
+
+ currentSize = 0;
+ }
+
+
+ /**
+ * Returns the number of elements currently on the stack, accounting for the
+ * double space required by Category 2 values.
+ */
+ public int size()
+ {
+ return currentSize;
+ }
+
+
+ /**
+ * Gets the specified Value from the stack, without disturbing it.
+ * @param index the index of the stack element, counting from the bottom
+ * of the stack.
+ * @return the value at the specified position.
+ */
+ public Value getBottom(int index)
+ {
+ return values[index];
+ }
+
+
+ /**
+ * Sets the specified Value on the stack, without disturbing it.
+ * @param index the index of the stack element, counting from the bottom
+ * of the stack.
+ * @param value the value to set.
+ */
+ public void setBottom(int index, Value value)
+ {
+ values[index] = value;
+ }
+
+
+ /**
+ * Gets the specified Value from the stack, without disturbing it.
+ * @param index the index of the stack element, counting from the top
+ * of the stack.
+ * @return the value at the specified position.
+ */
+ public Value getTop(int index)
+ {
+ return values[currentSize - index - 1];
+ }
+
+
+ /**
+ * Sets the specified Value on the stack, without disturbing it.
+ * @param index the index of the stack element, counting from the top
+ * of the stack.
+ * @param value the value to set.
+ */
+ public void setTop(int index, Value value)
+ {
+ values[currentSize - index - 1] = value;
+ }
+
+
+ /**
+ * Removes the specified Value from the stack.
+ * @param index the index of the stack element, counting from the top
+ * of the stack.
+ */
+ public void removeTop(int index)
+ {
+ System.arraycopy(values, currentSize - index,
+ values, currentSize - index - 1,
+ index);
+ currentSize--;
+ }
+
+
+ /**
+ * Pushes the given Value onto the stack.
+ */
+ public void push(Value value)
+ {
+ // Account for the extra space required by Category 2 values.
+ if (value.isCategory2())
+ {
+ values[currentSize++] = TOP_VALUE;
+ }
+
+ // Push the value.
+ values[currentSize++] = value;
+
+ // Update the maximum actual size;
+ if (actualMaxSize < currentSize)
+ {
+ actualMaxSize = currentSize;
+ }
+ }
+
+
+ /**
+ * Pops the top Value from the stack.
+ */
+ public Value pop()
+ {
+ Value value = values[--currentSize];
+
+ values[currentSize] = null;
+
+ // Account for the extra space required by Category 2 values.
+ if (value.isCategory2())
+ {
+ values[--currentSize] = null;
+ }
+
+ return value;
+ }
+
+
+ // Pop methods that provide convenient casts to the expected value types.
+
+ /**
+ * Pops the top IntegerValue from the stack.
+ */
+ public IntegerValue ipop()
+ {
+ return pop().integerValue();
+ }
+
+
+ /**
+ * Pops the top LongValue from the stack.
+ */
+ public LongValue lpop()
+ {
+ return pop().longValue();
+ }
+
+
+ /**
+ * Pops the top FloatValue from the stack.
+ */
+ public FloatValue fpop()
+ {
+ return pop().floatValue();
+ }
+
+
+ /**
+ * Pops the top DoubleValue from the stack.
+ */
+ public DoubleValue dpop()
+ {
+ return pop().doubleValue();
+ }
+
+
+ /**
+ * Pops the top ReferenceValue from the stack.
+ */
+ public ReferenceValue apop()
+ {
+ return pop().referenceValue();
+ }
+
+
+ /**
+ * Pops the top InstructionOffsetValue from the stack.
+ */
+ public InstructionOffsetValue opop()
+ {
+ return pop().instructionOffsetValue();
+ }
+
+
+ /**
+ * Pops the top category 1 value from the stack.
+ */
+ public void pop1()
+ {
+ values[--currentSize] = null;
+ }
+
+
+ /**
+ * Pops the top category 2 value from the stack (or alternatively, two
+ * Category 1 stack elements).
+ */
+ public void pop2()
+ {
+ values[--currentSize] = null;
+ values[--currentSize] = null;
+ }
+
+
+ /**
+ * Duplicates the top Category 1 value.
+ */
+ public void dup()
+ {
+ values[currentSize] = values[currentSize - 1].category1Value();
+
+ currentSize++;
+
+ // Update the maximum actual size;
+ if (actualMaxSize < currentSize)
+ {
+ actualMaxSize = currentSize;
+ }
+ }
+
+
+ /**
+ * Duplicates the top Category 1 value, one Category 1 element down the
+ * stack.
+ */
+ public void dup_x1()
+ {
+ values[currentSize] = values[currentSize - 1].category1Value();
+ values[currentSize - 1] = values[currentSize - 2].category1Value();
+ values[currentSize - 2] = values[currentSize ];
+
+ currentSize++;
+
+ // Update the maximum actual size;
+ if (actualMaxSize < currentSize)
+ {
+ actualMaxSize = currentSize;
+ }
+ }
+
+
+ /**
+ * Duplicates the top Category 1 value, two Category 1 elements (or one
+ * Category 2 element) down the stack.
+ */
+ public void dup_x2()
+ {
+ values[currentSize] = values[currentSize - 1].category1Value();
+ values[currentSize - 1] = values[currentSize - 2];
+ values[currentSize - 2] = values[currentSize - 3];
+ values[currentSize - 3] = values[currentSize ];
+
+ currentSize++;
+
+ // Update the maximum actual size;
+ if (actualMaxSize < currentSize)
+ {
+ actualMaxSize = currentSize;
+ }
+ }
+
+ /**
+ * Duplicates the top Category 2 value (or alternatively, the equivalent
+ * Category 1 stack elements).
+ */
+ public void dup2()
+ {
+ values[currentSize ] = values[currentSize - 2];
+ values[currentSize + 1] = values[currentSize - 1];
+
+ currentSize += 2;
+
+ // Update the maximum actual size;
+ if (actualMaxSize < currentSize)
+ {
+ actualMaxSize = currentSize;
+ }
+ }
+
+
+ /**
+ * Duplicates the top Category 2 value, one Category 1 element down the
+ * stack (or alternatively, the equivalent Category 1 stack values).
+ */
+ public void dup2_x1()
+ {
+ values[currentSize + 1] = values[currentSize - 1];
+ values[currentSize ] = values[currentSize - 2];
+ values[currentSize - 1] = values[currentSize - 3];
+ values[currentSize - 2] = values[currentSize + 1];
+ values[currentSize - 3] = values[currentSize ];
+
+ currentSize += 2;
+
+ // Update the maximum actual size;
+ if (actualMaxSize < currentSize)
+ {
+ actualMaxSize = currentSize;
+ }
+ }
+
+
+ /**
+ * Duplicates the top Category 2 value, one Category 2 stack element down
+ * the stack (or alternatively, the equivalent Category 1 stack values).
+ */
+ public void dup2_x2()
+ {
+ values[currentSize + 1] = values[currentSize - 1];
+ values[currentSize ] = values[currentSize - 2];
+ values[currentSize - 1] = values[currentSize - 3];
+ values[currentSize - 2] = values[currentSize - 4];
+ values[currentSize - 3] = values[currentSize + 1];
+ values[currentSize - 4] = values[currentSize ];
+
+ currentSize += 2;
+
+ // Update the maximum actual size;
+ if (actualMaxSize < currentSize)
+ {
+ actualMaxSize = currentSize;
+ }
+ }
+
+
+ /**
+ * Swaps the top two Category 1 values.
+ */
+ public void swap()
+ {
+ Value value1 = values[currentSize - 1].category1Value();
+ Value value2 = values[currentSize - 2].category1Value();
+
+ values[currentSize - 1] = value2;
+ values[currentSize - 2] = value1;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (object == null ||
+ this.getClass() != object.getClass())
+ {
+ return false;
+ }
+
+ Stack other = (Stack)object;
+
+ if (this.currentSize != other.currentSize)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < currentSize; index++)
+ {
+ Value thisValue = this.values[index];
+ Value otherValue = other.values[index];
+ if (thisValue == null ? otherValue != null :
+ !thisValue.equals(otherValue))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ public int hashCode()
+ {
+ int hashCode = currentSize;
+
+ for (int index = 0; index < currentSize; index++)
+ {
+ Value value = values[index];
+ if (value != null)
+ {
+ hashCode ^= value.hashCode();
+ }
+ }
+
+ return hashCode;
+ }
+
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ for (int index = 0; index < currentSize; index++)
+ {
+ Value value = values[index];
+ buffer = buffer.append('[')
+ .append(value == null ? "empty" : value.toString())
+ .append(']');
+ }
+
+ return buffer.toString();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/TracedStack.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/TracedStack.java
new file mode 100644
index 0000000000..4d76747f02
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/TracedStack.java
@@ -0,0 +1,374 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.evaluation.value.Value;
+
+/**
+ * This Stack saves additional information with stack elements, to keep track
+ * of their origins.
+ * <p>
+ * The stack stores a given producer Value along with each Value it stores.
+ * It then generalizes a given collected Value with the producer Value
+ * of each Value it loads. The producer Value and the initial collected Value
+ * can be set. The generalized collected Value can be retrieved, either taking
+ * into account dup/swap instructions as proper instructions or ignoring them.
+ *
+ * @author Eric Lafortune
+ */
+public class TracedStack extends Stack
+{
+ private Value producerValue;
+ private Stack producerStack;
+ private Stack actualProducerStack;
+
+
+ /**
+ * Creates a new TracedStack with a given maximum size.
+ */
+ public TracedStack(int maxSize)
+ {
+ super(maxSize);
+
+ producerStack = new Stack(maxSize);
+ actualProducerStack = new Stack(maxSize);
+ }
+
+
+ /**
+ * Creates a new TracedStack that is a copy of the given TracedStack.
+ */
+ public TracedStack(TracedStack tracedStack)
+ {
+ super(tracedStack);
+
+ producerStack = new Stack(tracedStack.producerStack);
+ actualProducerStack = new Stack(tracedStack.actualProducerStack);
+ }
+
+
+ /**
+ * Sets the Value that will be stored along with all push and pop
+ * instructions.
+ */
+ public void setProducerValue(Value producerValue)
+ {
+ this.producerValue = producerValue;
+ }
+
+
+ /**
+ * Gets the specified producer Value from the stack, without disturbing it.
+ * @param index the index of the stack element, counting from the bottom
+ * of the stack.
+ * @return the producer value at the specified position.
+ */
+ public Value getBottomProducerValue(int index)
+ {
+ return producerStack.getBottom(index);
+ }
+
+
+ /**
+ * Gets the specified actual producer Value from the stack, ignoring
+ * dup/swap instructions, without disturbing it.
+ * @param index the index of the stack element, counting from the bottom
+ * of the stack.
+ * @return the producer value at the specified position.
+ */
+ public Value getBottomActualProducerValue(int index)
+ {
+ return actualProducerStack.getBottom(index);
+ }
+
+
+ /**
+ * Gets the specified producer Value from the stack, without disturbing it.
+ * @param index the index of the stack element, counting from the top
+ * of the stack.
+ * @return the producer value at the specified position.
+ */
+ public Value getTopProducerValue(int index)
+ {
+ return producerStack.getTop(index);
+ }
+
+
+ /**
+ * Gets the specified actual producer Value from the stack, ignoring
+ * dup/swap instructions, without disturbing it.
+ * @param index the index of the stack element, counting from the top
+ * of the stack.
+ * @return the producer value at the specified position.
+ */
+ public Value getTopActualProducerValue(int index)
+ {
+ return actualProducerStack.getTop(index);
+ }
+
+
+ // Implementations for Stack.
+
+ public void reset(int size)
+ {
+ super.reset(size);
+
+ producerStack.reset(size);
+ actualProducerStack.reset(size);
+ }
+
+ public void copy(TracedStack other)
+ {
+ super.copy(other);
+
+ producerStack.copy(other.producerStack);
+ actualProducerStack.copy(other.actualProducerStack);
+ }
+
+ public boolean generalize(TracedStack other)
+ {
+ return
+ super.generalize(other) |
+ producerStack.generalize(other.producerStack) |
+ actualProducerStack.generalize(other.actualProducerStack);
+ }
+
+ public void clear()
+ {
+ super.clear();
+
+ producerStack.clear();
+ actualProducerStack.clear();
+ }
+
+ public void removeTop(int index)
+ {
+ super.removeTop(index);
+
+ producerStack.removeTop(index);
+ actualProducerStack.removeTop(index);
+ }
+
+ public void push(Value value)
+ {
+ super.push(value);
+
+ producerPush();
+
+ // Account for the extra space required by Category 2 values.
+ if (value.isCategory2())
+ {
+ producerPush();
+ }
+ }
+
+ public Value pop()
+ {
+ Value value = super.pop();
+
+ producerPop();
+
+ // Account for the extra space required by Category 2 values.
+ if (value.isCategory2())
+ {
+ producerPop();
+ }
+
+ return value;
+ }
+
+ public void pop1()
+ {
+ super.pop1();
+
+ producerPop();
+ }
+
+ public void pop2()
+ {
+ super.pop2();
+
+ producerPop();
+ producerPop();
+ }
+
+ public void dup()
+ {
+ super.dup();
+
+ producerStack.pop();
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+
+ actualProducerStack.dup();
+ }
+
+ public void dup_x1()
+ {
+ super.dup_x1();
+
+ producerStack.pop();
+ producerStack.pop();
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+
+ actualProducerStack.dup_x1();
+ }
+
+ public void dup_x2()
+ {
+ super.dup_x2();
+
+ producerStack.pop();
+ producerStack.pop();
+ producerStack.pop();
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+
+ actualProducerStack.dup_x2();
+ }
+
+ public void dup2()
+ {
+ super.dup2();
+
+ producerStack.pop();
+ producerStack.pop();
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+
+ actualProducerStack.dup2();
+ }
+
+ public void dup2_x1()
+ {
+ super.dup2_x1();
+
+ producerStack.pop();
+ producerStack.pop();
+ producerStack.pop();
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+
+ actualProducerStack.dup2_x1();
+ }
+
+ public void dup2_x2()
+ {
+ super.dup2_x2();
+
+ producerStack.pop();
+ producerStack.pop();
+ producerStack.pop();
+ producerStack.pop();
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+
+ actualProducerStack.dup2_x2();
+ }
+
+ public void swap()
+ {
+ super.swap();
+
+ producerStack.pop();
+ producerStack.pop();
+ producerStack.push(producerValue);
+ producerStack.push(producerValue);
+
+ actualProducerStack.swap();
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (object == null ||
+ this.getClass() != object.getClass())
+ {
+ return false;
+ }
+
+ TracedStack other = (TracedStack)object;
+
+ return super.equals(object) &&
+ this.producerStack.equals(other.producerStack) &&
+ this.actualProducerStack.equals(other.actualProducerStack);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ producerStack.hashCode() ^
+ actualProducerStack.hashCode();
+ }
+
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ for (int index = 0; index < this.size(); index++)
+ {
+ Value value = this.values[index];
+ Value producerValue = producerStack.getBottom(index);
+ Value actualProducerValue = actualProducerStack.getBottom(index);
+ buffer = buffer.append('[')
+ .append(producerValue == null ? "empty:" :
+ producerValue.equals(actualProducerValue) ? producerValue.toString() :
+ producerValue.toString() + actualProducerValue.toString())
+ .append(value == null ? "empty" : value.toString())
+ .append(']');
+ }
+
+ return buffer.toString();
+ }
+
+
+ // Small utility methods.
+
+ private void producerPush()
+ {
+ producerStack.push(producerValue);
+ actualProducerStack.push(producerValue);
+ }
+
+
+ private void producerPop()
+ {
+ producerStack.pop();
+ actualProducerStack.pop();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/TracedVariables.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/TracedVariables.java
new file mode 100644
index 0000000000..da2deb8e7d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/TracedVariables.java
@@ -0,0 +1,199 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.evaluation.value.Value;
+
+/**
+ * This Variables class saves additional information with variables, to keep
+ * track of their origins.
+ * <p>
+ * The Variables class stores a given producer Value along with each Value it
+ * stores. It then generalizes a given collected Value with the producer Value
+ * of each Value it loads. The producer Value and the initial collected Value
+ * can be set; the generalized collected Value can be retrieved.
+ *
+ * @author Eric Lafortune
+ */
+public class TracedVariables extends Variables
+{
+ public static final int NONE = -1;
+
+
+ private Value producerValue;
+ private Variables producerVariables;
+
+
+ /**
+ * Creates a new TracedVariables with a given size.
+ */
+ public TracedVariables(int size)
+ {
+ super(size);
+
+ producerVariables = new Variables(size);
+ }
+
+
+ /**
+ * Creates a new TracedVariables that is a copy of the given TracedVariables.
+ */
+ public TracedVariables(TracedVariables tracedVariables)
+ {
+ super(tracedVariables);
+
+ producerVariables = new Variables(tracedVariables.producerVariables);
+ }
+
+
+ /**
+ * Sets the Value that will be stored along with all store instructions.
+ */
+ public void setProducerValue(Value producerValue)
+ {
+ this.producerValue = producerValue;
+ }
+
+
+ /**
+ * Gets the producer Value for the specified variable, without disturbing it.
+ * @param index the variable index.
+ * @return the producer value of the given variable.
+ */
+ public Value getProducerValue(int index)
+ {
+ return producerVariables.getValue(index);
+ }
+
+
+ /**
+ * Sets the given producer Value for the specified variable, without
+ * disturbing it.
+ * @param index the variable index.
+ * @param value the producer value to set.
+ */
+ public void setProducerValue(int index, Value value)
+ {
+ producerVariables.store(index, value);
+ }
+
+
+ // Implementations for Variables.
+
+ public void reset(int size)
+ {
+ super.reset(size);
+
+ producerVariables.reset(size);
+ }
+
+ public void initialize(TracedVariables other)
+ {
+ super.initialize(other);
+
+ producerVariables.initialize(other.producerVariables);
+ }
+
+ public boolean generalize(TracedVariables other,
+ boolean clearConflictingOtherVariables)
+ {
+ boolean variablesChanged = super.generalize(other, clearConflictingOtherVariables);
+ boolean producersChanged = producerVariables.generalize(other.producerVariables, clearConflictingOtherVariables);
+ /* consumerVariables.generalize(other.consumerVariables)*/
+
+ // Clear any traces if a variable has become null.
+ if (variablesChanged)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (values[index] == null)
+ {
+ producerVariables.values[index] = null;
+
+ if (clearConflictingOtherVariables)
+ {
+ other.producerVariables.values[index] = null;
+ }
+ }
+ }
+ }
+
+ return variablesChanged || producersChanged;
+ }
+
+
+ public void store(int index, Value value)
+ {
+ // Store the value itself in the variable.
+ super.store(index, value);
+
+ // Store the producer value in its producer variable.
+ producerVariables.store(index, producerValue);
+
+ // Account for the extra space required by Category 2 values.
+ if (value.isCategory2())
+ {
+ producerVariables.store(index+1, producerValue);
+ }
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (object == null ||
+ this.getClass() != object.getClass())
+ {
+ return false;
+ }
+
+ TracedVariables other = (TracedVariables)object;
+
+ return super.equals(object) &&
+ this.producerVariables.equals(other.producerVariables);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ producerVariables.hashCode();
+ }
+
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ for (int index = 0; index < this.size(); index++)
+ {
+ Value value = this.values[index];
+ Value producerValue = producerVariables.getValue(index);
+ buffer = buffer.append('[')
+ .append(producerValue == null ? "empty:" : producerValue.toString())
+ .append(value == null ? "empty" : value.toString())
+ .append(']');
+ }
+
+ return buffer.toString();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Variables.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Variables.java
new file mode 100644
index 0000000000..d61364a793
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/Variables.java
@@ -0,0 +1,347 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation;
+
+import proguard.evaluation.value.*;
+
+import java.util.Arrays;
+
+/**
+ * This class represents a local variable frame that contains <code>Value</code>
+ * objects. Values are generalizations of all values that have been stored in
+ * the respective variables.
+ *
+ * @author Eric Lafortune
+ */
+public class Variables
+{
+ private static final TopValue TOP_VALUE = new TopValue();
+
+
+ protected Value[] values;
+ protected int size;
+
+
+ /**
+ * Creates a new Variables object with a given maximum number of variables.
+ */
+ public Variables(int size)
+ {
+ this.values = new Value[size];
+ this.size = size;
+ }
+
+
+ /**
+ * Creates a Variables object that is a copy of the given Variables object.
+ */
+ public Variables(Variables variables)
+ {
+ // Create the values array.
+ this(variables.size);
+
+ // Copy the values.
+ initialize(variables);
+ }
+
+
+ /**
+ * Resets this Variables object, so that it can be reused.
+ */
+ public void reset(int size)
+ {
+ // Is the values array large enough?
+ if (values.length < size)
+ {
+ // Create a new one.
+ values = new Value[size];
+ }
+ else
+ {
+ // Clear the old variables.
+ Arrays.fill(values, 0, this.size, null);
+ }
+
+ this.size = size;
+ }
+
+
+ /**
+ * Initializes the values of this Variables object with the values of the
+ * given Variables object. The other object may have fewer values, in which
+ * case the remaining values are left unchanged.
+ */
+ public void initialize(Variables other)
+ {
+ if (this.size < other.size)
+ {
+ throw new IllegalArgumentException("Variable frame is too small ["+this.size+"] compared to other frame ["+other.size+"]");
+ }
+
+ // Copy the values.
+ System.arraycopy(other.values, 0, this.values, 0, other.size);
+ }
+
+
+ /**
+ * Generalizes the values of this Variables object with the values of the
+ * given Variables object.
+ * @param clearConflictingOtherVariables specifies whether the other
+ * variables should be cleared too,
+ * in case of conflicts.
+ * @return whether the generalization has made any difference.
+ */
+ public boolean generalize(Variables other,
+ boolean clearConflictingOtherVariables)
+ {
+ if (this.size != other.size)
+ {
+ throw new IllegalArgumentException("Variable frames have different sizes ["+this.size+"] and ["+other.size+"]");
+ }
+
+ boolean changed = false;
+
+ for (int index = 0; index < size; index++)
+ {
+ Value thisValue = this.values[index];
+ Value otherValue = other.values[index];
+
+ // Occasionally, two values of different types might be present
+ // in the same variable in a variable frame (corresponding to
+ // two local variables that share the same index), at some point
+ // outside of their scopes. Don't generalize the variable then,
+ // but let it clear instead.
+ if (thisValue != null &&
+ otherValue != null &&
+ thisValue.computationalType() == otherValue.computationalType())
+ {
+ Value newValue = thisValue.generalize(otherValue);
+
+ changed = changed || !thisValue.equals(newValue);
+
+ this.values[index] = newValue;
+ }
+ else
+ {
+ changed = changed || thisValue != null;
+
+ this.values[index] = null;
+
+ if (clearConflictingOtherVariables)
+ {
+ other.values[index] = null;
+ }
+ }
+ }
+
+ return changed;
+ }
+
+
+ /**
+ * Returns the number of variables.
+ */
+ public int size()
+ {
+ return size;
+ }
+
+
+ /**
+ * Gets the Value of the variable with the given index, without disturbing it.
+ */
+ public Value getValue(int index)
+ {
+ if (index < 0 ||
+ index >= size)
+ {
+ throw new IndexOutOfBoundsException("Variable index ["+index+"] out of bounds ["+size+"]");
+ }
+
+ return values[index];
+ }
+
+
+ /**
+ * Stores the given Value at the given variable index.
+ */
+ public void store(int index, Value value)
+ {
+ if (index < 0 ||
+ index >= size)
+ {
+ throw new IndexOutOfBoundsException("Variable index ["+index+"] out of bounds ["+size+"]");
+ }
+
+ // Store the value.
+ values[index] = value;
+
+ // Account for the extra space required by Category 2 values.
+ if (value.isCategory2())
+ {
+ values[index + 1] = TOP_VALUE;
+ }
+ }
+
+
+ /**
+ * Loads the Value from the variable with the given index.
+ */
+ public Value load(int index)
+ {
+ if (index < 0 ||
+ index >= size)
+ {
+ throw new IndexOutOfBoundsException("Variable index ["+index+"] out of bounds ["+size+"]");
+ }
+
+ return values[index];
+ }
+
+
+ // Load methods that provide convenient casts to the expected value types.
+
+ /**
+ * Loads the IntegerValue from the variable with the given index.
+ */
+ public IntegerValue iload(int index)
+ {
+ return load(index).integerValue();
+ }
+
+
+ /**
+ * Loads the LongValue from the variable with the given index.
+ */
+ public LongValue lload(int index)
+ {
+ return load(index).longValue();
+ }
+
+
+ /**
+ * Loads the FloatValue from the variable with the given index.
+ */
+ public FloatValue fload(int index)
+ {
+ return load(index).floatValue();
+ }
+
+
+ /**
+ * Loads the DoubleValue from the variable with the given index.
+ */
+ public DoubleValue dload(int index)
+ {
+ return load(index).doubleValue();
+ }
+
+
+ /**
+ * Loads the ReferenceValue from the variable with the given index.
+ */
+ public ReferenceValue aload(int index)
+ {
+ return load(index).referenceValue();
+ }
+
+
+ /**
+ * Loads the InstructionOffsetValue from the variable with the given index.
+ */
+ public InstructionOffsetValue oload(int index)
+ {
+ return load(index).instructionOffsetValue();
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (object == null ||
+ this.getClass() != object.getClass())
+ {
+ return false;
+ }
+
+ Variables other = (Variables)object;
+
+ if (this.size != other.size)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < size; index++)
+ {
+ Value thisValue = this.values[index];
+ Value otherValue = other.values[index];
+
+ // Occasionally, two values of different types might be
+ // present in the same variable in a variable frame
+ // (corresponding to two local variables that share the
+ // same index), at some point outside of their scopes.
+ // We'll ignore these.
+ if (thisValue != null &&
+ otherValue != null &&
+ thisValue.computationalType() == otherValue.computationalType() &&
+ !thisValue.equals(otherValue))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ public int hashCode()
+ {
+ int hashCode = size;
+
+ for (int index = 0; index < size; index++)
+ {
+ Value value = values[index];
+ if (value != null)
+ {
+ hashCode ^= value.hashCode();
+ }
+ }
+
+ return hashCode;
+ }
+
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ for (int index = 0; index < size; index++)
+ {
+ Value value = values[index];
+ buffer = buffer.append('[')
+ .append(value == null ? "empty" : value.toString())
+ .append(']');
+ }
+
+ return buffer.toString();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ArrayReferenceValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ArrayReferenceValue.java
new file mode 100644
index 0000000000..822d006fde
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ArrayReferenceValue.java
@@ -0,0 +1,165 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.Clazz;
+
+/**
+ * This ReferenceValue represents a partially evaluated array. It has an array
+ * length and possibly array values (up to a fixed maximum number). It is not
+ * immutable.
+ *
+ * @author Eric Lafortune
+ */
+class ArrayReferenceValue extends TypedReferenceValue
+{
+ protected final IntegerValue arrayLength;
+
+
+ /**
+ * Creates a new ArrayReferenceValue.
+ */
+ public ArrayReferenceValue(String type,
+ Clazz referencedClass,
+ IntegerValue arrayLength)
+ {
+ super(type, referencedClass, false);
+
+ this.arrayLength = arrayLength;
+ }
+
+
+ // Implementations for ReferenceValue.
+
+ public IntegerValue arrayLength(ValueFactory valueFactory)
+ {
+ return arrayLength;
+ }
+
+
+ // Implementations of binary methods of ReferenceValue.
+
+ public ReferenceValue generalize(ReferenceValue other)
+ {
+ return other.generalize(this);
+ }
+
+
+ public int equal(ReferenceValue other)
+ {
+ return other.equal(this);
+ }
+
+
+// // Implementations of binary ReferenceValue methods with
+// // IdentifiedReferenceValue arguments.
+//
+// public ReferenceValue generalize(IdentifiedReferenceValue other)
+// {
+// return generalize((TypedReferenceValue)other);
+// }
+//
+//
+// public int equal(IdentifiedReferenceValue other)
+// {
+// return equal((TypedReferenceValue)other);
+// }
+
+
+ // Implementations of binary ReferenceValue methods with
+ // ArrayReferenceValue arguments.
+
+ public ReferenceValue generalize(ArrayReferenceValue other)
+ {
+ return
+ this.equals(other) ? this :
+ this.type != null &&
+ this.type.equals(other.type) &&
+ this.referencedClass == other.referencedClass ? new ArrayReferenceValue(this.type,
+ this.referencedClass,
+ this.arrayLength.generalize(other.arrayLength)) :
+ generalize((TypedReferenceValue)other);
+ }
+
+
+ public int equal(ArrayReferenceValue other)
+ {
+ if (this.arrayLength.equal(other.arrayLength) == NEVER)
+ {
+ return NEVER;
+ }
+
+ return equal((TypedReferenceValue)other);
+ }
+
+
+// // Implementations of binary ReferenceValue methods with
+// // IdentifiedArrayReferenceValue arguments.
+//
+// public ReferenceValue generalize(IdentifiedArrayReferenceValue other)
+// {
+// return generalize((ArrayReferenceValue)other);
+// }
+//
+//
+// public int equal(IdentifiedArrayReferenceValue other)
+// {
+// return equal((ArrayReferenceValue)other);
+// }
+//
+//
+// // Implementations of binary ReferenceValue methods with
+// // DetailedArrayReferenceValue arguments.
+//
+// public ReferenceValue generalize(DetailedArrayReferenceValue other)
+// {
+// return generalize((IdentifiedArrayReferenceValue)other);
+// }
+//
+//
+// public int equal(DetailedArrayReferenceValue other)
+// {
+// return equal((IdentifiedArrayReferenceValue)other);
+// }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.arrayLength.equals(((ArrayReferenceValue)object).arrayLength);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ arrayLength.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return super.toString() + '['+arrayLength+']';
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Category1Value.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Category1Value.java
new file mode 100644
index 0000000000..a9b8a53083
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Category1Value.java
@@ -0,0 +1,41 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This abstract class represents a partially evaluated Category 1 value.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class Category1Value extends Value
+{
+ // Implementations for Value.
+
+ public final Category1Value category1Value()
+ {
+ return this;
+ }
+
+ public final boolean isCategory2()
+ {
+ return false;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Category2Value.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Category2Value.java
new file mode 100644
index 0000000000..8229207c1f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Category2Value.java
@@ -0,0 +1,41 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This abstract class represents a partially evaluated Category 2 value.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class Category2Value extends Value
+{
+ // Implementations for Value.
+
+ public final Category2Value category2Value()
+ {
+ return this;
+ }
+
+ public final boolean isCategory2()
+ {
+ return true;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ComparisonValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ComparisonValue.java
new file mode 100644
index 0000000000..d52d2709a8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ComparisonValue.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This IntegerValue represents the result of a comparisons of two scalar
+ * values.
+ *
+ * @author Eric Lafortune
+ */
+final class ComparisonValue extends SpecificIntegerValue
+{
+ private final Value value1;
+ private final Value value2;
+
+
+ /**
+ * Creates a new comparison integer value of the two given scalar values.
+ */
+ public ComparisonValue(Value value1,
+ Value value2)
+ {
+ this.value1 = value1;
+ this.value2 = value2;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.value1.equals(((ComparisonValue)object).value1) &&
+ this.value2.equals(((ComparisonValue)object).value2);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ value1.hashCode() ^
+ value2.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "("+value1+"~"+ value2 +")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeDoubleValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeDoubleValue.java
new file mode 100644
index 0000000000..f060f2d651
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeDoubleValue.java
@@ -0,0 +1,81 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This DoubleValue represents the result of a binary operation on two double
+ * values.
+ *
+ * @author Eric Lafortune
+ */
+final class CompositeDoubleValue extends SpecificDoubleValue
+{
+ public static final byte ADD = '+';
+ public static final byte SUBTRACT = '-';
+ public static final byte MULTIPLY = '*';
+ public static final byte DIVIDE = '/';
+ public static final byte REMAINDER = '%';
+
+
+ private final DoubleValue doubleValue1;
+ private final byte operation;
+ private final DoubleValue doubleValue2;
+
+
+ /**
+ * Creates a new composite double value of the two given double values
+ * and the given operation.
+ */
+ public CompositeDoubleValue(DoubleValue doubleValue1,
+ byte operation,
+ DoubleValue doubleValue2)
+ {
+ this.doubleValue1 = doubleValue1;
+ this.operation = operation;
+ this.doubleValue2 = doubleValue2;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.doubleValue1.equals(((CompositeDoubleValue)object).doubleValue1) &&
+ this.operation == ((CompositeDoubleValue)object).operation &&
+ this.doubleValue2.equals(((CompositeDoubleValue)object).doubleValue2);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ doubleValue1.hashCode() ^
+ doubleValue2.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "("+doubleValue1+((char)operation)+doubleValue2+")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeFloatValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeFloatValue.java
new file mode 100644
index 0000000000..88e62617db
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeFloatValue.java
@@ -0,0 +1,81 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This FloatValue represents the result of a binary operation on two float
+ * values.
+ *
+ * @author Eric Lafortune
+ */
+final class CompositeFloatValue extends SpecificFloatValue
+{
+ public static final byte ADD = '+';
+ public static final byte SUBTRACT = '-';
+ public static final byte MULTIPLY = '*';
+ public static final byte DIVIDE = '/';
+ public static final byte REMAINDER = '%';
+
+
+ private final FloatValue floatValue1;
+ private final byte operation;
+ private final FloatValue floatValue2;
+
+
+ /**
+ * Creates a new composite float value of the two given float values
+ * and the given operation.
+ */
+ public CompositeFloatValue(FloatValue floatValue1,
+ byte operation,
+ FloatValue floatValue2)
+ {
+ this.floatValue1 = floatValue1;
+ this.operation = operation;
+ this.floatValue2 = floatValue2;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.floatValue1.equals(((CompositeFloatValue)object).floatValue1) &&
+ this.operation == ((CompositeFloatValue)object).operation &&
+ this.floatValue2.equals(((CompositeFloatValue)object).floatValue2);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ floatValue1.hashCode() ^
+ floatValue2.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "("+floatValue1+((char)operation)+floatValue2+")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeIntegerValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeIntegerValue.java
new file mode 100644
index 0000000000..50d348a2f9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeIntegerValue.java
@@ -0,0 +1,87 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This IntegerValue represents the result of a binary operation on two integer
+ * values.
+ *
+ * @author Eric Lafortune
+ */
+final class CompositeIntegerValue extends SpecificIntegerValue
+{
+ public static final byte ADD = '+';
+ public static final byte SUBTRACT = '-';
+ public static final byte MULTIPLY = '*';
+ public static final byte DIVIDE = '/';
+ public static final byte REMAINDER = '%';
+ public static final byte SHIFT_LEFT = '<';
+ public static final byte SHIFT_RIGHT = '>';
+ public static final byte UNSIGNED_SHIFT_RIGHT = '}';
+ public static final byte AND = '&';
+ public static final byte OR = '|';
+ public static final byte XOR = '^';
+
+
+ private final IntegerValue integerValue1;
+ private final byte operation;
+ private final IntegerValue integerValue2;
+
+
+ /**
+ * Creates a new composite integer value of the two given integer values
+ * and the given operation.
+ */
+ public CompositeIntegerValue(IntegerValue integerValue1,
+ byte operation,
+ IntegerValue integerValue2)
+ {
+ this.integerValue1 = integerValue1;
+ this.operation = operation;
+ this.integerValue2 = integerValue2;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.integerValue1.equals(((CompositeIntegerValue)object).integerValue1) &&
+ this.operation == ((CompositeIntegerValue)object).operation &&
+ this.integerValue2.equals(((CompositeIntegerValue)object).integerValue2);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ integerValue1.hashCode() ^
+ integerValue2.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "("+integerValue1+((char)operation)+integerValue2+")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeLongValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeLongValue.java
new file mode 100644
index 0000000000..49b5094004
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/CompositeLongValue.java
@@ -0,0 +1,87 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This LongValue represents the result of a binary operation on two long
+ * values.
+ *
+ * @author Eric Lafortune
+ */
+final class CompositeLongValue extends SpecificLongValue
+{
+ public static final byte ADD = '+';
+ public static final byte SUBTRACT = '-';
+ public static final byte MULTIPLY = '*';
+ public static final byte DIVIDE = '/';
+ public static final byte REMAINDER = '%';
+ public static final byte SHIFT_LEFT = '<';
+ public static final byte SHIFT_RIGHT = '>';
+ public static final byte UNSIGNED_SHIFT_RIGHT = '}';
+ public static final byte AND = '&';
+ public static final byte OR = '|';
+ public static final byte XOR = '^';
+
+
+ private final LongValue longValue1;
+ private final byte operation;
+ private final Value longValue2;
+
+
+ /**
+ * Creates a new composite long value of the two given long values
+ * and the given operation.
+ */
+ public CompositeLongValue(LongValue longValue1,
+ byte operation,
+ Value longValue2)
+ {
+ this.longValue1 = longValue1;
+ this.operation = operation;
+ this.longValue2 = longValue2;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.longValue1.equals(((CompositeLongValue)object).longValue1) &&
+ this.operation == ((CompositeLongValue)object).operation &&
+ this.longValue2.equals(((CompositeLongValue)object).longValue2);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ longValue1.hashCode() ^
+ longValue2.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "("+longValue1+((char)operation)+longValue2+")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedByteValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedByteValue.java
new file mode 100644
index 0000000000..ffcb24a13f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedByteValue.java
@@ -0,0 +1,64 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This IntegerValue represents a byte value that is converted from an
+ * integer value.
+ *
+ * @author Eric Lafortune
+ */
+final class ConvertedByteValue extends SpecificIntegerValue
+{
+ private final IntegerValue value;
+
+
+ /**
+ * Creates a new converted byte value of the given integer value.
+ */
+ public ConvertedByteValue(IntegerValue value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.value.equals(((ConvertedByteValue)object).value);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ value.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "(byte)("+value+")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedCharacterValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedCharacterValue.java
new file mode 100644
index 0000000000..3b0706a8d9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedCharacterValue.java
@@ -0,0 +1,64 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This IntegerValue represents a character value that is converted from an
+ * integer value.
+ *
+ * @author Eric Lafortune
+ */
+final class ConvertedCharacterValue extends SpecificIntegerValue
+{
+ private final IntegerValue value;
+
+
+ /**
+ * Creates a new converted character value of the given integer value.
+ */
+ public ConvertedCharacterValue(IntegerValue value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.value.equals(((ConvertedCharacterValue)object).value);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ value.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "(char)("+value+")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedDoubleValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedDoubleValue.java
new file mode 100644
index 0000000000..0472a26137
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedDoubleValue.java
@@ -0,0 +1,64 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This DoubleValue represents a double value that is converted from another
+ * scalar value.
+ *
+ * @author Eric Lafortune
+ */
+final class ConvertedDoubleValue extends SpecificDoubleValue
+{
+ private final Value value;
+
+
+ /**
+ * Creates a new converted double value of the given value.
+ */
+ public ConvertedDoubleValue(Value value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.value.equals(((ConvertedDoubleValue)object).value);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ value.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "(double)("+value+")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedFloatValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedFloatValue.java
new file mode 100644
index 0000000000..afa5cf72d1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedFloatValue.java
@@ -0,0 +1,64 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This FloatValue represents a float value that is converted from another
+ * scalar value.
+ *
+ * @author Eric Lafortune
+ */
+final class ConvertedFloatValue extends SpecificFloatValue
+{
+ private final Value value;
+
+
+ /**
+ * Creates a new converted float value of the given value.
+ */
+ public ConvertedFloatValue(Value value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.value.equals(((ConvertedFloatValue)object).value);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ value.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "(float)("+value+")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedIntegerValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedIntegerValue.java
new file mode 100644
index 0000000000..2ec9ab8609
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedIntegerValue.java
@@ -0,0 +1,64 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This IntegerValue represents a integer value that is converted from another
+ * scalar value.
+ *
+ * @author Eric Lafortune
+ */
+final class ConvertedIntegerValue extends SpecificIntegerValue
+{
+ private final Value value;
+
+
+ /**
+ * Creates a new converted integer value of the given value.
+ */
+ public ConvertedIntegerValue(Value value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.value.equals(((ConvertedIntegerValue)object).value);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ value.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "(int)("+value+")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedLongValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedLongValue.java
new file mode 100644
index 0000000000..03eb4fd404
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedLongValue.java
@@ -0,0 +1,64 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This LongValue represents a long value that is converted from another
+ * scalar value.
+ *
+ * @author Eric Lafortune
+ */
+final class ConvertedLongValue extends SpecificLongValue
+{
+ private final Value value;
+
+
+ /**
+ * Creates a new converted long value of the given value.
+ */
+ public ConvertedLongValue(Value value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.value.equals(((ConvertedLongValue)object).value);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ value.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "(long)("+value+")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedShortValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedShortValue.java
new file mode 100644
index 0000000000..e1f1745eb6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ConvertedShortValue.java
@@ -0,0 +1,64 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This IntegerValue represents a short value that is converted from an
+ * integer value.
+ *
+ * @author Eric Lafortune
+ */
+final class ConvertedShortValue extends SpecificIntegerValue
+{
+ private final IntegerValue value;
+
+
+ /**
+ * Creates a new converted short value of the given integer value.
+ */
+ public ConvertedShortValue(IntegerValue value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.value.equals(((ConvertedShortValue)object).value);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ value.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "(short)("+value+")";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DetailedArrayReferenceValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DetailedArrayReferenceValue.java
new file mode 100644
index 0000000000..3f73b91e4a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DetailedArrayReferenceValue.java
@@ -0,0 +1,301 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.util.ClassUtil;
+import proguard.util.ArrayUtil;
+
+/**
+ * This IdentifiedArrayReferenceValue represents an identified array reference
+ * value with its elements.
+ *
+ * @author Eric Lafortune
+ */
+class DetailedArrayReferenceValue extends IdentifiedArrayReferenceValue
+{
+ private static final int MAXIMUM_STORED_ARRAY_LENGTH = 32;
+
+
+ private final Value[] values;
+
+
+ /**
+ * Creates a new array reference value with the given ID.
+ */
+ public DetailedArrayReferenceValue(String type,
+ Clazz referencedClass,
+ IntegerValue arrayLength,
+ ValueFactory valuefactory,
+ int id)
+ {
+ super(type, referencedClass, arrayLength, valuefactory, id);
+
+ // Is the array short enough to analyze?
+ if (arrayLength.isParticular() &&
+ arrayLength.value() <= MAXIMUM_STORED_ARRAY_LENGTH)
+ {
+ // Initialize the values of the array.
+ InitialValueFactory initialValueFactory =
+ new InitialValueFactory(valuefactory);
+
+ String elementType = ClassUtil.isInternalArrayType(type) ?
+ type.substring(1) :
+ type;
+
+ this.values = new Value[arrayLength.value()];
+
+ for (int index = 0; index < values.length; index++)
+ {
+ values[index] = initialValueFactory.createValue(elementType);
+ }
+ }
+ else
+ {
+ // Just ignore the values of the array.
+ this.values = null;
+ }
+ }
+
+
+ // Implementations for ReferenceValue.
+
+ public IntegerValue integerArrayLoad(IntegerValue indexValue, ValueFactory valueFactory)
+ {
+ Value value = arrayLoad(indexValue, valueFactory);
+ return value != null ?
+ value.integerValue() :
+ super.integerArrayLoad(indexValue, valueFactory);
+ }
+
+
+ public LongValue longArrayLoad(IntegerValue indexValue, ValueFactory valueFactory)
+ {
+ Value value = arrayLoad(indexValue, valueFactory);
+ return value != null ?
+ value.longValue() :
+ super.longArrayLoad(indexValue, valueFactory);
+ }
+
+
+ public FloatValue floatArrayLoad(IntegerValue indexValue, ValueFactory valueFactory)
+ {
+ Value value = arrayLoad(indexValue, valueFactory);
+ return value != null ?
+ value.floatValue() :
+ super.floatArrayLoad(indexValue, valueFactory);
+ }
+
+
+ public DoubleValue doubleArrayLoad(IntegerValue indexValue, ValueFactory valueFactory)
+ {
+ Value value = arrayLoad(indexValue, valueFactory);
+ return value != null ?
+ value.doubleValue() :
+ super.doubleArrayLoad(indexValue, valueFactory);
+ }
+
+
+ public ReferenceValue referenceArrayLoad(IntegerValue indexValue, ValueFactory valueFactory)
+ {
+ Value value = arrayLoad(indexValue, valueFactory);
+ return value != null ?
+ value.referenceValue() :
+ super.referenceArrayLoad(indexValue, valueFactory);
+ }
+
+
+ /**
+ * Returns the specified untyped value from the given array, or null if it
+ * is unknown.
+ */
+ private Value arrayLoad(IntegerValue indexValue, ValueFactory valueFactory)
+ {
+ if (values != null &&
+ indexValue.isParticular())
+ {
+ int index = indexValue.value();
+ if (index >=0 &&
+ index < values.length)
+ {
+ return values[index];
+ }
+ }
+
+ return null;
+ }
+
+
+ public void arrayStore(IntegerValue indexValue, Value value)
+ {
+ if (values != null)
+ {
+ if (indexValue.isParticular())
+ {
+ int index = indexValue.value();
+ if (index >=0 &&
+ index < values.length)
+ {
+ values[index] = value;
+ }
+ }
+ else
+ {
+ for (int index = 0; index < values.length; index++)
+ {
+ values[index].generalize(value);
+ }
+ }
+ }
+ }
+
+
+ // Implementations of binary methods of ReferenceValue.
+
+ public ReferenceValue generalize(ReferenceValue other)
+ {
+ return other.generalize(this);
+ }
+
+
+ public int equal(ReferenceValue other)
+ {
+ return other.equal(this);
+ }
+
+
+// // Implementations of binary ReferenceValue methods with
+// // IdentifiedReferenceValue arguments.
+//
+// public ReferenceValue generalize(IdentifiedReferenceValue other)
+// {
+// return generalize((TypedReferenceValue)other);
+// }
+//
+//
+// public int equal(IdentifiedReferenceValue other)
+// {
+// return equal((TypedReferenceValue)other);
+// }
+//
+//
+// // Implementations of binary ReferenceValue methods with
+// // ArrayReferenceValue arguments.
+//
+// public ReferenceValue generalize(ArrayReferenceValue other)
+// {
+// return generalize((TypedReferenceValue)other);
+// }
+//
+//
+// public int equal(ArrayReferenceValue other)
+// {
+// return equal((TypedReferenceValue)other);
+// }
+//
+//
+// // Implementations of binary ReferenceValue methods with
+// // IdentifiedArrayReferenceValue arguments.
+//
+// public ReferenceValue generalize(IdentifiedArrayReferenceValue other)
+// {
+// return generalize((ArrayReferenceValue)other);
+// }
+//
+//
+// public int equal(IdentifiedArrayReferenceValue other)
+// {
+// return equal((ArrayReferenceValue)other);
+// }
+//
+//
+// // Implementations of binary ReferenceValue methods with
+// // DetailedArrayReferenceValue arguments.
+//
+// public ReferenceValue generalize(DetailedArrayReferenceValue other)
+// {
+// return generalize((IdentifiedArrayReferenceValue)other);
+// }
+//
+//
+// public int equal(DetailedArrayReferenceValue other)
+// {
+// return equal((IdentifiedArrayReferenceValue)other);
+// }
+
+
+ // Implementations for Value.
+
+ public boolean isParticular()
+ {
+ if (values == null)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < values.length; index++)
+ {
+ if (!values[index].isParticular())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ ArrayUtil.equalOrNull(this.values, ((DetailedArrayReferenceValue)object).values);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ ArrayUtil.hashCodeOrNull(values);
+ }
+
+
+ public String toString()
+ {
+ if (values == null)
+ {
+ return super.toString();
+ }
+
+ StringBuffer buffer = new StringBuffer(super.toString());
+
+ buffer.append('{');
+ for (int index = 0; index < values.length; index++)
+ {
+ buffer.append(values[index]);
+ buffer.append(index < values.length-1 ? ',' : '}');
+ }
+
+ return buffer.toString();
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DetailedValueFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DetailedValueFactory.java
new file mode 100644
index 0000000000..0145523e85
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DetailedValueFactory.java
@@ -0,0 +1,48 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.*;
+
+/**
+ * This identified value factory creates array reference values that also
+ * represent their elements, in as far as possible.
+ *
+ * @author Eric Lafortune
+ */
+public class DetailedValueFactory
+extends IdentifiedValueFactory
+{
+ // Implementations for ReferenceValue.
+
+ public ReferenceValue createArrayReferenceValue(String type,
+ Clazz referencedClass,
+ IntegerValue arrayLength)
+ {
+ return type == null ?
+ REFERENCE_VALUE_NULL :
+ new DetailedArrayReferenceValue(ClassConstants.TYPE_ARRAY + type,
+ referencedClass,
+ arrayLength,
+ this,
+ referenceID++);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DoubleValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DoubleValue.java
new file mode 100644
index 0000000000..44912e7f2a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/DoubleValue.java
@@ -0,0 +1,359 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.ClassConstants;
+
+/**
+ * This class represents a partially evaluated double value.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class DoubleValue extends Category2Value
+{
+ /**
+ * Returns the specific double value, if applicable.
+ */
+ public double value()
+ {
+ return 0.0;
+ }
+
+
+ // Basic unary methods.
+
+ /**
+ * Returns the negated value of this DoubleValue.
+ */
+ public abstract DoubleValue negate();
+
+ /**
+ * Converts this DoubleValue to an IntegerValue.
+ */
+ public abstract IntegerValue convertToInteger();
+
+ /**
+ * Converts this DoubleValue to a LongValue.
+ */
+ public abstract LongValue convertToLong();
+
+ /**
+ * Converts this DoubleValue to a FloatValue.
+ */
+ public abstract FloatValue convertToFloat();
+
+
+ // Basic binary methods.
+
+ /**
+ * Returns the generalization of this DoubleValue and the given other
+ * DoubleValue.
+ */
+ public abstract DoubleValue generalize(DoubleValue other);
+
+
+ /**
+ * Returns the sum of this DoubleValue and the given DoubleValue.
+ */
+ public abstract DoubleValue add(DoubleValue other);
+
+ /**
+ * Returns the difference of this DoubleValue and the given DoubleValue.
+ */
+ public abstract DoubleValue subtract(DoubleValue other);
+
+ /**
+ * Returns the difference of the given DoubleValue and this DoubleValue.
+ */
+ public abstract DoubleValue subtractFrom(DoubleValue other);
+
+ /**
+ * Returns the product of this DoubleValue and the given DoubleValue.
+ */
+ public abstract DoubleValue multiply(DoubleValue other);
+
+ /**
+ * Returns the quotient of this DoubleValue and the given DoubleValue.
+ */
+ public abstract DoubleValue divide(DoubleValue other);
+
+ /**
+ * Returns the quotient of the given DoubleValue and this DoubleValue.
+ */
+ public abstract DoubleValue divideOf(DoubleValue other);
+
+ /**
+ * Returns the remainder of this DoubleValue divided by the given DoubleValue.
+ */
+ public abstract DoubleValue remainder(DoubleValue other);
+
+ /**
+ * Returns the remainder of the given DoubleValue divided by this DoubleValue.
+ */
+ public abstract DoubleValue remainderOf(DoubleValue other);
+
+ /**
+ * Returns an IntegerValue with value -1, 0, or 1, if this DoubleValue is
+ * less than, equal to, or greater than the given DoubleValue, respectively.
+ */
+ public abstract IntegerValue compare(DoubleValue other);
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns an IntegerValue with value 1, 0, or -1, if this DoubleValue is
+ * less than, equal to, or greater than the given DoubleValue, respectively.
+ */
+ public final IntegerValue compareReverse(DoubleValue other)
+ {
+ return compare(other).negate();
+ }
+
+
+ // Similar binary methods, but this time with more specific arguments.
+
+ /**
+ * Returns the generalization of this DoubleValue and the given other
+ * SpecificDoubleValue.
+ */
+ public DoubleValue generalize(SpecificDoubleValue other)
+ {
+ return generalize((DoubleValue)other);
+ }
+
+
+ /**
+ * Returns the sum of this DoubleValue and the given SpecificDoubleValue.
+ */
+ public DoubleValue add(SpecificDoubleValue other)
+ {
+ return add((DoubleValue)other);
+ }
+
+ /**
+ * Returns the difference of this DoubleValue and the given SpecificDoubleValue.
+ */
+ public DoubleValue subtract(SpecificDoubleValue other)
+ {
+ return subtract((DoubleValue)other);
+ }
+
+ /**
+ * Returns the difference of the given SpecificDoubleValue and this DoubleValue.
+ */
+ public DoubleValue subtractFrom(SpecificDoubleValue other)
+ {
+ return subtractFrom((DoubleValue)other);
+ }
+
+ /**
+ * Returns the product of this DoubleValue and the given SpecificDoubleValue.
+ */
+ public DoubleValue multiply(SpecificDoubleValue other)
+ {
+ return multiply((DoubleValue)other);
+ }
+
+ /**
+ * Returns the quotient of this DoubleValue and the given SpecificDoubleValue.
+ */
+ public DoubleValue divide(SpecificDoubleValue other)
+ {
+ return divide((DoubleValue)other);
+ }
+
+ /**
+ * Returns the quotient of the given SpecificDoubleValue and this
+ * DoubleValue.
+ */
+ public DoubleValue divideOf(SpecificDoubleValue other)
+ {
+ return divideOf((DoubleValue)other);
+ }
+
+ /**
+ * Returns the remainder of this DoubleValue divided by the given
+ * SpecificDoubleValue.
+ */
+ public DoubleValue remainder(SpecificDoubleValue other)
+ {
+ return remainder((DoubleValue)other);
+ }
+
+ /**
+ * Returns the remainder of the given SpecificDoubleValue and this
+ * DoubleValue.
+ */
+ public DoubleValue remainderOf(SpecificDoubleValue other)
+ {
+ return remainderOf((DoubleValue)other);
+ }
+
+ /**
+ * Returns an IntegerValue with value -1, 0, or 1, if this DoubleValue is
+ * less than, equal to, or greater than the given SpecificDoubleValue,
+ * respectively.
+ */
+ public IntegerValue compare(SpecificDoubleValue other)
+ {
+ return compare((DoubleValue)other);
+ }
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns an IntegerValue with value 1, 0, or -1, if this DoubleValue is
+ * less than, equal to, or greater than the given SpecificDoubleValue,
+ * respectively.
+ */
+ public final IntegerValue compareReverse(SpecificDoubleValue other)
+ {
+ return compare(other).negate();
+ }
+
+
+ // Similar binary methods, but this time with particular arguments.
+
+ /**
+ * Returns the generalization of this DoubleValue and the given other
+ * ParticularDoubleValue.
+ */
+ public DoubleValue generalize(ParticularDoubleValue other)
+ {
+ return generalize((SpecificDoubleValue)other);
+ }
+
+
+ /**
+ * Returns the sum of this DoubleValue and the given ParticularDoubleValue.
+ */
+ public DoubleValue add(ParticularDoubleValue other)
+ {
+ return add((SpecificDoubleValue)other);
+ }
+
+ /**
+ * Returns the difference of this DoubleValue and the given ParticularDoubleValue.
+ */
+ public DoubleValue subtract(ParticularDoubleValue other)
+ {
+ return subtract((SpecificDoubleValue)other);
+ }
+
+ /**
+ * Returns the difference of the given ParticularDoubleValue and this DoubleValue.
+ */
+ public DoubleValue subtractFrom(ParticularDoubleValue other)
+ {
+ return subtractFrom((SpecificDoubleValue)other);
+ }
+
+ /**
+ * Returns the product of this DoubleValue and the given ParticularDoubleValue.
+ */
+ public DoubleValue multiply(ParticularDoubleValue other)
+ {
+ return multiply((SpecificDoubleValue)other);
+ }
+
+ /**
+ * Returns the quotient of this DoubleValue and the given ParticularDoubleValue.
+ */
+ public DoubleValue divide(ParticularDoubleValue other)
+ {
+ return divide((SpecificDoubleValue)other);
+ }
+
+ /**
+ * Returns the quotient of the given ParticularDoubleValue and this
+ * DoubleValue.
+ */
+ public DoubleValue divideOf(ParticularDoubleValue other)
+ {
+ return divideOf((SpecificDoubleValue)other);
+ }
+
+ /**
+ * Returns the remainder of this DoubleValue divided by the given
+ * ParticularDoubleValue.
+ */
+ public DoubleValue remainder(ParticularDoubleValue other)
+ {
+ return remainder((SpecificDoubleValue)other);
+ }
+
+ /**
+ * Returns the remainder of the given ParticularDoubleValue and this
+ * DoubleValue.
+ */
+ public DoubleValue remainderOf(ParticularDoubleValue other)
+ {
+ return remainderOf((SpecificDoubleValue)other);
+ }
+
+ /**
+ * Returns an IntegerValue with value -1, 0, or 1, if this DoubleValue is
+ * less than, equal to, or greater than the given ParticularDoubleValue,
+ * respectively.
+ */
+ public IntegerValue compare(ParticularDoubleValue other)
+ {
+ return compare((SpecificDoubleValue)other);
+ }
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns an IntegerValue with value 1, 0, or -1, if this DoubleValue is
+ * less than, equal to, or greater than the given ParticularDoubleValue,
+ * respectively.
+ */
+ public final IntegerValue compareReverse(ParticularDoubleValue other)
+ {
+ return compare(other).negate();
+ }
+
+
+ // Implementations for Value.
+
+ public final DoubleValue doubleValue()
+ {
+ return this;
+ }
+
+ public final Value generalize(Value other)
+ {
+ return this.generalize(other.doubleValue());
+ }
+
+ public final int computationalType()
+ {
+ return TYPE_DOUBLE;
+ }
+
+ public final String internalType()
+ {
+ return String.valueOf(ClassConstants.TYPE_DOUBLE);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/FloatValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/FloatValue.java
new file mode 100644
index 0000000000..515cc862fa
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/FloatValue.java
@@ -0,0 +1,359 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.ClassConstants;
+
+/**
+ * This class represents a partially evaluated float value.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class FloatValue extends Category1Value
+{
+ /**
+ * Returns the specific float value, if applicable.
+ */
+ public float value()
+ {
+ return 0f;
+ }
+
+
+ // Basic unary methods.
+
+ /**
+ * Returns the negated value of this FloatValue.
+ */
+ public abstract FloatValue negate();
+
+ /**
+ * Converts this FloatValue to an IntegerValue.
+ */
+ public abstract IntegerValue convertToInteger();
+
+ /**
+ * Converts this FloatValue to a LongValue.
+ */
+ public abstract LongValue convertToLong();
+
+ /**
+ * Converts this FloatValue to a DoubleValue.
+ */
+ public abstract DoubleValue convertToDouble();
+
+
+ // Basic binary methods.
+
+ /**
+ * Returns the generalization of this FloatValue and the given other
+ * FloatValue.
+ */
+ public abstract FloatValue generalize(FloatValue other);
+
+
+ /**
+ * Returns the sum of this FloatValue and the given FloatValue.
+ */
+ public abstract FloatValue add(FloatValue other);
+
+ /**
+ * Returns the difference of this FloatValue and the given FloatValue.
+ */
+ public abstract FloatValue subtract(FloatValue other);
+
+ /**
+ * Returns the difference of the given FloatValue and this FloatValue.
+ */
+ public abstract FloatValue subtractFrom(FloatValue other);
+
+ /**
+ * Returns the product of this FloatValue and the given FloatValue.
+ */
+ public abstract FloatValue multiply(FloatValue other);
+
+ /**
+ * Returns the quotient of this FloatValue and the given FloatValue.
+ */
+ public abstract FloatValue divide(FloatValue other);
+
+ /**
+ * Returns the quotient of the given FloatValue and this FloatValue.
+ */
+ public abstract FloatValue divideOf(FloatValue other);
+
+ /**
+ * Returns the remainder of this FloatValue divided by the given FloatValue.
+ */
+ public abstract FloatValue remainder(FloatValue other);
+
+ /**
+ * Returns the remainder of the given FloatValue divided by this FloatValue.
+ */
+ public abstract FloatValue remainderOf(FloatValue other);
+
+ /**
+ * Returns an IntegerValue with value -1, 0, or 1, if this FloatValue is
+ * less than, equal to, or greater than the given FloatValue, respectively.
+ */
+ public abstract IntegerValue compare(FloatValue other);
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns an IntegerValue with value 1, 0, or -1, if this FloatValue is
+ * less than, equal to, or greater than the given FloatValue, respectively.
+ */
+ public final IntegerValue compareReverse(FloatValue other)
+ {
+ return compare(other).negate();
+ }
+
+
+ // Similar binary methods, but this time with more specific arguments.
+
+ /**
+ * Returns the generalization of this FloatValue and the given other
+ * SpecificFloatValue.
+ */
+ public FloatValue generalize(SpecificFloatValue other)
+ {
+ return generalize((FloatValue)other);
+ }
+
+
+ /**
+ * Returns the sum of this FloatValue and the given SpecificFloatValue.
+ */
+ public FloatValue add(SpecificFloatValue other)
+ {
+ return add((FloatValue)other);
+ }
+
+ /**
+ * Returns the difference of this FloatValue and the given SpecificFloatValue.
+ */
+ public FloatValue subtract(SpecificFloatValue other)
+ {
+ return subtract((FloatValue)other);
+ }
+
+ /**
+ * Returns the difference of the given SpecificFloatValue and this FloatValue.
+ */
+ public FloatValue subtractFrom(SpecificFloatValue other)
+ {
+ return subtractFrom((FloatValue)other);
+ }
+
+ /**
+ * Returns the product of this FloatValue and the given SpecificFloatValue.
+ */
+ public FloatValue multiply(SpecificFloatValue other)
+ {
+ return multiply((FloatValue)other);
+ }
+
+ /**
+ * Returns the quotient of this FloatValue and the given SpecificFloatValue.
+ */
+ public FloatValue divide(SpecificFloatValue other)
+ {
+ return divide((FloatValue)other);
+ }
+
+ /**
+ * Returns the quotient of the given SpecificFloatValue and this
+ * FloatValue.
+ */
+ public FloatValue divideOf(SpecificFloatValue other)
+ {
+ return divideOf((FloatValue)other);
+ }
+
+ /**
+ * Returns the remainder of this FloatValue divided by the given
+ * SpecificFloatValue.
+ */
+ public FloatValue remainder(SpecificFloatValue other)
+ {
+ return remainder((FloatValue)other);
+ }
+
+ /**
+ * Returns the remainder of the given SpecificFloatValue and this
+ * FloatValue.
+ */
+ public FloatValue remainderOf(SpecificFloatValue other)
+ {
+ return remainderOf((FloatValue)other);
+ }
+
+ /**
+ * Returns an IntegerValue with value -1, 0, or 1, if this FloatValue is
+ * less than, equal to, or greater than the given SpecificFloatValue,
+ * respectively.
+ */
+ public IntegerValue compare(SpecificFloatValue other)
+ {
+ return compare((FloatValue)other);
+ }
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns an IntegerValue with value 1, 0, or -1, if this FloatValue is
+ * less than, equal to, or greater than the given SpecificFloatValue,
+ * respectively.
+ */
+ public final IntegerValue compareReverse(SpecificFloatValue other)
+ {
+ return compare(other).negate();
+ }
+
+
+ // Similar binary methods, but this time with particular arguments.
+
+ /**
+ * Returns the generalization of this FloatValue and the given other
+ * ParticularFloatValue.
+ */
+ public FloatValue generalize(ParticularFloatValue other)
+ {
+ return generalize((SpecificFloatValue)other);
+ }
+
+
+ /**
+ * Returns the sum of this FloatValue and the given ParticularFloatValue.
+ */
+ public FloatValue add(ParticularFloatValue other)
+ {
+ return add((SpecificFloatValue)other);
+ }
+
+ /**
+ * Returns the difference of this FloatValue and the given ParticularFloatValue.
+ */
+ public FloatValue subtract(ParticularFloatValue other)
+ {
+ return subtract((SpecificFloatValue)other);
+ }
+
+ /**
+ * Returns the difference of the given ParticularFloatValue and this FloatValue.
+ */
+ public FloatValue subtractFrom(ParticularFloatValue other)
+ {
+ return subtractFrom((SpecificFloatValue)other);
+ }
+
+ /**
+ * Returns the product of this FloatValue and the given ParticularFloatValue.
+ */
+ public FloatValue multiply(ParticularFloatValue other)
+ {
+ return multiply((SpecificFloatValue)other);
+ }
+
+ /**
+ * Returns the quotient of this FloatValue and the given ParticularFloatValue.
+ */
+ public FloatValue divide(ParticularFloatValue other)
+ {
+ return divide((SpecificFloatValue)other);
+ }
+
+ /**
+ * Returns the quotient of the given ParticularFloatValue and this
+ * FloatValue.
+ */
+ public FloatValue divideOf(ParticularFloatValue other)
+ {
+ return divideOf((SpecificFloatValue)other);
+ }
+
+ /**
+ * Returns the remainder of this FloatValue divided by the given
+ * ParticularFloatValue.
+ */
+ public FloatValue remainder(ParticularFloatValue other)
+ {
+ return remainder((SpecificFloatValue)other);
+ }
+
+ /**
+ * Returns the remainder of the given ParticularFloatValue and this
+ * FloatValue.
+ */
+ public FloatValue remainderOf(ParticularFloatValue other)
+ {
+ return remainderOf((SpecificFloatValue)other);
+ }
+
+ /**
+ * Returns an IntegerValue with value -1, 0, or 1, if this FloatValue is
+ * less than, equal to, or greater than the given ParticularFloatValue,
+ * respectively.
+ */
+ public IntegerValue compare(ParticularFloatValue other)
+ {
+ return compare((SpecificFloatValue)other);
+ }
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns an IntegerValue with value 1, 0, or -1, if this FloatValue is
+ * less than, equal to, or greater than the given ParticularFloatValue,
+ * respectively.
+ */
+ public final IntegerValue compareReverse(ParticularFloatValue other)
+ {
+ return compare(other).negate();
+ }
+
+
+ // Implementations for Value.
+
+ public final FloatValue floatValue()
+ {
+ return this;
+ }
+
+ public final Value generalize(Value other)
+ {
+ return this.generalize(other.floatValue());
+ }
+
+ public final int computationalType()
+ {
+ return TYPE_FLOAT;
+ }
+
+ public final String internalType()
+ {
+ return String.valueOf(ClassConstants.TYPE_FLOAT);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedArrayReferenceValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedArrayReferenceValue.java
new file mode 100644
index 0000000000..6922dbd0e1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedArrayReferenceValue.java
@@ -0,0 +1,159 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.Clazz;
+
+/**
+ * This ArrayReferenceValue represents an array reference value that is
+ * identified by a unique ID.
+ *
+ * @author Eric Lafortune
+ */
+class IdentifiedArrayReferenceValue extends ArrayReferenceValue
+{
+ private final ValueFactory valuefactory;
+ private final int id;
+
+
+ /**
+ * Creates a new array reference value with the given ID.
+ */
+ public IdentifiedArrayReferenceValue(String type,
+ Clazz referencedClass,
+ IntegerValue arrayLength,
+ ValueFactory valuefactory,
+ int id)
+ {
+ super(type, referencedClass, arrayLength);
+
+ this.valuefactory = valuefactory;
+ this.id = id;
+ }
+
+
+ // Implementations of binary methods of ReferenceValue.
+
+ public ReferenceValue generalize(ReferenceValue other)
+ {
+ return other.generalize(this);
+ }
+
+
+ public int equal(ReferenceValue other)
+ {
+ return other.equal(this);
+ }
+
+
+// // Implementations of binary ReferenceValue methods with
+// // IdentifiedReferenceValue arguments.
+//
+// public ReferenceValue generalize(IdentifiedReferenceValue other)
+// {
+// return generalize((TypedReferenceValue)other);
+// }
+//
+//
+// public int equal(IdentifiedReferenceValue other)
+// {
+// return equal((TypedReferenceValue)other);
+// }
+//
+//
+// // Implementations of binary ReferenceValue methods with
+// // ArrayReferenceValue arguments.
+//
+// public ReferenceValue generalize(ArrayReferenceValue other)
+// {
+// return generalize((TypedReferenceValue)other);
+// }
+//
+//
+// public int equal(ArrayReferenceValue other)
+// {
+// return equal((TypedReferenceValue)other);
+// }
+//
+//
+ // Implementations of binary ReferenceValue methods with
+ // IdentifiedArrayReferenceValue arguments.
+
+// public ReferenceValue generalize(IdentifiedArrayReferenceValue other)
+// {
+// return generalize((ArrayReferenceValue)other);
+// }
+
+
+ public int equal(IdentifiedArrayReferenceValue other)
+ {
+ return this.equals(other) ? ALWAYS :
+ this.equal((TypedReferenceValue)other);
+ }
+
+
+// // Implementations of binary ReferenceValue methods with
+// // DetailedArrayReferenceValue arguments.
+//
+// public ReferenceValue generalize(DetailedArrayReferenceValue other)
+// {
+// return generalize((IdentifiedArrayReferenceValue)other);
+// }
+//
+//
+// public int equal(DetailedArrayReferenceValue other)
+// {
+// return equal((IdentifiedArrayReferenceValue)other);
+// }
+
+
+ // Implementations for Value.
+
+ public boolean isSpecific()
+ {
+ return true;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.valuefactory.equals(((IdentifiedArrayReferenceValue)object).valuefactory) &&
+ this.id == ((IdentifiedArrayReferenceValue)object).id;
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ valuefactory.hashCode() ^
+ id;
+ }
+
+
+ public String toString()
+ {
+ return super.toString() + '#' + id;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedDoubleValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedDoubleValue.java
new file mode 100644
index 0000000000..56cceda120
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedDoubleValue.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This DoubleValue represents a double value that is identified by a unique ID.
+ *
+ * @author Eric Lafortune
+ */
+final class IdentifiedDoubleValue extends SpecificDoubleValue
+{
+ private final ValueFactory valuefactory;
+ private final int id;
+
+
+ /**
+ * Creates a new double value with the given ID.
+ */
+ public IdentifiedDoubleValue(ValueFactory valuefactory, int id)
+ {
+ this.valuefactory = valuefactory;
+ this.id = id;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.valuefactory.equals(((IdentifiedDoubleValue)object).valuefactory) &&
+ this.id == ((IdentifiedDoubleValue)object).id;
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ valuefactory.hashCode() ^
+ id;
+ }
+
+
+ public String toString()
+ {
+ return "d"+id;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedFloatValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedFloatValue.java
new file mode 100644
index 0000000000..cfeb9a98ce
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedFloatValue.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This FloatValue represents a float value that is identified by a unique ID.
+ *
+ * @author Eric Lafortune
+ */
+final class IdentifiedFloatValue extends SpecificFloatValue
+{
+ private final ValueFactory valuefactory;
+ private final int id;
+
+
+ /**
+ * Creates a new float value with the given ID.
+ */
+ public IdentifiedFloatValue(ValueFactory valuefactory, int id)
+ {
+ this.valuefactory = valuefactory;
+ this.id = id;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.valuefactory.equals(((IdentifiedFloatValue)object).valuefactory) &&
+ this.id == ((IdentifiedFloatValue)object).id;
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ valuefactory.hashCode() ^
+ id;
+ }
+
+
+ public String toString()
+ {
+ return "f"+id;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedIntegerValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedIntegerValue.java
new file mode 100644
index 0000000000..e054e85602
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedIntegerValue.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This IntegerValue represents a integer value that is identified by a unique ID.
+ *
+ * @author Eric Lafortune
+ */
+final class IdentifiedIntegerValue extends SpecificIntegerValue
+{
+ private final ValueFactory valuefactory;
+ private final int id;
+
+
+ /**
+ * Creates a new integer value with the given ID.
+ */
+ public IdentifiedIntegerValue(ValueFactory valuefactory, int id)
+ {
+ this.valuefactory = valuefactory;
+ this.id = id;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.valuefactory.equals(((IdentifiedIntegerValue)object).valuefactory) &&
+ this.id == ((IdentifiedIntegerValue)object).id;
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ valuefactory.hashCode() ^
+ id;
+ }
+
+
+ public String toString()
+ {
+ return "i"+id;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedLongValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedLongValue.java
new file mode 100644
index 0000000000..d96ffdbe5e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedLongValue.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This LongValue represents a long value that is identified by a unique ID.
+ *
+ * @author Eric Lafortune
+ */
+final class IdentifiedLongValue extends SpecificLongValue
+{
+ private final ValueFactory valuefactory;
+ private final int id;
+
+
+ /**
+ * Creates a new long value with the given ID.
+ */
+ public IdentifiedLongValue(ValueFactory valuefactory, int id)
+ {
+ this.valuefactory = valuefactory;
+ this.id = id;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.valuefactory.equals(((IdentifiedLongValue)object).valuefactory) &&
+ this.id == ((IdentifiedLongValue)object).id;
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ valuefactory.hashCode() ^
+ id;
+ }
+
+
+ public String toString()
+ {
+ return "l"+id;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedReferenceValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedReferenceValue.java
new file mode 100644
index 0000000000..13e63384f5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedReferenceValue.java
@@ -0,0 +1,159 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.Clazz;
+
+/**
+ * This TypedReferenceValue represents a reference value that is identified by a
+ * unique ID.
+ *
+ * @author Eric Lafortune
+ */
+class IdentifiedReferenceValue extends TypedReferenceValue
+{
+ private final ValueFactory valuefactory;
+ private final int id;
+
+
+ /**
+ * Creates a new reference value with the given ID.
+ */
+ public IdentifiedReferenceValue(String type,
+ Clazz referencedClass,
+ boolean mayBeNull,
+ ValueFactory valuefactory,
+ int id)
+ {
+ super(type, referencedClass, mayBeNull);
+
+ this.valuefactory = valuefactory;
+ this.id = id;
+ }
+
+
+ // Implementations of binary methods of ReferenceValue.
+
+ public ReferenceValue generalize(ReferenceValue other)
+ {
+ return other.generalize(this);
+ }
+
+
+ public int equal(ReferenceValue other)
+ {
+ return other.equal(this);
+ }
+
+
+ // Implementations of binary ReferenceValue methods with
+ // IdentifiedReferenceValue arguments.
+
+// public ReferenceValue generalize(IdentifiedReferenceValue other)
+// {
+// return generalize((TypedReferenceValue)other);
+// }
+
+
+ public int equal(IdentifiedReferenceValue other)
+ {
+ return this.equals(other) ? ALWAYS :
+ this.equal((TypedReferenceValue)other);
+ }
+
+
+// // Implementations of binary ReferenceValue methods with
+// // ArrayReferenceValue arguments.
+//
+// public ReferenceValue generalize(ArrayReferenceValue other)
+// {
+// return generalize((TypedReferenceValue)other);
+// }
+//
+//
+// public int equal(ArrayReferenceValue other)
+// {
+// return equal((TypedReferenceValue)other);
+// }
+//
+//
+// // Implementations of binary ReferenceValue methods with
+// // IdentifiedArrayReferenceValue arguments.
+//
+// public ReferenceValue generalize(IdentifiedArrayReferenceValue other)
+// {
+// return generalize((ArrayReferenceValue)other);
+// }
+//
+//
+// public int equal(IdentifiedArrayReferenceValue other)
+// {
+// return equal((ArrayReferenceValue)other);
+// }
+//
+//
+// // Implementations of binary ReferenceValue methods with
+// // DetailedArrayReferenceValue arguments.
+//
+// public ReferenceValue generalize(DetailedArrayReferenceValue other)
+// {
+// return generalize((IdentifiedArrayReferenceValue)other);
+// }
+//
+//
+// public int equal(DetailedArrayReferenceValue other)
+// {
+// return equal((IdentifiedArrayReferenceValue)other);
+// }
+
+
+ // Implementations for Value.
+
+ public boolean isSpecific()
+ {
+ return true;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.valuefactory.equals(((IdentifiedReferenceValue)object).valuefactory) &&
+ this.id == ((IdentifiedReferenceValue)object).id;
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ valuefactory.hashCode() ^
+ id;
+ }
+
+
+ public String toString()
+ {
+ return super.toString()+'#'+id;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedValueFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedValueFactory.java
new file mode 100644
index 0000000000..b999d89a9e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IdentifiedValueFactory.java
@@ -0,0 +1,92 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.*;
+
+/**
+ * This particular value factory attaches a unique ID to any unknown values.
+ *
+ * @author Eric Lafortune
+ */
+public class IdentifiedValueFactory
+extends ParticularValueFactory
+{
+ protected int integerID;
+ protected int longID;
+ protected int floatID;
+ protected int doubleID;
+ protected int referenceID;
+
+
+ // Implementations for ValueFactory.
+
+ public IntegerValue createIntegerValue()
+ {
+ return new IdentifiedIntegerValue(this, integerID++);
+ }
+
+
+ public LongValue createLongValue()
+ {
+ return new IdentifiedLongValue(this, longID++);
+ }
+
+
+ public FloatValue createFloatValue()
+ {
+ return new IdentifiedFloatValue(this, floatID++);
+ }
+
+
+ public DoubleValue createDoubleValue()
+ {
+ return new IdentifiedDoubleValue(this, doubleID++);
+ }
+
+
+ public ReferenceValue createReferenceValue(String type,
+ Clazz referencedClass,
+ boolean mayBeNull)
+ {
+ return type == null ?
+ REFERENCE_VALUE_NULL :
+ new IdentifiedReferenceValue(type,
+ referencedClass,
+ mayBeNull,
+ this,
+ referenceID++);
+ }
+
+
+ public ReferenceValue createArrayReferenceValue(String type,
+ Clazz referencedClass,
+ IntegerValue arrayLength)
+ {
+ return type == null ?
+ REFERENCE_VALUE_NULL :
+ new IdentifiedArrayReferenceValue(ClassConstants.TYPE_ARRAY + type,
+ referencedClass,
+ arrayLength,
+ this,
+ referenceID++);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/InitialValueFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/InitialValueFactory.java
new file mode 100644
index 0000000000..725b392077
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/InitialValueFactory.java
@@ -0,0 +1,79 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.ClassConstants;
+
+/**
+ * This value factory creates initial values for fields and array elements,
+ * with the help of a given value factory. Note that this class itself doesn't
+ * implement ValueFactory.
+ *
+ * @author Eric Lafortune
+ */
+public class InitialValueFactory
+{
+ private final ValueFactory valueFactory;
+
+
+ /**
+ * Creates a new InitialValueFactory.
+ * @param valueFactory the value factory that will actually create the
+ * values.
+ */
+ public InitialValueFactory(ValueFactory valueFactory)
+ {
+ this.valueFactory = valueFactory;
+ }
+
+
+ /**
+ * Creates an initial value (0, 0L, 0.0f, 0.0, null) of the given type.
+ */
+ public Value createValue(String type)
+ {
+ switch (type.charAt(0))
+ {
+ case ClassConstants.TYPE_BOOLEAN:
+ case ClassConstants.TYPE_BYTE:
+ case ClassConstants.TYPE_CHAR:
+ case ClassConstants.TYPE_SHORT:
+ case ClassConstants.TYPE_INT:
+ return valueFactory.createIntegerValue(0);
+
+ case ClassConstants.TYPE_LONG:
+ return valueFactory.createLongValue(0L);
+
+ case ClassConstants.TYPE_FLOAT:
+ return valueFactory.createFloatValue(0.0f);
+
+ case ClassConstants.TYPE_DOUBLE:
+ return valueFactory.createDoubleValue(0.0);
+
+ case ClassConstants.TYPE_CLASS_START:
+ case ClassConstants.TYPE_ARRAY:
+ return valueFactory.createReferenceValueNull();
+
+ default:
+ throw new IllegalArgumentException("Invalid type ["+type+"]");
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/InstructionOffsetValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/InstructionOffsetValue.java
new file mode 100644
index 0000000000..69e76bdf13
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/InstructionOffsetValue.java
@@ -0,0 +1,320 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.ClassConstants;
+
+/**
+ * This class represents a partially evaluated instruction offset. It can
+ * contain 0 or more specific instruction offsets.
+ *
+ * @author Eric Lafortune
+ */
+public class InstructionOffsetValue extends Category1Value
+{
+ public static final InstructionOffsetValue EMPTY_VALUE = new InstructionOffsetValue();
+
+
+ private int[] values;
+
+
+ private InstructionOffsetValue()
+ {
+ }
+
+
+ public InstructionOffsetValue(int value)
+ {
+ this.values = new int[] { value };
+ }
+
+
+ public InstructionOffsetValue(int[] values)
+ {
+ this.values = values;
+ }
+
+
+ public int instructionOffsetCount()
+ {
+ return values == null ? 0 : values.length;
+ }
+
+
+ public int instructionOffset(int index)
+ {
+ return values[index];
+ }
+
+
+ /**
+ * Returns whether the given value is present in this list of instruction
+ * offsets.
+ */
+ public boolean contains(int value)
+ {
+ if (values != null)
+ {
+ for (int index = 0; index < values.length; index++)
+ {
+ if (values[index] == value)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns the minimum value from this list of instruction offsets.
+ * Returns <code>Integer.MAX_VALUE</code> if the list is empty.
+ */
+ public int minimumValue()
+ {
+ int minimumValue = Integer.MAX_VALUE;
+
+ if (values != null)
+ {
+ for (int index = 0; index < values.length; index++)
+ {
+ int value = values[index];
+
+ if (minimumValue > value)
+ {
+ minimumValue = value;
+ }
+ }
+ }
+
+ return minimumValue;
+ }
+
+
+ /**
+ * Returns the maximum value from this list of instruction offsets.
+ * Returns <code>Integer.MIN_VALUE</code> if the list is empty.
+ */
+ public int maximumValue()
+ {
+ int maximumValue = Integer.MIN_VALUE;
+
+ if (values != null)
+ {
+ for (int index = 0; index < values.length; index++)
+ {
+ int value = values[index];
+
+ if (maximumValue < value)
+ {
+ maximumValue = value;
+ }
+ }
+ }
+
+ return maximumValue;
+ }
+
+
+ /**
+ * Returns the generalization of this InstructionOffsetValue and the given
+ * other InstructionOffsetValue. The values of the other InstructionOffsetValue
+ * are guaranteed to remain at the end of the list, in the same order.
+ */
+ public final Value generalize(InstructionOffsetValue other)
+ {
+ // If the values array of either is null, we can return the other one.
+ int[] thisValues = this.values;
+ if (thisValues == null)
+ {
+ return other;
+ }
+
+ int[] otherValues = other.values;
+ if (otherValues == null)
+ {
+ return this;
+ }
+
+ // Compute the length of the union of the arrays.
+ int newLength = thisValues.length;
+ for (int index = 0; index < otherValues.length; index++)
+ {
+ if (!this.contains(otherValues[index]))
+ {
+ newLength++;
+ }
+ }
+
+ // If the length of the union array is equal to the length of the other
+ // values array, we can return it.
+ if (newLength == otherValues.length)
+ {
+ return other;
+ }
+
+ // If the length of the union array is equal to the length of this
+ // values array, we can return it. We have to make sure that the other
+ // values are at the end. We'll just test one special case, with a
+ // single other value.
+ if (newLength == this.values.length &&
+ otherValues.length == 1 &&
+ thisValues[thisValues.length-1] == otherValues[0])
+ {
+ return this;
+ }
+
+ // Create the union array.
+ int newIndex = 0;
+ int[] newValues = new int[newLength];
+
+ // Is the length of the union array is equal to the sum of the lengths?
+ if (newLength == thisValues.length + otherValues.length)
+ {
+ // We can just copy all values, because they are unique.
+ System.arraycopy(thisValues, 0, newValues, 0, thisValues.length);
+
+ newIndex = thisValues.length;
+ }
+ else
+ {
+ // Copy the values that are different from the other array.
+ for (int index = 0; index < thisValues.length; index++)
+ {
+ if (!other.contains(thisValues[index]))
+ {
+ newValues[newIndex++] = thisValues[index];
+ }
+ }
+ }
+
+ // Copy the values from the other array.
+ System.arraycopy(otherValues, 0, newValues, newIndex, otherValues.length);
+
+ return new InstructionOffsetValue(newValues);
+ }
+
+
+ // Implementations for Value.
+
+ public final InstructionOffsetValue instructionOffsetValue()
+ {
+ return this;
+ }
+
+ public boolean isSpecific()
+ {
+ return true;
+ }
+
+ public boolean isParticular()
+ {
+ return true;
+ }
+
+ public final Value generalize(Value other)
+ {
+ return this.generalize(other.instructionOffsetValue());
+ }
+
+ public final int computationalType()
+ {
+ return TYPE_INSTRUCTION_OFFSET;
+ }
+
+ public final String internalType()
+ {
+ return String.valueOf(ClassConstants.TYPE_INT);
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (object == null ||
+ this.getClass() != object.getClass())
+ {
+ return false;
+ }
+
+ InstructionOffsetValue other = (InstructionOffsetValue)object;
+ if (this.values == other.values)
+ {
+ return true;
+ }
+
+ if (this.values == null ||
+ other.values == null ||
+ this.values.length != other.values.length)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < other.values.length; index++)
+ {
+ if (!this.contains(other.values[index]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ public int hashCode()
+ {
+ int hashCode = this.getClass().hashCode();
+
+ if (values != null)
+ {
+ for (int index = 0; index < values.length; index++)
+ {
+ hashCode ^= values[index];
+ }
+ }
+
+ return hashCode;
+ }
+
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ if (values != null)
+ {
+ for (int index = 0; index < values.length; index++)
+ {
+ if (index > 0)
+ {
+ buffer.append(',');
+ }
+ buffer.append(values[index]);
+ }
+ }
+
+ return buffer.append(':').toString();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IntegerValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IntegerValue.java
new file mode 100644
index 0000000000..ecc68b0759
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/IntegerValue.java
@@ -0,0 +1,1002 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.ClassConstants;
+
+/**
+ * This class represents a partially evaluated integer value.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class IntegerValue extends Category1Value
+{
+ /**
+ * Returns the specific integer value, if applicable.
+ */
+ public int value()
+ {
+ return 0;
+ }
+
+
+ // Basic unary methods.
+
+ /**
+ * Returns the negated value of this IntegerValue.
+ */
+ public abstract IntegerValue negate();
+
+ /**
+ * Converts this IntegerValue to a byte IntegerValue.
+ */
+ public abstract IntegerValue convertToByte();
+
+ /**
+ * Converts this IntegerValue to a character IntegerValue.
+ */
+ public abstract IntegerValue convertToCharacter();
+
+ /**
+ * Converts this IntegerValue to a short IntegerValue.
+ */
+ public abstract IntegerValue convertToShort();
+
+ /**
+ * Converts this IntegerValue to a LongValue.
+ */
+ public abstract LongValue convertToLong();
+
+ /**
+ * Converts this IntegerValue to a FloatValue.
+ */
+ public abstract FloatValue convertToFloat();
+
+ /**
+ * Converts this IntegerValue to a DoubleValue.
+ */
+ public abstract DoubleValue convertToDouble();
+
+
+ // Basic binary methods.
+
+ /**
+ * Returns the generalization of this IntegerValue and the given other
+ * IntegerValue.
+ */
+ public abstract IntegerValue generalize(IntegerValue other);
+
+ /**
+ * Returns the sum of this IntegerValue and the given IntegerValue.
+ */
+ public abstract IntegerValue add(IntegerValue other);
+
+ /**
+ * Returns the difference of this IntegerValue and the given IntegerValue.
+ */
+ public abstract IntegerValue subtract(IntegerValue other);
+
+ /**
+ * Returns the difference of the given IntegerValue and this IntegerValue.
+ */
+ public abstract IntegerValue subtractFrom(IntegerValue other);
+
+ /**
+ * Returns the product of this IntegerValue and the given IntegerValue.
+ */
+ public abstract IntegerValue multiply(IntegerValue other)
+ throws ArithmeticException;
+
+ /**
+ * Returns the quotient of this IntegerValue and the given IntegerValue.
+ */
+ public abstract IntegerValue divide(IntegerValue other)
+ throws ArithmeticException;
+
+ /**
+ * Returns the quotient of the given IntegerValue and this IntegerValue.
+ */
+ public abstract IntegerValue divideOf(IntegerValue other)
+ throws ArithmeticException;
+
+ /**
+ * Returns the remainder of this IntegerValue divided by the given
+ * IntegerValue.
+ */
+ public abstract IntegerValue remainder(IntegerValue other)
+ throws ArithmeticException;
+
+ /**
+ * Returns the remainder of the given IntegerValue divided by this
+ * IntegerValue.
+ */
+ public abstract IntegerValue remainderOf(IntegerValue other)
+ throws ArithmeticException;
+
+ /**
+ * Returns this IntegerValue, shifted left by the given IntegerValue.
+ */
+ public abstract IntegerValue shiftLeft(IntegerValue other);
+
+ /**
+ * Returns this IntegerValue, shifted right by the given IntegerValue.
+ */
+ public abstract IntegerValue shiftRight(IntegerValue other);
+
+ /**
+ * Returns this unsigned IntegerValue, shifted left by the given
+ * IntegerValue.
+ */
+ public abstract IntegerValue unsignedShiftRight(IntegerValue other);
+
+ /**
+ * Returns the given IntegerValue, shifted left by this IntegerValue.
+ */
+ public abstract IntegerValue shiftLeftOf(IntegerValue other);
+
+ /**
+ * Returns the given IntegerValue, shifted right by this IntegerValue.
+ */
+ public abstract IntegerValue shiftRightOf(IntegerValue other);
+
+ /**
+ * Returns the given unsigned IntegerValue, shifted left by this
+ * IntegerValue.
+ */
+ public abstract IntegerValue unsignedShiftRightOf(IntegerValue other);
+
+ /**
+ * Returns the given LongValue, shifted left by this IntegerValue.
+ */
+ public abstract LongValue shiftLeftOf(LongValue other);
+
+ /**
+ * Returns the given LongValue, shifted right by this IntegerValue.
+ */
+ public abstract LongValue shiftRightOf(LongValue other);
+
+ /**
+ * Returns the given unsigned LongValue, shifted right by this IntegerValue.
+ */
+ public abstract LongValue unsignedShiftRightOf(LongValue other);
+
+ /**
+ * Returns the logical <i>and</i> of this IntegerValue and the given
+ * IntegerValue.
+ */
+ public abstract IntegerValue and(IntegerValue other);
+
+ /**
+ * Returns the logical <i>or</i> of this IntegerValue and the given
+ * IntegerValue.
+ */
+ public abstract IntegerValue or(IntegerValue other);
+
+ /**
+ * Returns the logical <i>xor</i> of this IntegerValue and the given
+ * IntegerValue.
+ */
+ public abstract IntegerValue xor(IntegerValue other);
+
+ /**
+ * Returns whether this IntegerValue and the given IntegerValue are equal:
+ * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public abstract int equal(IntegerValue other);
+
+ /**
+ * Returns whether this IntegerValue is less than the given IntegerValue:
+ * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public abstract int lessThan(IntegerValue other);
+
+ /**
+ * Returns whether this IntegerValue is less than or equal to the given
+ * IntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public abstract int lessThanOrEqual(IntegerValue other);
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns whether this IntegerValue and the given IntegerValue are different:
+ * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public final int notEqual(IntegerValue other)
+ {
+ return -equal(other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is greater than the given IntegerValue:
+ * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public final int greaterThan(IntegerValue other)
+ {
+ return -lessThanOrEqual(other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is greater than or equal to the given IntegerValue:
+ * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public final int greaterThanOrEqual(IntegerValue other)
+ {
+ return -lessThan(other);
+ }
+
+
+ // Similar binary methods, but this time with unknown arguments.
+
+ /**
+ * Returns the generalization of this IntegerValue and the given other
+ * UnknownIntegerValue.
+ */
+ public IntegerValue generalize(UnknownIntegerValue other)
+ {
+ return generalize((IntegerValue)other);
+ }
+
+
+ /**
+ * Returns the sum of this IntegerValue and the given UnknownIntegerValue.
+ */
+ public IntegerValue add(UnknownIntegerValue other)
+ {
+ return add((IntegerValue)other);
+ }
+
+ /**
+ * Returns the difference of this IntegerValue and the given UnknownIntegerValue.
+ */
+ public IntegerValue subtract(UnknownIntegerValue other)
+ {
+ return subtract((IntegerValue)other);
+ }
+
+ /**
+ * Returns the difference of the given UnknownIntegerValue and this IntegerValue.
+ */
+ public IntegerValue subtractFrom(UnknownIntegerValue other)
+ {
+ return subtractFrom((IntegerValue)other);
+ }
+
+ /**
+ * Returns the product of this IntegerValue and the given UnknownIntegerValue.
+ */
+ public IntegerValue multiply(UnknownIntegerValue other)
+ {
+ return multiply((IntegerValue)other);
+ }
+
+ /**
+ * Returns the quotient of this IntegerValue and the given
+ * UnknownIntegerValue.
+ */
+ public IntegerValue divide(UnknownIntegerValue other)
+ {
+ return divide((IntegerValue)other);
+ }
+
+ /**
+ * Returns the quotient of the given UnknownIntegerValue and this
+ * IntegerValue.
+ */
+ public IntegerValue divideOf(UnknownIntegerValue other)
+ {
+ return divideOf((IntegerValue)other);
+ }
+
+ /**
+ * Returns the remainder of this IntegerValue divided by the given
+ * UnknownIntegerValue.
+ */
+ public IntegerValue remainder(UnknownIntegerValue other)
+ {
+ return remainder((IntegerValue)other);
+ }
+
+ /**
+ * Returns the remainder of the given UnknownIntegerValue divided by this
+ * IntegerValue.
+ */
+ public IntegerValue remainderOf(UnknownIntegerValue other)
+ {
+ return remainderOf((IntegerValue)other);
+ }
+
+ /**
+ * Returns this IntegerValue, shifted left by the given UnknownIntegerValue.
+ */
+ public IntegerValue shiftLeft(UnknownIntegerValue other)
+ {
+ return shiftLeft((IntegerValue)other);
+ }
+
+ /**
+ * Returns this IntegerValue, shifted right by the given UnknownIntegerValue.
+ */
+ public IntegerValue shiftRight(UnknownIntegerValue other)
+ {
+ return shiftRight((IntegerValue)other);
+ }
+
+ /**
+ * Returns this unsigned IntegerValue, shifted right by the given
+ * UnknownIntegerValue.
+ */
+ public IntegerValue unsignedShiftRight(UnknownIntegerValue other)
+ {
+ return unsignedShiftRight((IntegerValue)other);
+ }
+
+ /**
+ * Returns the given UnknownIntegerValue, shifted left by this IntegerValue.
+ */
+ public IntegerValue shiftLeftOf(UnknownIntegerValue other)
+ {
+ return shiftLeftOf((IntegerValue)other);
+ }
+
+ /**
+ * Returns the given UnknownIntegerValue, shifted right by this IntegerValue.
+ */
+ public IntegerValue shiftRightOf(UnknownIntegerValue other)
+ {
+ return shiftRightOf((IntegerValue)other);
+ }
+
+ /**
+ * Returns the given unsigned UnknownIntegerValue, shifted right by this
+ * IntegerValue.
+ */
+ public IntegerValue unsignedShiftRightOf(UnknownIntegerValue other)
+ {
+ return unsignedShiftRightOf((IntegerValue)other);
+ }
+
+ /**
+ * Returns the given UnknownLongValue, shifted left by this IntegerValue.
+ */
+ public LongValue shiftLeftOf(UnknownLongValue other)
+ {
+ return shiftLeftOf((LongValue)other);
+ }
+
+ /**
+ * Returns the given UnknownLongValue, shifted right by this IntegerValue.
+ */
+ public LongValue shiftRightOf(UnknownLongValue other)
+ {
+ return shiftRightOf((LongValue)other);
+ }
+
+ /**
+ * Returns the given unsigned UnknownLongValue, shifted right by this
+ * IntegerValue.
+ */
+ public LongValue unsignedShiftRightOf(UnknownLongValue other)
+ {
+ return unsignedShiftRightOf((LongValue)other);
+ }
+
+ /**
+ * Returns the logical <i>and</i> of this IntegerValue and the given
+ * UnknownIntegerValue.
+ */
+ public IntegerValue and(UnknownIntegerValue other)
+ {
+ return and((IntegerValue)other);
+ }
+
+ /**
+ * Returns the logical <i>or</i> of this IntegerValue and the given
+ * UnknownIntegerValue.
+ */
+ public IntegerValue or(UnknownIntegerValue other)
+ {
+ return or((IntegerValue)other);
+ }
+
+ /**
+ * Returns the logical <i>xor</i> of this IntegerValue and the given
+ * UnknownIntegerValue.
+ */
+ public IntegerValue xor(UnknownIntegerValue other)
+ {
+ return xor((IntegerValue)other);
+ }
+
+ /**
+ * Returns whether this IntegerValue and the given UnknownIntegerValue are
+ * equal: <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public int equal(UnknownIntegerValue other)
+ {
+ return equal((IntegerValue)other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is less than the given
+ * UnknownIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public int lessThan(UnknownIntegerValue other)
+ {
+ return lessThan((IntegerValue)other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is less than or equal to the given
+ * UnknownIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public int lessThanOrEqual(UnknownIntegerValue other)
+ {
+ return lessThanOrEqual((IntegerValue)other);
+ }
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns whether this IntegerValue and the given UnknownIntegerValue are
+ * different: <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public final int notEqual(UnknownIntegerValue other)
+ {
+ return -equal(other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is greater than the given
+ * UnknownIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public final int greaterThan(UnknownIntegerValue other)
+ {
+ return -lessThanOrEqual(other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is greater than or equal to the given
+ * UnknownIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public final int greaterThanOrEqual(UnknownIntegerValue other)
+ {
+ return -lessThan(other);
+ }
+
+
+ // Similar binary methods, but this time with specific arguments.
+
+ /**
+ * Returns the generalization of this IntegerValue and the given other
+ * SpecificIntegerValue.
+ */
+ public IntegerValue generalize(SpecificIntegerValue other)
+ {
+ return generalize((IntegerValue)other);
+ }
+
+
+ /**
+ * Returns the sum of this IntegerValue and the given SpecificIntegerValue.
+ */
+ public IntegerValue add(SpecificIntegerValue other)
+ {
+ return add((IntegerValue)other);
+ }
+
+ /**
+ * Returns the difference of this IntegerValue and the given SpecificIntegerValue.
+ */
+ public IntegerValue subtract(SpecificIntegerValue other)
+ {
+ return subtract((IntegerValue)other);
+ }
+
+ /**
+ * Returns the difference of the given SpecificIntegerValue and this IntegerValue.
+ */
+ public IntegerValue subtractFrom(SpecificIntegerValue other)
+ {
+ return subtractFrom((IntegerValue)other);
+ }
+
+ /**
+ * Returns the product of this IntegerValue and the given SpecificIntegerValue.
+ */
+ public IntegerValue multiply(SpecificIntegerValue other)
+ {
+ return multiply((IntegerValue)other);
+ }
+
+ /**
+ * Returns the quotient of this IntegerValue and the given
+ * SpecificIntegerValue.
+ */
+ public IntegerValue divide(SpecificIntegerValue other)
+ {
+ return divide((IntegerValue)other);
+ }
+
+ /**
+ * Returns the quotient of the given SpecificIntegerValue and this
+ * IntegerValue.
+ */
+ public IntegerValue divideOf(SpecificIntegerValue other)
+ {
+ return divideOf((IntegerValue)other);
+ }
+
+ /**
+ * Returns the remainder of this IntegerValue divided by the given
+ * SpecificIntegerValue.
+ */
+ public IntegerValue remainder(SpecificIntegerValue other)
+ {
+ return remainder((IntegerValue)other);
+ }
+
+ /**
+ * Returns the remainder of the given SpecificIntegerValue divided by this
+ * IntegerValue.
+ */
+ public IntegerValue remainderOf(SpecificIntegerValue other)
+ {
+ return remainderOf((IntegerValue)other);
+ }
+
+ /**
+ * Returns this IntegerValue, shifted left by the given SpecificIntegerValue.
+ */
+ public IntegerValue shiftLeft(SpecificIntegerValue other)
+ {
+ return shiftLeft((IntegerValue)other);
+ }
+
+ /**
+ * Returns this IntegerValue, shifted right by the given SpecificIntegerValue.
+ */
+ public IntegerValue shiftRight(SpecificIntegerValue other)
+ {
+ return shiftRight((IntegerValue)other);
+ }
+
+ /**
+ * Returns this unsigned IntegerValue, shifted right by the given
+ * SpecificIntegerValue.
+ */
+ public IntegerValue unsignedShiftRight(SpecificIntegerValue other)
+ {
+ return unsignedShiftRight((IntegerValue)other);
+ }
+
+ /**
+ * Returns the given SpecificIntegerValue, shifted left by this IntegerValue.
+ */
+ public IntegerValue shiftLeftOf(SpecificIntegerValue other)
+ {
+ return shiftLeftOf((IntegerValue)other);
+ }
+
+ /**
+ * Returns the given SpecificIntegerValue, shifted right by this IntegerValue.
+ */
+ public IntegerValue shiftRightOf(SpecificIntegerValue other)
+ {
+ return shiftRightOf((IntegerValue)other);
+ }
+
+ /**
+ * Returns the given unsigned SpecificIntegerValue, shifted right by this
+ * IntegerValue.
+ */
+ public IntegerValue unsignedShiftRightOf(SpecificIntegerValue other)
+ {
+ return unsignedShiftRightOf((IntegerValue)other);
+ }
+
+ /**
+ * Returns the given SpecificLongValue, shifted left by this IntegerValue.
+ */
+ public LongValue shiftLeftOf(SpecificLongValue other)
+ {
+ return shiftLeftOf((LongValue)other);
+ }
+
+ /**
+ * Returns the given SpecificLongValue, shifted right by this IntegerValue.
+ */
+ public LongValue shiftRightOf(SpecificLongValue other)
+ {
+ return shiftRightOf((LongValue)other);
+ }
+
+ /**
+ * Returns the given unsigned SpecificLongValue, shifted right by this
+ * IntegerValue.
+ */
+ public LongValue unsignedShiftRightOf(SpecificLongValue other)
+ {
+ return unsignedShiftRightOf((LongValue)other);
+ }
+
+ /**
+ * Returns the logical <i>and</i> of this IntegerValue and the given
+ * SpecificIntegerValue.
+ */
+ public IntegerValue and(SpecificIntegerValue other)
+ {
+ return and((IntegerValue)other);
+ }
+
+ /**
+ * Returns the logical <i>or</i> of this IntegerValue and the given
+ * SpecificIntegerValue.
+ */
+ public IntegerValue or(SpecificIntegerValue other)
+ {
+ return or((IntegerValue)other);
+ }
+
+ /**
+ * Returns the logical <i>xor</i> of this IntegerValue and the given
+ * SpecificIntegerValue.
+ */
+ public IntegerValue xor(SpecificIntegerValue other)
+ {
+ return xor((IntegerValue)other);
+ }
+
+ /**
+ * Returns whether this IntegerValue and the given SpecificIntegerValue are
+ * equal: <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public int equal(SpecificIntegerValue other)
+ {
+ return equal((IntegerValue)other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is less than the given
+ * SpecificIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public int lessThan(SpecificIntegerValue other)
+ {
+ return lessThan((IntegerValue)other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is less than or equal to the given
+ * SpecificIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public int lessThanOrEqual(SpecificIntegerValue other)
+ {
+ return lessThanOrEqual((IntegerValue)other);
+ }
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns whether this IntegerValue and the given SpecificIntegerValue are
+ * different: <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public final int notEqual(SpecificIntegerValue other)
+ {
+ return -equal(other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is greater than the given
+ * SpecificIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public final int greaterThan(SpecificIntegerValue other)
+ {
+ return -lessThanOrEqual(other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is greater than or equal to the given
+ * SpecificIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public final int greaterThanOrEqual(SpecificIntegerValue other)
+ {
+ return -lessThan(other);
+ }
+
+
+ // Similar binary methods, but this time with particular arguments.
+
+ /**
+ * Returns the generalization of this IntegerValue and the given other
+ * ParticularIntegerValue.
+ */
+ public IntegerValue generalize(ParticularIntegerValue other)
+ {
+ return generalize((SpecificIntegerValue)other);
+ }
+
+
+ /**
+ * Returns the sum of this IntegerValue and the given ParticularIntegerValue.
+ */
+ public IntegerValue add(ParticularIntegerValue other)
+ {
+ return add((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the difference of this IntegerValue and the given ParticularIntegerValue.
+ */
+ public IntegerValue subtract(ParticularIntegerValue other)
+ {
+ return subtract((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the difference of the given ParticularIntegerValue and this IntegerValue.
+ */
+ public IntegerValue subtractFrom(ParticularIntegerValue other)
+ {
+ return subtractFrom((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the product of this IntegerValue and the given ParticularIntegerValue.
+ */
+ public IntegerValue multiply(ParticularIntegerValue other)
+ {
+ return multiply((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the quotient of this IntegerValue and the given
+ * ParticularIntegerValue.
+ */
+ public IntegerValue divide(ParticularIntegerValue other)
+ {
+ return divide((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the quotient of the given ParticularIntegerValue and this
+ * IntegerValue.
+ */
+ public IntegerValue divideOf(ParticularIntegerValue other)
+ {
+ return divideOf((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the remainder of this IntegerValue divided by the given
+ * ParticularIntegerValue.
+ */
+ public IntegerValue remainder(ParticularIntegerValue other)
+ {
+ return remainder((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the remainder of the given ParticularIntegerValue divided by this
+ * IntegerValue.
+ */
+ public IntegerValue remainderOf(ParticularIntegerValue other)
+ {
+ return remainderOf((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns this IntegerValue, shifted left by the given ParticularIntegerValue.
+ */
+ public IntegerValue shiftLeft(ParticularIntegerValue other)
+ {
+ return shiftLeft((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns this IntegerValue, shifted right by the given ParticularIntegerValue.
+ */
+ public IntegerValue shiftRight(ParticularIntegerValue other)
+ {
+ return shiftRight((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns this unsigned IntegerValue, shifted right by the given
+ * ParticularIntegerValue.
+ */
+ public IntegerValue unsignedShiftRight(ParticularIntegerValue other)
+ {
+ return unsignedShiftRight((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the given ParticularIntegerValue, shifted left by this IntegerValue.
+ */
+ public IntegerValue shiftLeftOf(ParticularIntegerValue other)
+ {
+ return shiftLeftOf((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the given ParticularIntegerValue, shifted right by this IntegerValue.
+ */
+ public IntegerValue shiftRightOf(ParticularIntegerValue other)
+ {
+ return shiftRightOf((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the given unsigned ParticularIntegerValue, shifted right by this
+ * IntegerValue.
+ */
+ public IntegerValue unsignedShiftRightOf(ParticularIntegerValue other)
+ {
+ return unsignedShiftRightOf((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the given ParticularLongValue, shifted left by this IntegerValue.
+ */
+ public LongValue shiftLeftOf(ParticularLongValue other)
+ {
+ return shiftLeftOf((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the given ParticularLongValue, shifted right by this IntegerValue.
+ */
+ public LongValue shiftRightOf(ParticularLongValue other)
+ {
+ return shiftRightOf((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the given unsigned ParticularLongValue, shifted right by this
+ * IntegerValue.
+ */
+ public LongValue unsignedShiftRightOf(ParticularLongValue other)
+ {
+ return unsignedShiftRightOf((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the logical <i>and</i> of this IntegerValue and the given
+ * ParticularIntegerValue.
+ */
+ public IntegerValue and(ParticularIntegerValue other)
+ {
+ return and((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the logical <i>or</i> of this IntegerValue and the given
+ * ParticularIntegerValue.
+ */
+ public IntegerValue or(ParticularIntegerValue other)
+ {
+ return or((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the logical <i>xor</i> of this IntegerValue and the given
+ * ParticularIntegerValue.
+ */
+ public IntegerValue xor(ParticularIntegerValue other)
+ {
+ return xor((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns whether this IntegerValue and the given ParticularIntegerValue are
+ * equal: <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public int equal(ParticularIntegerValue other)
+ {
+ return equal((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is less than the given
+ * ParticularIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public int lessThan(ParticularIntegerValue other)
+ {
+ return lessThan((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is less than or equal to the given
+ * ParticularIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public int lessThanOrEqual(ParticularIntegerValue other)
+ {
+ return lessThanOrEqual((SpecificIntegerValue)other);
+ }
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns whether this IntegerValue and the given ParticularIntegerValue are
+ * different: <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public final int notEqual(ParticularIntegerValue other)
+ {
+ return -equal(other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is greater than the given
+ * ParticularIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public final int greaterThan(ParticularIntegerValue other)
+ {
+ return -lessThanOrEqual(other);
+ }
+
+ /**
+ * Returns whether this IntegerValue is greater than or equal to the given
+ * ParticularIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+ * <code>ALWAYS</code>.
+ */
+ public final int greaterThanOrEqual(ParticularIntegerValue other)
+ {
+ return -lessThan(other);
+ }
+
+
+ // Implementations for Value.
+
+ public final IntegerValue integerValue()
+ {
+ return this;
+ }
+
+ public final Value generalize(Value other)
+ {
+ return this.generalize(other.integerValue());
+ }
+
+ public final int computationalType()
+ {
+ return TYPE_INTEGER;
+ }
+
+ public final String internalType()
+ {
+ return String.valueOf(ClassConstants.TYPE_INT);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/LongValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/LongValue.java
new file mode 100644
index 0000000000..be57950305
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/LongValue.java
@@ -0,0 +1,554 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.ClassConstants;
+
+/**
+ * This class represents a partially evaluated long value.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class LongValue extends Category2Value
+{
+ /**
+ * Returns the specific long value, if applicable.
+ */
+ public long value()
+ {
+ return 0;
+ }
+
+
+ // Basic unary methods.
+
+ /**
+ * Returns the negated value of this LongValue.
+ */
+ public abstract LongValue negate();
+
+
+ /**
+ * Converts this LongValue to an IntegerValue.
+ */
+ public abstract IntegerValue convertToInteger();
+
+ /**
+ * Converts this LongValue to a FloatValue.
+ */
+ public abstract FloatValue convertToFloat();
+
+ /**
+ * Converts this LongValue to a DoubleValue.
+ */
+ public abstract DoubleValue convertToDouble();
+
+
+ // Basic binary methods.
+
+ /**
+ * Returns the generalization of this LongValue and the given other
+ * LongValue.
+ */
+ public LongValue generalize(LongValue other)
+ {
+ return other.generalize(this);
+ }
+
+ /**
+ * Returns the sum of this LongValue and the given LongValue.
+ */
+ public LongValue add(LongValue other)
+ {
+ return other.add(this);
+ }
+
+ /**
+ * Returns the difference of this LongValue and the given LongValue.
+ */
+ public LongValue subtract(LongValue other)
+ {
+ return other.subtractFrom(this);
+ }
+
+ /**
+ * Returns the difference of the given LongValue and this LongValue.
+ */
+ public LongValue subtractFrom(LongValue other)
+ {
+ return other.subtract(this);
+ }
+
+ /**
+ * Returns the product of this LongValue and the given LongValue.
+ */
+ public LongValue multiply(LongValue other)
+ throws ArithmeticException
+ {
+ return other.multiply(this);
+ }
+
+ /**
+ * Returns the quotient of this LongValue and the given LongValue.
+ */
+ public LongValue divide(LongValue other)
+ throws ArithmeticException
+ {
+ return other.divideOf(this);
+ }
+
+ /**
+ * Returns the quotient of the given LongValue and this LongValue.
+ */
+ public LongValue divideOf(LongValue other)
+ throws ArithmeticException
+ {
+ return other.divide(this);
+ }
+
+ /**
+ * Returns the remainder of this LongValue divided by the given
+ * LongValue.
+ */
+ public LongValue remainder(LongValue other)
+ throws ArithmeticException
+ {
+ return other.remainderOf(this);
+ }
+
+ /**
+ * Returns the remainder of the given LongValue divided by this
+ * LongValue.
+ */
+ public LongValue remainderOf(LongValue other)
+ throws ArithmeticException
+ {
+ return other.remainder(this);
+ }
+
+ /**
+ * Returns this LongValue, shifted left by the given IntegerValue.
+ */
+ public LongValue shiftLeft(IntegerValue other)
+ {
+ return other.shiftLeftOf(this);
+ }
+
+ /**
+ * Returns this LongValue, shifted right by the given IntegerValue.
+ */
+ public LongValue shiftRight(IntegerValue other)
+ {
+ return other.shiftRightOf(this);
+ }
+
+ /**
+ * Returns this unsigned LongValue, shifted left by the given
+ * IntegerValue.
+ */
+ public LongValue unsignedShiftRight(IntegerValue other)
+ {
+ return other.unsignedShiftRightOf(this);
+ }
+
+ /**
+ * Returns the logical <i>and</i> of this LongValue and the given
+ * LongValue.
+ */
+ public LongValue and(LongValue other)
+ {
+ return other.and(this);
+ }
+
+ /**
+ * Returns the logical <i>or</i> of this LongValue and the given
+ * LongValue.
+ */
+ public LongValue or(LongValue other)
+ {
+ return other.or(this);
+ }
+
+ /**
+ * Returns the logical <i>xor</i> of this LongValue and the given
+ * LongValue.
+ */
+ public LongValue xor(LongValue other)
+ {
+ return other.xor(this);
+ }
+
+ /**
+ * Returns an IntegerValue with value -1, 0, or 1, if this LongValue is
+ * less than, equal to, or greater than the given LongValue, respectively.
+ */
+ public IntegerValue compare(LongValue other)
+ {
+ return other.compareReverse(this);
+ }
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns an IntegerValue with value 1, 0, or -1, if this LongValue is
+ * less than, equal to, or greater than the given LongValue, respectively.
+ */
+ public final IntegerValue compareReverse(LongValue other)
+ {
+ return compare(other).negate();
+ }
+
+
+ // Similar binary methods, but this time with more specific arguments.
+
+ /**
+ * Returns the generalization of this LongValue and the given other
+ * SpecificLongValue.
+ */
+ public LongValue generalize(SpecificLongValue other)
+ {
+ return this;
+ }
+
+
+ /**
+ * Returns the sum of this LongValue and the given SpecificLongValue.
+ */
+ public LongValue add(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns the difference of this LongValue and the given SpecificLongValue.
+ */
+ public LongValue subtract(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns the difference of the given SpecificLongValue and this LongValue.
+ */
+ public LongValue subtractFrom(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns the product of this LongValue and the given SpecificLongValue.
+ */
+ public LongValue multiply(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns the quotient of this LongValue and the given
+ * SpecificLongValue.
+ */
+ public LongValue divide(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns the quotient of the given SpecificLongValue and this
+ * LongValue.
+ */
+ public LongValue divideOf(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns the remainder of this LongValue divided by the given
+ * SpecificLongValue.
+ */
+ public LongValue remainder(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns the remainder of the given SpecificLongValue divided by this
+ * LongValue.
+ */
+ public LongValue remainderOf(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns this LongValue, shifted left by the given SpecificLongValue.
+ */
+ public LongValue shiftLeft(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns this LongValue, shifted right by the given SpecificLongValue.
+ */
+ public LongValue shiftRight(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns this unsigned LongValue, shifted right by the given
+ * SpecificLongValue.
+ */
+ public LongValue unsignedShiftRight(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns the logical <i>and</i> of this LongValue and the given
+ * SpecificLongValue.
+ */
+ public LongValue and(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns the logical <i>or</i> of this LongValue and the given
+ * SpecificLongValue.
+ */
+ public LongValue or(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns the logical <i>xor</i> of this LongValue and the given
+ * SpecificLongValue.
+ */
+ public LongValue xor(SpecificLongValue other)
+ {
+ return this;
+ }
+
+ /**
+ * Returns an IntegerValue with value -1, 0, or 1, if this LongValue is
+ * less than, equal to, or greater than the given SpecificLongValue,
+ * respectively.
+ */
+ public IntegerValue compare(SpecificLongValue other)
+ {
+ return new ComparisonValue(this, other);
+ }
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns an IntegerValue with value 1, 0, or -1, if this LongValue is
+ * less than, equal to, or greater than the given SpecificLongValue,
+ * respectively.
+ */
+ public final IntegerValue compareReverse(SpecificLongValue other)
+ {
+ return compare(other).negate();
+ }
+
+
+ // Similar binary methods, but this time with particular arguments.
+
+ /**
+ * Returns the generalization of this LongValue and the given other
+ * ParticularLongValue.
+ */
+ public LongValue generalize(ParticularLongValue other)
+ {
+ return generalize((SpecificLongValue)other);
+ }
+
+
+ /**
+ * Returns the sum of this LongValue and the given ParticularLongValue.
+ */
+ public LongValue add(ParticularLongValue other)
+ {
+ return add((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the difference of this LongValue and the given ParticularLongValue.
+ */
+ public LongValue subtract(ParticularLongValue other)
+ {
+ return subtract((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the difference of the given ParticularLongValue and this LongValue.
+ */
+ public LongValue subtractFrom(ParticularLongValue other)
+ {
+ return subtractFrom((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the product of this LongValue and the given ParticularLongValue.
+ */
+ public LongValue multiply(ParticularLongValue other)
+ {
+ return multiply((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the quotient of this LongValue and the given
+ * ParticularLongValue.
+ */
+ public LongValue divide(ParticularLongValue other)
+ {
+ return divide((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the quotient of the given ParticularLongValue and this
+ * LongValue.
+ */
+ public LongValue divideOf(ParticularLongValue other)
+ {
+ return divideOf((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the remainder of this LongValue divided by the given
+ * ParticularLongValue.
+ */
+ public LongValue remainder(ParticularLongValue other)
+ {
+ return remainder((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the remainder of the given ParticularLongValue divided by this
+ * LongValue.
+ */
+ public LongValue remainderOf(ParticularLongValue other)
+ {
+ return remainderOf((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns this LongValue, shifted left by the given ParticularIntegerValue.
+ */
+ public LongValue shiftLeft(ParticularIntegerValue other)
+ {
+ return shiftLeft((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns this LongValue, shifted right by the given ParticularIntegerValue.
+ */
+ public LongValue shiftRight(ParticularIntegerValue other)
+ {
+ return shiftRight((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns this unsigned LongValue, shifted right by the given
+ * ParticularIntegerValue.
+ */
+ public LongValue unsignedShiftRight(ParticularIntegerValue other)
+ {
+ return unsignedShiftRight((SpecificIntegerValue)other);
+ }
+
+ /**
+ * Returns the logical <i>and</i> of this LongValue and the given
+ * ParticularLongValue.
+ */
+ public LongValue and(ParticularLongValue other)
+ {
+ return and((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the logical <i>or</i> of this LongValue and the given
+ * ParticularLongValue.
+ */
+ public LongValue or(ParticularLongValue other)
+ {
+ return or((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns the logical <i>xor</i> of this LongValue and the given
+ * ParticularLongValue.
+ */
+ public LongValue xor(ParticularLongValue other)
+ {
+ return xor((SpecificLongValue)other);
+ }
+
+ /**
+ * Returns an IntegerValue with value -1, 0, or 1, if this LongValue is
+ * less than, equal to, or greater than the given ParticularLongValue,
+ * respectively.
+ */
+ public IntegerValue compare(ParticularLongValue other)
+ {
+ return compare((SpecificLongValue)other);
+ }
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns an IntegerValue with value 1, 0, or -1, if this LongValue is
+ * less than, equal to, or greater than the given ParticularLongValue,
+ * respectively.
+ */
+ public final IntegerValue compareReverse(ParticularLongValue other)
+ {
+ return compare(other).negate();
+ }
+
+
+ // Implementations for Value.
+
+ public final LongValue longValue()
+ {
+ return this;
+ }
+
+ public final Value generalize(Value other)
+ {
+ return this.generalize(other.longValue());
+ }
+
+ public final int computationalType()
+ {
+ return TYPE_LONG;
+ }
+
+ public final String internalType()
+ {
+ return String.valueOf(ClassConstants.TYPE_INT);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedDoubleValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedDoubleValue.java
new file mode 100644
index 0000000000..f26e8fc7f3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedDoubleValue.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This DoubleValue represents a double value that is negated.
+ *
+ * @author Eric Lafortune
+ */
+final class NegatedDoubleValue extends SpecificDoubleValue
+{
+ private final DoubleValue doubleValue;
+
+
+ /**
+ * Creates a new negated double value of the given double value.
+ */
+ public NegatedDoubleValue(DoubleValue doubleValue)
+ {
+ this.doubleValue = doubleValue;
+ }
+
+
+ // Implementations of unary methods of DoubleValue.
+
+ public DoubleValue negate()
+ {
+ return doubleValue;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.doubleValue.equals(((NegatedDoubleValue)object).doubleValue);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ doubleValue.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "-"+doubleValue;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedFloatValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedFloatValue.java
new file mode 100644
index 0000000000..0443a0961f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedFloatValue.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This FloatValue represents a float value that is negated.
+ *
+ * @author Eric Lafortune
+ */
+final class NegatedFloatValue extends SpecificFloatValue
+{
+ private final FloatValue floatValue;
+
+
+ /**
+ * Creates a new negated float value of the given float value.
+ */
+ public NegatedFloatValue(FloatValue floatValue)
+ {
+ this.floatValue = floatValue;
+ }
+
+
+ // Implementations of unary methods of FloatValue.
+
+ public FloatValue negate()
+ {
+ return floatValue;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.floatValue.equals(((NegatedFloatValue)object).floatValue);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ floatValue.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "-"+floatValue;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedIntegerValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedIntegerValue.java
new file mode 100644
index 0000000000..746c906174
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedIntegerValue.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This IntegerValue represents a integer value that is negated.
+ *
+ * @author Eric Lafortune
+ */
+final class NegatedIntegerValue extends SpecificIntegerValue
+{
+ private final IntegerValue integerValue;
+
+
+ /**
+ * Creates a new negated integer value of the given integer value.
+ */
+ public NegatedIntegerValue(IntegerValue integerValue)
+ {
+ this.integerValue = integerValue;
+ }
+
+
+ // Implementations of unary methods of IntegerValue.
+
+ public IntegerValue negate()
+ {
+ return integerValue;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.integerValue.equals(((NegatedIntegerValue)object).integerValue);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ integerValue.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "-"+integerValue;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedLongValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedLongValue.java
new file mode 100644
index 0000000000..c23cc31c6a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/NegatedLongValue.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This LongValue represents a long value that is negated.
+ *
+ * @author Eric Lafortune
+ */
+final class NegatedLongValue extends SpecificLongValue
+{
+ private final LongValue longValue;
+
+
+ /**
+ * Creates a new negated long value of the given long value.
+ */
+ public NegatedLongValue(LongValue longValue)
+ {
+ this.longValue = longValue;
+ }
+
+
+ // Implementations of unary methods of LongValue.
+
+ public LongValue negate()
+ {
+ return longValue;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return this == object ||
+ super.equals(object) &&
+ this.longValue.equals(((NegatedLongValue)object).longValue);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ longValue.hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "-"+longValue;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularDoubleValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularDoubleValue.java
new file mode 100644
index 0000000000..f61628f242
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularDoubleValue.java
@@ -0,0 +1,221 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This DoubleValue represents a particular double value.
+ *
+ * @author Eric Lafortune
+ */
+final class ParticularDoubleValue extends SpecificDoubleValue
+{
+ private final double value;
+
+
+ /**
+ * Creates a new particular double value.
+ */
+ public ParticularDoubleValue(double value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementations for DoubleValue.
+
+ public double value()
+ {
+ return value;
+ }
+
+
+ // Implementations of unary methods of DoubleValue.
+
+ public DoubleValue negate()
+ {
+ return new ParticularDoubleValue(-value);
+ }
+
+ public IntegerValue convertToInteger()
+ {
+ return new ParticularIntegerValue((int)value);
+ }
+
+ public LongValue convertToLong()
+ {
+ return new ParticularLongValue((long)value);
+ }
+
+ public FloatValue convertToFloat()
+ {
+ return new ParticularFloatValue((float)value);
+ }
+
+
+ // Implementations of binary methods of DoubleValue.
+
+ public DoubleValue generalize(DoubleValue other)
+ {
+ return other.generalize(this);
+ }
+
+ public DoubleValue add(DoubleValue other)
+ {
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.add(this);
+ return other.add(this);
+ }
+
+ public DoubleValue subtract(DoubleValue other)
+ {
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other.negate() : other.subtractFrom(this);
+ return other.subtractFrom(this);
+ }
+
+ public DoubleValue subtractFrom(DoubleValue other)
+ {
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.subtract(this);
+ return other.subtract(this);
+ }
+
+ public DoubleValue multiply(DoubleValue other)
+ {
+ return other.multiply(this);
+ }
+
+ public DoubleValue divide(DoubleValue other)
+ {
+ return other.divideOf(this);
+ }
+
+ public DoubleValue divideOf(DoubleValue other)
+ {
+ return other.divide(this);
+ }
+
+ public DoubleValue remainder(DoubleValue other)
+ {
+ return other.remainderOf(this);
+ }
+
+ public DoubleValue remainderOf(DoubleValue other)
+ {
+ return other.remainder(this);
+ }
+
+ public IntegerValue compare(DoubleValue other)
+ {
+ return other.compareReverse(this);
+ }
+
+
+ // Implementations of binary DoubleValue methods with ParticularDoubleValue
+ // arguments.
+
+ public DoubleValue generalize(ParticularDoubleValue other)
+ {
+ // Also handle NaN and Infinity.
+ return Double.doubleToRawLongBits(this.value) ==
+ Double.doubleToRawLongBits(other.value) ?
+ this : ValueFactory.DOUBLE_VALUE;
+ }
+
+ public DoubleValue add(ParticularDoubleValue other)
+ {
+ return new ParticularDoubleValue(this.value + other.value);
+ }
+
+ public DoubleValue subtract(ParticularDoubleValue other)
+ {
+ return new ParticularDoubleValue(this.value - other.value);
+ }
+
+ public DoubleValue subtractFrom(ParticularDoubleValue other)
+ {
+ return new ParticularDoubleValue(other.value - this.value);
+ }
+
+ public DoubleValue multiply(ParticularDoubleValue other)
+ {
+ return new ParticularDoubleValue(this.value * other.value);
+ }
+
+ public DoubleValue divide(ParticularDoubleValue other)
+ {
+ return new ParticularDoubleValue(this.value / other.value);
+ }
+
+ public DoubleValue divideOf(ParticularDoubleValue other)
+ {
+ return new ParticularDoubleValue(other.value / this.value);
+ }
+
+ public DoubleValue remainder(ParticularDoubleValue other)
+ {
+ return new ParticularDoubleValue(this.value % other.value);
+ }
+
+ public DoubleValue remainderOf(ParticularDoubleValue other)
+ {
+ return new ParticularDoubleValue(other.value % this.value);
+ }
+
+ public IntegerValue compare(ParticularDoubleValue other)
+ {
+ return this.value < other.value ? ParticularValueFactory.INTEGER_VALUE_M1 :
+ this.value == other.value ? ParticularValueFactory.INTEGER_VALUE_0 :
+ ParticularValueFactory.INTEGER_VALUE_1;
+ }
+
+
+ // Implementations for Value.
+
+ public boolean isParticular()
+ {
+ return true;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ // Also handle NaN and Infinity.
+ return super.equals(object) &&
+ Double.doubleToLongBits(this.value) ==
+ Double.doubleToLongBits(((ParticularDoubleValue)object).value);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ (int)Double.doubleToLongBits(value);
+ }
+
+
+ public String toString()
+ {
+ return value+"d";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularFloatValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularFloatValue.java
new file mode 100644
index 0000000000..98875be428
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularFloatValue.java
@@ -0,0 +1,221 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This FloatValue represents a particular float value.
+ *
+ * @author Eric Lafortune
+ */
+final class ParticularFloatValue extends SpecificFloatValue
+{
+ private final float value;
+
+
+ /**
+ * Creates a new particular float value.
+ */
+ public ParticularFloatValue(float value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementations for FloatValue.
+
+ public float value()
+ {
+ return value;
+ }
+
+
+ // Implementations of unary methods of FloatValue.
+
+ public FloatValue negate()
+ {
+ return new ParticularFloatValue(-value);
+ }
+
+ public IntegerValue convertToInteger()
+ {
+ return new ParticularIntegerValue((int)value);
+ }
+
+ public LongValue convertToLong()
+ {
+ return new ParticularLongValue((long)value);
+ }
+
+ public DoubleValue convertToDouble()
+ {
+ return new ParticularDoubleValue((float)value);
+ }
+
+
+ // Implementations of binary methods of FloatValue.
+
+ public FloatValue generalize(FloatValue other)
+ {
+ return other.generalize(this);
+ }
+
+ public FloatValue add(FloatValue other)
+ {
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.add(this);
+ return other.add(this);
+ }
+
+ public FloatValue subtract(FloatValue other)
+ {
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other.negate() : other.subtractFrom(this);
+ return other.subtractFrom(this);
+ }
+
+ public FloatValue subtractFrom(FloatValue other)
+ {
+ // Careful: -0.0 + 0.0 == 0.0
+ //return value == 0.0 ? other : other.subtract(this);
+ return other.subtract(this);
+ }
+
+ public FloatValue multiply(FloatValue other)
+ {
+ return other.multiply(this);
+ }
+
+ public FloatValue divide(FloatValue other)
+ {
+ return other.divideOf(this);
+ }
+
+ public FloatValue divideOf(FloatValue other)
+ {
+ return other.divide(this);
+ }
+
+ public FloatValue remainder(FloatValue other)
+ {
+ return other.remainderOf(this);
+ }
+
+ public FloatValue remainderOf(FloatValue other)
+ {
+ return other.remainder(this);
+ }
+
+ public IntegerValue compare(FloatValue other)
+ {
+ return other.compareReverse(this);
+ }
+
+
+ // Implementations of binary FloatValue methods with ParticularFloatValue
+ // arguments.
+
+ public FloatValue generalize(ParticularFloatValue other)
+ {
+ // Also handle NaN and Infinity.
+ return Float.floatToRawIntBits(this.value) ==
+ Float.floatToRawIntBits(other.value) ?
+ this : ValueFactory.FLOAT_VALUE;
+ }
+
+ public FloatValue add(ParticularFloatValue other)
+ {
+ return new ParticularFloatValue(this.value + other.value);
+ }
+
+ public FloatValue subtract(ParticularFloatValue other)
+ {
+ return new ParticularFloatValue(this.value - other.value);
+ }
+
+ public FloatValue subtractFrom(ParticularFloatValue other)
+ {
+ return new ParticularFloatValue(other.value - this.value);
+ }
+
+ public FloatValue multiply(ParticularFloatValue other)
+ {
+ return new ParticularFloatValue(this.value * other.value);
+ }
+
+ public FloatValue divide(ParticularFloatValue other)
+ {
+ return new ParticularFloatValue(this.value / other.value);
+ }
+
+ public FloatValue divideOf(ParticularFloatValue other)
+ {
+ return new ParticularFloatValue(other.value / this.value);
+ }
+
+ public FloatValue remainder(ParticularFloatValue other)
+ {
+ return new ParticularFloatValue(this.value % other.value);
+ }
+
+ public FloatValue remainderOf(ParticularFloatValue other)
+ {
+ return new ParticularFloatValue(other.value % this.value);
+ }
+
+ public IntegerValue compare(ParticularFloatValue other)
+ {
+ return this.value < other.value ? ParticularValueFactory.INTEGER_VALUE_M1 :
+ this.value == other.value ? ParticularValueFactory.INTEGER_VALUE_0 :
+ ParticularValueFactory.INTEGER_VALUE_1;
+ }
+
+
+ // Implementations for Value.
+
+ public boolean isParticular()
+ {
+ return true;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ // Also handle NaN and Infinity.
+ return super.equals(object) &&
+ Float.floatToIntBits(this.value) ==
+ Float.floatToIntBits(((ParticularFloatValue)object).value);
+ }
+
+
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ Float.floatToIntBits(value);
+ }
+
+
+ public String toString()
+ {
+ return value+"f";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularIntegerValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularIntegerValue.java
new file mode 100644
index 0000000000..95cf5c57cb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularIntegerValue.java
@@ -0,0 +1,383 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This IntegerValue represents a particular integer value.
+ *
+ * @author Eric Lafortune
+ */
+final class ParticularIntegerValue extends SpecificIntegerValue
+{
+ private final int value;
+
+
+ /**
+ * Creates a new particular integer value.
+ */
+ public ParticularIntegerValue(int value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementations for IntegerValue.
+
+ public int value()
+ {
+ return value;
+ }
+
+
+ // Implementations of unary methods of IntegerValue.
+
+ public IntegerValue negate()
+ {
+ return new ParticularIntegerValue(-value);
+ }
+
+ public IntegerValue convertToByte()
+ {
+ int byteValue = (byte)value;
+
+ return byteValue == value ?
+ this :
+ new ParticularIntegerValue(byteValue);
+ }
+
+ public IntegerValue convertToCharacter()
+ {
+ int charValue = (char)value;
+
+ return charValue == value ?
+ this :
+ new ParticularIntegerValue(charValue);
+ }
+
+ public IntegerValue convertToShort()
+ {
+ int shortValue = (short)value;
+
+ return shortValue == value ?
+ this :
+ new ParticularIntegerValue(shortValue);
+ }
+
+ public LongValue convertToLong()
+ {
+ return new ParticularLongValue((long)value);
+ }
+
+ public FloatValue convertToFloat()
+ {
+ return new ParticularFloatValue((float)value);
+ }
+
+ public DoubleValue convertToDouble()
+ {
+ return new ParticularDoubleValue((double)value);
+ }
+
+
+ // Implementations of binary methods of IntegerValue.
+
+ public IntegerValue generalize(IntegerValue other)
+ {
+ return other.generalize(this);
+ }
+
+ public IntegerValue add(IntegerValue other)
+ {
+ return other.add(this);
+ }
+
+ public IntegerValue subtract(IntegerValue other)
+ {
+ return other.subtractFrom(this);
+ }
+
+ public IntegerValue subtractFrom(IntegerValue other)
+ {
+ return other.subtract(this);
+ }
+
+ public IntegerValue multiply(IntegerValue other)
+ {
+ return other.multiply(this);
+ }
+
+ public IntegerValue divide(IntegerValue other)
+ throws ArithmeticException
+ {
+ return other.divideOf(this);
+ }
+
+ public IntegerValue divideOf(IntegerValue other)
+ throws ArithmeticException
+ {
+ return other.divide(this);
+ }
+
+ public IntegerValue remainder(IntegerValue other)
+ throws ArithmeticException
+ {
+ return other.remainderOf(this);
+ }
+
+ public IntegerValue remainderOf(IntegerValue other)
+ throws ArithmeticException
+ {
+ return other.remainder(this);
+ }
+
+ public IntegerValue shiftLeft(IntegerValue other)
+ {
+ return other.shiftLeftOf(this);
+ }
+
+ public IntegerValue shiftLeftOf(IntegerValue other)
+ {
+ return other.shiftLeft(this);
+ }
+
+ public IntegerValue shiftRight(IntegerValue other)
+ {
+ return other.shiftRightOf(this);
+ }
+
+ public IntegerValue shiftRightOf(IntegerValue other)
+ {
+ return other.shiftRight(this);
+ }
+
+ public IntegerValue unsignedShiftRight(IntegerValue other)
+ {
+ return other.unsignedShiftRightOf(this);
+ }
+
+ public IntegerValue unsignedShiftRightOf(IntegerValue other)
+ {
+ return other.unsignedShiftRight(this);
+ }
+
+ public LongValue shiftLeftOf(LongValue other)
+ {
+ return other.shiftLeft(this);
+ }
+
+ public LongValue shiftRightOf(LongValue other)
+ {
+ return other.shiftRight(this);
+ }
+
+ public LongValue unsignedShiftRightOf(LongValue other)
+ {
+ return other.unsignedShiftRight(this);
+ }
+
+ public IntegerValue and(IntegerValue other)
+ {
+ return other.and(this);
+ }
+
+ public IntegerValue or(IntegerValue other)
+ {
+ return other.or(this);
+ }
+
+ public IntegerValue xor(IntegerValue other)
+ {
+ return other.xor(this);
+ }
+
+ public int equal(IntegerValue other)
+ {
+ return other.equal(this);
+ }
+
+ public int lessThan(IntegerValue other)
+ {
+ return other.greaterThan(this);
+ }
+
+ public int lessThanOrEqual(IntegerValue other)
+ {
+ return other.greaterThanOrEqual(this);
+ }
+
+
+ // Implementations of binary IntegerValue methods with ParticularIntegerValue
+ // arguments.
+
+ public IntegerValue generalize(ParticularIntegerValue other)
+ {
+ return generalize((SpecificIntegerValue)other);
+ }
+
+ public IntegerValue add(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(this.value + other.value);
+ }
+
+ public IntegerValue subtract(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(this.value - other.value);
+ }
+
+ public IntegerValue subtractFrom(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(other.value - this.value);
+ }
+
+ public IntegerValue multiply(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(this.value * other.value);
+ }
+
+ public IntegerValue divide(ParticularIntegerValue other)
+ throws ArithmeticException
+ {
+ return new ParticularIntegerValue(this.value / other.value);
+ }
+
+ public IntegerValue divideOf(ParticularIntegerValue other)
+ throws ArithmeticException
+ {
+ return new ParticularIntegerValue(other.value / this.value);
+ }
+
+ public IntegerValue remainder(ParticularIntegerValue other)
+ throws ArithmeticException
+ {
+ return new ParticularIntegerValue(this.value % other.value);
+ }
+
+ public IntegerValue remainderOf(ParticularIntegerValue other)
+ throws ArithmeticException
+ {
+ return new ParticularIntegerValue(other.value % this.value);
+ }
+
+ public IntegerValue shiftLeft(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(this.value << other.value);
+ }
+
+ public IntegerValue shiftRight(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(this.value >> other.value);
+ }
+
+ public IntegerValue unsignedShiftRight(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(this.value >>> other.value);
+ }
+
+ public IntegerValue shiftLeftOf(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(other.value << this.value);
+ }
+
+ public IntegerValue shiftRightOf(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(other.value >> this.value);
+ }
+
+ public IntegerValue unsignedShiftRightOf(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(other.value >>> this.value);
+ }
+
+ public LongValue shiftLeftOf(ParticularLongValue other)
+ {
+ return new ParticularLongValue(other.value() << this.value);
+ }
+
+ public LongValue shiftRightOf(ParticularLongValue other)
+ {
+ return new ParticularLongValue(other.value() >> this.value);
+ }
+
+ public LongValue unsignedShiftRightOf(ParticularLongValue other)
+ {
+ return new ParticularLongValue(other.value() >>> this.value);
+ }
+
+ public IntegerValue and(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(this.value & other.value);
+ }
+
+ public IntegerValue or(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(this.value | other.value);
+ }
+
+ public IntegerValue xor(ParticularIntegerValue other)
+ {
+ return new ParticularIntegerValue(this.value ^ other.value);
+ }
+
+ public int equal(ParticularIntegerValue other)
+ {
+ return this.value == other.value ? ALWAYS : NEVER;
+ }
+
+ public int lessThan(ParticularIntegerValue other)
+ {
+ return this.value < other.value ? ALWAYS : NEVER;
+ }
+
+ public int lessThanOrEqual(ParticularIntegerValue other)
+ {
+ return this.value <= other.value ? ALWAYS : NEVER;
+ }
+
+
+ // Implementations for Value.
+
+ public boolean isParticular()
+ {
+ return true;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return super.equals(object) &&
+ this.value == ((ParticularIntegerValue)object).value;
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode() ^
+ value;
+ }
+
+
+ public String toString()
+ {
+ return Integer.toString(value);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularLongValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularLongValue.java
new file mode 100644
index 0000000000..b733dd90a7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularLongValue.java
@@ -0,0 +1,271 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This LongValue represents a particular long value.
+ *
+ * @author Eric Lafortune
+ */
+final class ParticularLongValue extends SpecificLongValue
+{
+ private final long value;
+
+
+ /**
+ * Creates a new particular long value.
+ */
+ public ParticularLongValue(long value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementations for LongValue.
+
+ public long value()
+ {
+ return value;
+ }
+
+
+ // Implementations of unary methods of LongValue.
+
+ public LongValue negate()
+ {
+ return new ParticularLongValue(-value);
+ }
+
+ public IntegerValue convertToInteger()
+ {
+ return new ParticularIntegerValue((int)value);
+ }
+
+ public FloatValue convertToFloat()
+ {
+ return new ParticularFloatValue((float)value);
+ }
+
+ public DoubleValue convertToDouble()
+ {
+ return new ParticularDoubleValue((double)value);
+ }
+
+
+ // Implementations of binary methods of LongValue.
+
+ public LongValue generalize(LongValue other)
+ {
+ return other.generalize(this);
+ }
+
+ public LongValue add(LongValue other)
+ {
+ return other.add(this);
+ }
+
+ public LongValue subtract(LongValue other)
+ {
+ return other.subtractFrom(this);
+ }
+
+ public LongValue subtractFrom(LongValue other)
+ {
+ return other.subtract(this);
+ }
+
+ public LongValue multiply(LongValue other)
+ {
+ return other.multiply(this);
+ }
+
+ public LongValue divide(LongValue other)
+ throws ArithmeticException
+ {
+ return other.divideOf(this);
+ }
+
+ public LongValue divideOf(LongValue other)
+ throws ArithmeticException
+ {
+ return other.divide(this);
+ }
+
+ public LongValue remainder(LongValue other)
+ throws ArithmeticException
+ {
+ return other.remainderOf(this);
+ }
+
+ public LongValue remainderOf(LongValue other)
+ throws ArithmeticException
+ {
+ return other.remainder(this);
+ }
+
+ public LongValue shiftLeft(IntegerValue other)
+ {
+ return other.shiftLeftOf(this);
+ }
+
+ public LongValue shiftRight(IntegerValue other)
+ {
+ return other.shiftRightOf(this);
+ }
+
+ public LongValue unsignedShiftRight(IntegerValue other)
+ {
+ return other.unsignedShiftRightOf(this);
+ }
+
+ public LongValue and(LongValue other)
+ {
+ return other.and(this);
+ }
+
+ public LongValue or(LongValue other)
+ {
+ return other.or(this);
+ }
+
+ public LongValue xor(LongValue other)
+ {
+ return other.xor(this);
+ }
+
+ public IntegerValue compare(LongValue other)
+ {
+ return other.compareReverse(this);
+ }
+
+
+ // Implementations of binary LongValue methods with ParticularLongValue
+ // arguments.
+
+ public LongValue generalize(ParticularLongValue other)
+ {
+ return generalize((SpecificLongValue)other);
+ }
+
+ public LongValue add(ParticularLongValue other)
+ {
+ return new ParticularLongValue(this.value + other.value);
+ }
+
+ public LongValue subtract(ParticularLongValue other)
+ {
+ return new ParticularLongValue(this.value - other.value);
+ }
+
+ public LongValue subtractFrom(ParticularLongValue other)
+ {
+ return new ParticularLongValue(other.value - this.value);
+ }
+
+ public LongValue multiply(ParticularLongValue other)
+ {
+ return new ParticularLongValue(this.value * other.value);
+ }
+
+ public LongValue divide(ParticularLongValue other)
+ throws ArithmeticException
+ {
+ return new ParticularLongValue(this.value / other.value);
+ }
+
+ public LongValue divideOf(ParticularLongValue other)
+ throws ArithmeticException
+ {
+ return new ParticularLongValue(other.value / this.value);
+ }
+
+ public LongValue remainder(ParticularLongValue other)
+ throws ArithmeticException
+ {
+ return new ParticularLongValue(this.value % other.value);
+ }
+
+ public LongValue remainderOf(ParticularLongValue other)
+ throws ArithmeticException
+ {
+ return new ParticularLongValue(other.value % this.value);
+ }
+
+ public LongValue shiftLeft(ParticularIntegerValue other)
+ {
+ return new ParticularLongValue(this.value << other.value());
+ }
+
+ public LongValue shiftRight(ParticularIntegerValue other)
+ {
+ return new ParticularLongValue(this.value >> other.value());
+ }
+
+ public LongValue unsignedShiftRight(ParticularIntegerValue other)
+ {
+ return new ParticularLongValue(this.value >>> other.value());
+ }
+
+ public LongValue and(ParticularLongValue other)
+ {
+ return new ParticularLongValue(this.value & other.value);
+ }
+
+ public LongValue or(ParticularLongValue other)
+ {
+ return new ParticularLongValue(this.value | other.value);
+ }
+
+ public LongValue xor(ParticularLongValue other)
+ {
+ return new ParticularLongValue(this.value ^ other.value);
+ }
+
+
+ // Implementations for Value.
+
+ public boolean isParticular()
+ {
+ return true;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return super.equals(object) &&
+ this.value == ((ParticularLongValue)object).value;
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode() ^
+ (int)value;
+ }
+
+
+ public String toString()
+ {
+ return value+"L";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularValueFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularValueFactory.java
new file mode 100644
index 0000000000..294ab1b3a5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ParticularValueFactory.java
@@ -0,0 +1,111 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.*;
+
+/**
+ * This value factory creates particular values.
+ *
+ * @author Eric Lafortune
+ */
+public class ParticularValueFactory
+extends ValueFactory
+{
+ // Shared copies of Value objects, to avoid creating a lot of objects.
+ static final IntegerValue INTEGER_VALUE_M1 = new ParticularIntegerValue(-1);
+ static final IntegerValue INTEGER_VALUE_0 = new ParticularIntegerValue(0);
+ static final IntegerValue INTEGER_VALUE_1 = new ParticularIntegerValue(1);
+ static final IntegerValue INTEGER_VALUE_2 = new ParticularIntegerValue(2);
+ static final IntegerValue INTEGER_VALUE_3 = new ParticularIntegerValue(3);
+ static final IntegerValue INTEGER_VALUE_4 = new ParticularIntegerValue(4);
+ static final IntegerValue INTEGER_VALUE_5 = new ParticularIntegerValue(5);
+ static final LongValue LONG_VALUE_0 = new ParticularLongValue(0);
+ static final LongValue LONG_VALUE_1 = new ParticularLongValue(1);
+ static final FloatValue FLOAT_VALUE_0 = new ParticularFloatValue(0.0f);
+ static final FloatValue FLOAT_VALUE_1 = new ParticularFloatValue(1.0f);
+ static final FloatValue FLOAT_VALUE_2 = new ParticularFloatValue(2.0f);
+ static final DoubleValue DOUBLE_VALUE_0 = new ParticularDoubleValue(0.0);
+ static final DoubleValue DOUBLE_VALUE_1 = new ParticularDoubleValue(1.0);
+
+
+ private static int POS_ZERO_FLOAT_BITS = Float.floatToIntBits(0.0f);
+ private static long POS_ZERO_DOUBLE_BITS = Double.doubleToLongBits(0.0);
+
+
+ // Implementations for ValueFactory.
+
+ public IntegerValue createIntegerValue(int value)
+ {
+ switch (value)
+ {
+ case -1: return INTEGER_VALUE_M1;
+ case 0: return INTEGER_VALUE_0;
+ case 1: return INTEGER_VALUE_1;
+ case 2: return INTEGER_VALUE_2;
+ case 3: return INTEGER_VALUE_3;
+ case 4: return INTEGER_VALUE_4;
+ case 5: return INTEGER_VALUE_5;
+ default: return new ParticularIntegerValue(value);
+ }
+ }
+
+
+ public LongValue createLongValue(long value)
+ {
+ return value == 0L ? LONG_VALUE_0 :
+ value == 1L ? LONG_VALUE_1 :
+ new ParticularLongValue(value);
+ }
+
+
+ public FloatValue createFloatValue(float value)
+ {
+ // Make sure to distinguish between +0.0 and -0.0.
+ return value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS
+ ? FLOAT_VALUE_0 :
+ value == 1.0f ? FLOAT_VALUE_1 :
+ value == 2.0f ? FLOAT_VALUE_2 :
+ new ParticularFloatValue(value);
+ }
+
+
+ public DoubleValue createDoubleValue(double value)
+ {
+ // Make sure to distinguish between +0.0 and -0.0.
+ return value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS
+ ? DOUBLE_VALUE_0 :
+ value == 1.0 ? DOUBLE_VALUE_1 :
+ new ParticularDoubleValue(value);
+ }
+
+
+ public ReferenceValue createArrayReferenceValue(String type,
+ Clazz referencedClass,
+ IntegerValue arrayLength)
+ {
+ return type == null ?
+ REFERENCE_VALUE_NULL :
+ new ArrayReferenceValue(ClassConstants.TYPE_ARRAY + type,
+ referencedClass,
+ arrayLength);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ReferenceValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ReferenceValue.java
new file mode 100644
index 0000000000..2f7c4f711a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ReferenceValue.java
@@ -0,0 +1,305 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.Clazz;
+
+/**
+ * This class represents a partially evaluated reference value.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class ReferenceValue extends Category1Value
+{
+ /**
+ * Returns the type.
+ */
+ public abstract String getType();
+;
+
+ /**
+ * Returns the class that is referenced by the type.
+ */
+ public abstract Clazz getReferencedClass();
+
+
+ // Basic unary methods.
+
+ /**
+ * Returns whether the type is <code>null</code>.
+ */
+ public abstract int isNull();
+
+
+ /**
+ * Returns whether the type is an instance of the given type.
+ */
+ public abstract int instanceOf(String otherType, Clazz otherReferencedClass);
+
+
+ /**
+ * Returns a generalization of this ReferenceValue that may be null,
+ * depending on the flag.
+ */
+ public abstract ReferenceValue generalizeMayBeNull(boolean mayBeNull);
+
+
+ /**
+ * Returns the length of the array, assuming this type is an array.
+ */
+ public IntegerValue arrayLength(ValueFactory valueFactory)
+ {
+ return valueFactory.createIntegerValue();
+ }
+
+
+ /**
+ * Returns the value of the array at the given index, assuming this type
+ * is an integer array.
+ */
+ public IntegerValue integerArrayLoad(IntegerValue indexValue, ValueFactory valueFactory)
+ {
+ return valueFactory.createIntegerValue();
+ }
+
+
+ /**
+ * Returns the value of the array at the given index, assuming this type
+ * is an long array.
+ */
+ public LongValue longArrayLoad(IntegerValue indexValue, ValueFactory valueFactory)
+ {
+ return valueFactory.createLongValue();
+ }
+
+
+ /**
+ * Returns the value of the array at the given index, assuming this type
+ * is an float array.
+ */
+ public FloatValue floatArrayLoad(IntegerValue indexValue, ValueFactory valueFactory)
+ {
+ return valueFactory.createFloatValue();
+ }
+
+
+ /**
+ * Returns the value of the array at the given index, assuming this type
+ * is an double array.
+ */
+ public DoubleValue doubleArrayLoad(IntegerValue indexValue, ValueFactory valueFactory)
+ {
+ return valueFactory.createDoubleValue();
+ }
+
+
+ /**
+ * Returns the value of the array at the given index, assuming this type
+ * is a reference array.
+ */
+ public abstract ReferenceValue referenceArrayLoad(IntegerValue indexValue, ValueFactory valueFactory);
+
+
+ /**
+ * Stores the given value at the given index in the given array, assuming
+ * this type is an array.
+ */
+ public void arrayStore(IntegerValue indexValue, Value value)
+ {
+ }
+
+
+ // Basic binary methods.
+
+ /**
+ * Returns the generalization of this ReferenceValue and the given other
+ * ReferenceValue.
+ */
+ public abstract ReferenceValue generalize(ReferenceValue other);
+
+
+ /**
+ * Returns whether this ReferenceValue is equal to the given other
+ * ReferenceValue.
+ * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public abstract int equal(ReferenceValue other);
+
+
+ // Derived unary methods.
+
+ /**
+ * Returns whether this ReferenceValue is not <code>null</code>.
+ * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public final int isNotNull()
+ {
+ return -isNull();
+ }
+
+
+ // Derived binary methods.
+
+ /**
+ * Returns whether this ReferenceValue and the given ReferenceValue are different.
+ * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public final int notEqual(ReferenceValue other)
+ {
+ return -equal(other);
+ }
+
+
+ // Similar binary methods, but this time with typed reference arguments.
+
+ /**
+ * Returns the generalization of this ReferenceValue and the given other
+ * TypedReferenceValue.
+ */
+ public ReferenceValue generalize(TypedReferenceValue other)
+ {
+ return generalize((ReferenceValue)other);
+ }
+
+
+ /**
+ * Returns whether this ReferenceValue is equal to the given other
+ * TypedReferenceValue.
+ * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public int equal(TypedReferenceValue other)
+ {
+ return equal((ReferenceValue)other);
+ }
+
+
+ // Similar binary methods, but this time with identified reference
+ // arguments.
+
+ /**
+ * Returns the generalization of this ReferenceValue and the given other
+ * IdentifiedReferenceValue.
+ */
+ public ReferenceValue generalize(IdentifiedReferenceValue other)
+ {
+ return generalize((TypedReferenceValue)other);
+ }
+
+
+ /**
+ * Returns whether this ReferenceValue is equal to the given other
+ * IdentifiedReferenceValue.
+ * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public int equal(IdentifiedReferenceValue other)
+ {
+ return equal((TypedReferenceValue)other);
+ }
+
+
+ // Similar binary methods, but this time with array reference arguments.
+
+ /**
+ * Returns the generalization of this ReferenceValue and the given other
+ * ArrayReferenceValue.
+ */
+ public ReferenceValue generalize(ArrayReferenceValue other)
+ {
+ return generalize((TypedReferenceValue)other);
+ }
+
+
+ /**
+ * Returns whether this ReferenceValue is equal to the given other
+ * ArrayReferenceValue.
+ * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public int equal(ArrayReferenceValue other)
+ {
+ return equal((TypedReferenceValue)other);
+ }
+
+
+ // Similar binary methods, but this time with identified array reference
+ // arguments.
+
+ /**
+ * Returns the generalization of this ReferenceValue and the given other
+ * IdentifiedArrayReferenceValue.
+ */
+ public ReferenceValue generalize(IdentifiedArrayReferenceValue other)
+ {
+ return generalize((ArrayReferenceValue)other);
+ }
+
+
+ /**
+ * Returns whether this ReferenceValue is equal to the given other
+ * IdentifiedArrayReferenceValue.
+ * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public int equal(IdentifiedArrayReferenceValue other)
+ {
+ return equal((ArrayReferenceValue)other);
+ }
+
+
+ // Similar binary methods, but this time with detailed array reference
+ // arguments.
+
+ /**
+ * Returns the generalization of this ReferenceValue and the given other
+ * DetailedArrayReferenceValue.
+ */
+ public ReferenceValue generalize(DetailedArrayReferenceValue other)
+ {
+ return generalize((IdentifiedArrayReferenceValue)other);
+ }
+
+
+ /**
+ * Returns whether this ReferenceValue is equal to the given other
+ * DetailedArrayReferenceValue.
+ * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+ */
+ public int equal(DetailedArrayReferenceValue other)
+ {
+ return equal((IdentifiedArrayReferenceValue)other);
+ }
+
+
+ // Implementations for Value.
+
+ public final ReferenceValue referenceValue()
+ {
+ return this;
+ }
+
+ public final Value generalize(Value other)
+ {
+ return this.generalize(other.referenceValue());
+ }
+
+ public final int computationalType()
+ {
+ return TYPE_REFERENCE;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificDoubleValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificDoubleValue.java
new file mode 100644
index 0000000000..746cd43a0c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificDoubleValue.java
@@ -0,0 +1,186 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This DoubleValue represents a specific double value.
+ *
+ * @author Eric Lafortune
+ */
+abstract class SpecificDoubleValue extends DoubleValue
+{
+ // Implementations of unary methods of DoubleValue.
+
+ public DoubleValue negate()
+ {
+ return new NegatedDoubleValue(this);
+ }
+
+ public IntegerValue convertToInteger()
+ {
+ return new ConvertedIntegerValue(this);
+ }
+
+ public LongValue convertToLong()
+ {
+ return new ConvertedLongValue(this);
+ }
+
+ public FloatValue convertToFloat()
+ {
+ return new ConvertedFloatValue(this);
+ }
+
+
+ // Implementations of binary methods of DoubleValue.
+
+ public DoubleValue generalize(DoubleValue other)
+ {
+ return other.generalize(this);
+ }
+
+ public DoubleValue add(DoubleValue other)
+ {
+ return other.add(this);
+ }
+
+ public DoubleValue subtract(DoubleValue other)
+ {
+ return other.subtractFrom(this);
+ }
+
+ public DoubleValue subtractFrom(DoubleValue other)
+ {
+ return other.subtract(this);
+ }
+
+ public DoubleValue multiply(DoubleValue other)
+ {
+ return other.multiply(this);
+ }
+
+ public DoubleValue divide(DoubleValue other)
+ {
+ return other.divideOf(this);
+ }
+
+ public DoubleValue divideOf(DoubleValue other)
+ {
+ return other.divide(this);
+ }
+
+ public DoubleValue remainder(DoubleValue other)
+ {
+ return other.remainderOf(this);
+ }
+
+ public DoubleValue remainderOf(DoubleValue other)
+ {
+ return other.remainder(this);
+ }
+
+ public IntegerValue compare(DoubleValue other)
+ {
+ return other.compareReverse(this);
+ }
+
+
+ // Implementations of binary DoubleValue methods with SpecificDoubleValue
+ // arguments.
+
+ public DoubleValue generalize(SpecificDoubleValue other)
+ {
+ return this.equals(other) ? this : ValueFactory.DOUBLE_VALUE;
+ }
+
+ public DoubleValue add(SpecificDoubleValue other)
+ {
+ return new CompositeDoubleValue(this, CompositeDoubleValue.ADD, other);
+ }
+
+ public DoubleValue subtract(SpecificDoubleValue other)
+ {
+ return new CompositeDoubleValue(this, CompositeDoubleValue.SUBTRACT, other);
+ }
+
+ public DoubleValue subtractFrom(SpecificDoubleValue other)
+ {
+ return new CompositeDoubleValue(other, CompositeDoubleValue.SUBTRACT, this);
+ }
+
+ public DoubleValue multiply(SpecificDoubleValue other)
+ {
+ return new CompositeDoubleValue(this, CompositeDoubleValue.MULTIPLY, other);
+ }
+
+ public DoubleValue divide(SpecificDoubleValue other)
+ {
+ return new CompositeDoubleValue(this, CompositeDoubleValue.DIVIDE, other);
+ }
+
+ public DoubleValue divideOf(SpecificDoubleValue other)
+ {
+ return new CompositeDoubleValue(other, CompositeDoubleValue.DIVIDE, this);
+ }
+
+ public DoubleValue remainder(SpecificDoubleValue other)
+ {
+ return new CompositeDoubleValue(this, CompositeDoubleValue.REMAINDER, other);
+ }
+
+ public DoubleValue remainderOf(SpecificDoubleValue other)
+ {
+ return new CompositeDoubleValue(other, CompositeDoubleValue.REMAINDER, this);
+ }
+
+ public IntegerValue compare(SpecificDoubleValue other)
+ {
+ return ValueFactory.INTEGER_VALUE;
+
+ // Not handling NaN properly.
+ //return this.equals(other) ?
+ // ParticularValueFactory.INTEGER_VALUE_0 :
+ // new ComparisonValue(this, other);
+ }
+
+
+ // Implementations for Value.
+
+ public boolean isSpecific()
+ {
+ return true;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return object != null &&
+ this.getClass() == object.getClass();
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificFloatValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificFloatValue.java
new file mode 100644
index 0000000000..6c6dd9c7eb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificFloatValue.java
@@ -0,0 +1,186 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This FloatValue represents a specific float value.
+ *
+ * @author Eric Lafortune
+ */
+abstract class SpecificFloatValue extends FloatValue
+{
+ // Implementations of unary methods of FloatValue.
+
+ public FloatValue negate()
+ {
+ return new NegatedFloatValue(this);
+ }
+
+ public IntegerValue convertToInteger()
+ {
+ return new ConvertedIntegerValue(this);
+ }
+
+ public LongValue convertToLong()
+ {
+ return new ConvertedLongValue(this);
+ }
+
+ public DoubleValue convertToDouble()
+ {
+ return new ConvertedDoubleValue(this);
+ }
+
+
+ // Implementations of binary methods of FloatValue.
+
+ public FloatValue generalize(FloatValue other)
+ {
+ return other.generalize(this);
+ }
+
+ public FloatValue add(FloatValue other)
+ {
+ return other.add(this);
+ }
+
+ public FloatValue subtract(FloatValue other)
+ {
+ return other.subtractFrom(this);
+ }
+
+ public FloatValue subtractFrom(FloatValue other)
+ {
+ return other.subtract(this);
+ }
+
+ public FloatValue multiply(FloatValue other)
+ {
+ return other.multiply(this);
+ }
+
+ public FloatValue divide(FloatValue other)
+ {
+ return other.divideOf(this);
+ }
+
+ public FloatValue divideOf(FloatValue other)
+ {
+ return other.divide(this);
+ }
+
+ public FloatValue remainder(FloatValue other)
+ {
+ return other.remainderOf(this);
+ }
+
+ public FloatValue remainderOf(FloatValue other)
+ {
+ return other.remainder(this);
+ }
+
+ public IntegerValue compare(FloatValue other)
+ {
+ return other.compareReverse(this);
+ }
+
+
+ // Implementations of binary FloatValue methods with SpecificFloatValue
+ // arguments.
+
+ public FloatValue generalize(SpecificFloatValue other)
+ {
+ return this.equals(other) ? this : ValueFactory.FLOAT_VALUE;
+ }
+
+ public FloatValue add(SpecificFloatValue other)
+ {
+ return new CompositeFloatValue(this, CompositeFloatValue.ADD, other);
+ }
+
+ public FloatValue subtract(SpecificFloatValue other)
+ {
+ return new CompositeFloatValue(this, CompositeFloatValue.SUBTRACT, other);
+ }
+
+ public FloatValue subtractFrom(SpecificFloatValue other)
+ {
+ return new CompositeFloatValue(other, CompositeFloatValue.SUBTRACT, this);
+ }
+
+ public FloatValue multiply(SpecificFloatValue other)
+ {
+ return new CompositeFloatValue(this, CompositeFloatValue.MULTIPLY, other);
+ }
+
+ public FloatValue divide(SpecificFloatValue other)
+ {
+ return new CompositeFloatValue(this, CompositeFloatValue.DIVIDE, other);
+ }
+
+ public FloatValue divideOf(SpecificFloatValue other)
+ {
+ return new CompositeFloatValue(other, CompositeFloatValue.DIVIDE, this);
+ }
+
+ public FloatValue remainder(SpecificFloatValue other)
+ {
+ return new CompositeFloatValue(this, CompositeFloatValue.REMAINDER, other);
+ }
+
+ public FloatValue remainderOf(SpecificFloatValue other)
+ {
+ return new CompositeFloatValue(other, CompositeFloatValue.REMAINDER, this);
+ }
+
+ public IntegerValue compare(SpecificFloatValue other)
+ {
+ return ValueFactory.INTEGER_VALUE;
+
+ // Not handling NaN properly.
+ //return this.equals(other) ?
+ // ParticularValueFactory.INTEGER_VALUE_0 :
+ // new ComparisonValue(this, other);
+ }
+
+
+ // Implementations for Value.
+
+ public boolean isSpecific()
+ {
+ return true;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return object != null &&
+ this.getClass() == object.getClass();
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificIntegerValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificIntegerValue.java
new file mode 100644
index 0000000000..b4befcfc25
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificIntegerValue.java
@@ -0,0 +1,354 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This IntegerValue represents a specific integer value.
+ *
+ * @author Eric Lafortune
+ */
+abstract class SpecificIntegerValue extends IntegerValue
+{
+ // Implementations of unary methods of IntegerValue.
+
+ public IntegerValue negate()
+ {
+ return new NegatedIntegerValue(this);
+ }
+
+ public IntegerValue convertToByte()
+ {
+ return new ConvertedByteValue(this);
+ }
+
+ public IntegerValue convertToCharacter()
+ {
+ return new ConvertedCharacterValue(this);
+ }
+
+ public IntegerValue convertToShort()
+ {
+ return new ConvertedShortValue(this);
+ }
+
+ public LongValue convertToLong()
+ {
+ return new ConvertedLongValue(this);
+ }
+
+ public FloatValue convertToFloat()
+ {
+ return new ConvertedFloatValue(this);
+ }
+
+ public DoubleValue convertToDouble()
+ {
+ return new ConvertedDoubleValue(this);
+ }
+
+
+ // Implementations of binary methods of IntegerValue.
+
+ public IntegerValue generalize(IntegerValue other)
+ {
+ return other.generalize(this);
+ }
+
+ public IntegerValue add(IntegerValue other)
+ {
+ return other.add(this);
+ }
+
+ public IntegerValue subtract(IntegerValue other)
+ {
+ return other.subtractFrom(this);
+ }
+
+ public IntegerValue subtractFrom(IntegerValue other)
+ {
+ return other.subtract(this);
+ }
+
+ public IntegerValue multiply(IntegerValue other)
+ {
+ return other.multiply(this);
+ }
+
+ public IntegerValue divide(IntegerValue other)
+ throws ArithmeticException
+ {
+ return other.divideOf(this);
+ }
+
+ public IntegerValue divideOf(IntegerValue other)
+ throws ArithmeticException
+ {
+ return other.divide(this);
+ }
+
+ public IntegerValue remainder(IntegerValue other)
+ throws ArithmeticException
+ {
+ return other.remainderOf(this);
+ }
+
+ public IntegerValue remainderOf(IntegerValue other)
+ throws ArithmeticException
+ {
+ return other.remainder(this);
+ }
+
+ public IntegerValue shiftLeft(IntegerValue other)
+ {
+ return other.shiftLeftOf(this);
+ }
+
+ public IntegerValue shiftLeftOf(IntegerValue other)
+ {
+ return other.shiftLeft(this);
+ }
+
+ public IntegerValue shiftRight(IntegerValue other)
+ {
+ return other.shiftRightOf(this);
+ }
+
+ public IntegerValue shiftRightOf(IntegerValue other)
+ {
+ return other.shiftRight(this);
+ }
+
+ public IntegerValue unsignedShiftRight(IntegerValue other)
+ {
+ return other.unsignedShiftRightOf(this);
+ }
+
+ public IntegerValue unsignedShiftRightOf(IntegerValue other)
+ {
+ return other.unsignedShiftRight(this);
+ }
+
+ public LongValue shiftLeftOf(LongValue other)
+ {
+ return other.shiftLeft(this);
+ }
+
+ public LongValue shiftRightOf(LongValue other)
+ {
+ return other.shiftRight(this);
+ }
+
+ public LongValue unsignedShiftRightOf(LongValue other)
+ {
+ return other.unsignedShiftRight(this);
+ }
+
+ public IntegerValue and(IntegerValue other)
+ {
+ return other.and(this);
+ }
+
+ public IntegerValue or(IntegerValue other)
+ {
+ return other.or(this);
+ }
+
+ public IntegerValue xor(IntegerValue other)
+ {
+ return other.xor(this);
+ }
+
+ public int equal(IntegerValue other)
+ {
+ return other.equal(this);
+ }
+
+ public int lessThan(IntegerValue other)
+ {
+ return other.greaterThan(this);
+ }
+
+ public int lessThanOrEqual(IntegerValue other)
+ {
+ return other.greaterThanOrEqual(this);
+ }
+
+
+ // Implementations of binary IntegerValue methods with SpecificIntegerValue
+ // arguments.
+
+ public IntegerValue generalize(SpecificIntegerValue other)
+ {
+ return this.equals(other) ? this : ValueFactory.INTEGER_VALUE;
+ }
+
+ public IntegerValue add(SpecificIntegerValue other)
+ {
+ return new CompositeIntegerValue(this, CompositeIntegerValue.ADD, other);
+ }
+
+ public IntegerValue subtract(SpecificIntegerValue other)
+ {
+ return this.equals(other) ?
+ ParticularValueFactory.INTEGER_VALUE_0 :
+ new CompositeIntegerValue(this, CompositeIntegerValue.SUBTRACT, other);
+ }
+
+ public IntegerValue subtractFrom(SpecificIntegerValue other)
+ {
+ return this.equals(other) ?
+ ParticularValueFactory.INTEGER_VALUE_0 :
+ new CompositeIntegerValue(other, CompositeIntegerValue.SUBTRACT, this);
+ }
+
+ public IntegerValue multiply(SpecificIntegerValue other)
+ {
+ return new CompositeIntegerValue(this, CompositeIntegerValue.MULTIPLY, other);
+ }
+
+ public IntegerValue divide(SpecificIntegerValue other)
+ throws ArithmeticException
+ {
+ return new CompositeIntegerValue(this, CompositeIntegerValue.DIVIDE, other);
+ }
+
+ public IntegerValue divideOf(SpecificIntegerValue other)
+ throws ArithmeticException
+ {
+ return new CompositeIntegerValue(other, CompositeIntegerValue.DIVIDE, this);
+ }
+
+ public IntegerValue remainder(SpecificIntegerValue other)
+ throws ArithmeticException
+ {
+ return new CompositeIntegerValue(this, CompositeIntegerValue.REMAINDER, other);
+ }
+
+ public IntegerValue remainderOf(SpecificIntegerValue other)
+ throws ArithmeticException
+ {
+ return new CompositeIntegerValue(other, CompositeIntegerValue.REMAINDER, this);
+ }
+
+ public IntegerValue shiftLeft(SpecificIntegerValue other)
+ {
+ return new CompositeIntegerValue(this, CompositeIntegerValue.SHIFT_LEFT, other);
+ }
+
+ public IntegerValue shiftRight(SpecificIntegerValue other)
+ {
+ return new CompositeIntegerValue(this, CompositeIntegerValue.SHIFT_RIGHT, other);
+ }
+
+ public IntegerValue unsignedShiftRight(SpecificIntegerValue other)
+ {
+ return new CompositeIntegerValue(this, CompositeIntegerValue.UNSIGNED_SHIFT_RIGHT, other);
+ }
+
+ public IntegerValue shiftLeftOf(SpecificIntegerValue other)
+ {
+ return new CompositeIntegerValue(other, CompositeIntegerValue.SHIFT_LEFT, this);
+ }
+
+ public IntegerValue shiftRightOf(SpecificIntegerValue other)
+ {
+ return new CompositeIntegerValue(other, CompositeIntegerValue.SHIFT_RIGHT, this);
+ }
+
+ public IntegerValue unsignedShiftRightOf(SpecificIntegerValue other)
+ {
+ return new CompositeIntegerValue(other, CompositeIntegerValue.UNSIGNED_SHIFT_RIGHT, this);
+ }
+
+ public LongValue shiftLeftOf(SpecificLongValue other)
+ {
+ return new CompositeLongValue(other, CompositeLongValue.SHIFT_LEFT, this);
+ }
+
+ public LongValue shiftRightOf(SpecificLongValue other)
+ {
+ return new CompositeLongValue(other, CompositeLongValue.SHIFT_RIGHT, this);
+ }
+
+ public LongValue unsignedShiftRightOf(SpecificLongValue other)
+ {
+ return new CompositeLongValue(other, CompositeLongValue.UNSIGNED_SHIFT_RIGHT, this);
+ }
+
+ public IntegerValue and(SpecificIntegerValue other)
+ {
+ return this.equals(other) ?
+ this :
+ new CompositeIntegerValue(other, CompositeIntegerValue.AND, this);
+ }
+
+ public IntegerValue or(SpecificIntegerValue other)
+ {
+ return this.equals(other) ?
+ this :
+ new CompositeIntegerValue(other, CompositeIntegerValue.OR, this);
+ }
+
+ public IntegerValue xor(SpecificIntegerValue other)
+ {
+ return this.equals(other) ?
+ ParticularValueFactory.INTEGER_VALUE_0 :
+ new CompositeIntegerValue(other, CompositeIntegerValue.XOR, this);
+ }
+
+ public int equal(SpecificIntegerValue other)
+ {
+ return this.equals(other) ? ALWAYS : MAYBE;
+ }
+
+ public int lessThan(SpecificIntegerValue other)
+ {
+ return this.equals(other) ? NEVER : MAYBE;
+ }
+
+ public int lessThanOrEqual(SpecificIntegerValue other)
+ {
+ return this.equals(other) ? ALWAYS : MAYBE;
+ }
+
+
+ // Implementations for Value.
+
+ public boolean isSpecific()
+ {
+ return true;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return object != null &&
+ this.getClass() == object.getClass();
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificLongValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificLongValue.java
new file mode 100644
index 0000000000..c63ce03246
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/SpecificLongValue.java
@@ -0,0 +1,259 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This LongValue represents a specific long value.
+ *
+ * @author Eric Lafortune
+ */
+abstract class SpecificLongValue extends LongValue
+{
+ // Implementations of unary methods of LongValue.
+
+ public LongValue negate()
+ {
+ return new NegatedLongValue(this);
+ }
+
+ public IntegerValue convertToInteger()
+ {
+ return new ConvertedIntegerValue(this);
+ }
+
+ public FloatValue convertToFloat()
+ {
+ return new ConvertedFloatValue(this);
+ }
+
+ public DoubleValue convertToDouble()
+ {
+ return new ConvertedDoubleValue(this);
+ }
+
+
+ // Implementations of binary methods of LongValue.
+
+ public LongValue generalize(LongValue other)
+ {
+ return other.generalize(this);
+ }
+
+ public LongValue add(LongValue other)
+ {
+ return other.add(this);
+ }
+
+ public LongValue subtract(LongValue other)
+ {
+ return other.subtractFrom(this);
+ }
+
+ public LongValue subtractFrom(LongValue other)
+ {
+ return other.subtract(this);
+ }
+
+ public LongValue multiply(LongValue other)
+ {
+ return other.multiply(this);
+ }
+
+ public LongValue divide(LongValue other)
+ throws ArithmeticException
+ {
+ return other.divideOf(this);
+ }
+
+ public LongValue divideOf(LongValue other)
+ throws ArithmeticException
+ {
+ return other.divide(this);
+ }
+
+ public LongValue remainder(LongValue other)
+ throws ArithmeticException
+ {
+ return other.remainderOf(this);
+ }
+
+ public LongValue remainderOf(LongValue other)
+ throws ArithmeticException
+ {
+ return other.remainder(this);
+ }
+
+ public LongValue shiftLeft(IntegerValue other)
+ {
+ return other.shiftLeftOf(this);
+ }
+
+ public LongValue shiftRight(IntegerValue other)
+ {
+ return other.shiftRightOf(this);
+ }
+
+ public LongValue unsignedShiftRight(IntegerValue other)
+ {
+ return other.unsignedShiftRightOf(this);
+ }
+
+ public LongValue and(LongValue other)
+ {
+ return other.and(this);
+ }
+
+ public LongValue or(LongValue other)
+ {
+ return other.or(this);
+ }
+
+ public LongValue xor(LongValue other)
+ {
+ return other.xor(this);
+ }
+
+ public IntegerValue compare(LongValue other)
+ {
+ return other.compareReverse(this);
+ }
+
+
+ // Implementations of binary LongValue methods with SpecificLongValue
+ // arguments.
+
+ public LongValue generalize(SpecificLongValue other)
+ {
+ return this.equals(other) ? this : ValueFactory.LONG_VALUE;
+ }
+
+ public LongValue add(SpecificLongValue other)
+ {
+ return new CompositeLongValue(this, CompositeLongValue.ADD, other);
+ }
+
+ public LongValue subtract(SpecificLongValue other)
+ {
+ return this.equals(other) ?
+ ParticularValueFactory.LONG_VALUE_0 :
+ new CompositeLongValue(this, CompositeLongValue.SUBTRACT, other);
+ }
+
+ public LongValue subtractFrom(SpecificLongValue other)
+ {
+ return this.equals(other) ?
+ ParticularValueFactory.LONG_VALUE_0 :
+ new CompositeLongValue(other, CompositeLongValue.SUBTRACT, this);
+ }
+
+ public LongValue multiply(SpecificLongValue other)
+ {
+ return new CompositeLongValue(this, CompositeLongValue.MULTIPLY, other);
+ }
+
+ public LongValue divide(SpecificLongValue other)
+ throws ArithmeticException
+ {
+ return new CompositeLongValue(this, CompositeLongValue.DIVIDE, other);
+ }
+
+ public LongValue divideOf(SpecificLongValue other)
+ throws ArithmeticException
+ {
+ return new CompositeLongValue(other, CompositeLongValue.DIVIDE, this);
+ }
+
+ public LongValue remainder(SpecificLongValue other)
+ throws ArithmeticException
+ {
+ return new CompositeLongValue(this, CompositeLongValue.REMAINDER, other);
+ }
+
+ public LongValue remainderOf(SpecificLongValue other)
+ throws ArithmeticException
+ {
+ return new CompositeLongValue(other, CompositeLongValue.REMAINDER, this);
+ }
+
+ public LongValue shiftLeft(SpecificLongValue other)
+ {
+ return new CompositeLongValue(this, CompositeLongValue.SHIFT_LEFT, other);
+ }
+
+ public LongValue shiftRight(SpecificLongValue other)
+ {
+ return new CompositeLongValue(this, CompositeLongValue.SHIFT_RIGHT, other);
+ }
+
+ public LongValue unsignedShiftRight(SpecificLongValue other)
+ {
+ return new CompositeLongValue(this, CompositeLongValue.UNSIGNED_SHIFT_RIGHT, other);
+ }
+
+ public LongValue and(SpecificLongValue other)
+ {
+ return this.equals(other) ?
+ this :
+ new CompositeLongValue(other, CompositeLongValue.AND, this);
+ }
+
+ public LongValue or(SpecificLongValue other)
+ {
+ return this.equals(other) ?
+ this :
+ new CompositeLongValue(other, CompositeLongValue.OR, this);
+ }
+
+ public LongValue xor(SpecificLongValue other)
+ {
+ return this.equals(other) ?
+ ParticularValueFactory.LONG_VALUE_0 :
+ new CompositeLongValue(other, CompositeLongValue.XOR, this);
+ }
+
+ public IntegerValue compare(SpecificLongValue other)
+ {
+ return new ComparisonValue(this, other);
+ }
+
+
+ // Implementations for Value.
+
+ public boolean isSpecific()
+ {
+ return true;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return object != null &&
+ this.getClass() == object.getClass();
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/TopValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/TopValue.java
new file mode 100644
index 0000000000..eb3a7ea795
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/TopValue.java
@@ -0,0 +1,79 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This class represents a partially evaluated top value. A top value is the
+ * dummy value that takes up the extra space when storing a long value or a
+ * double value.
+ *
+ * @author Eric Lafortune
+ */
+public class TopValue extends Category1Value
+{
+ // Implementations for Value.
+
+ public boolean isSpecific()
+ {
+ return true;
+ }
+
+ public boolean isParticular()
+ {
+ return true;
+ }
+
+ public final Value generalize(Value other)
+ {
+ return this.getClass() == other.getClass() ? this : null;
+ }
+
+ public final int computationalType()
+ {
+ return TYPE_TOP;
+ }
+
+ public final String internalType()
+ {
+ return null;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return object != null &&
+ this.getClass() == object.getClass();
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "T";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/TypedReferenceValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/TypedReferenceValue.java
new file mode 100644
index 0000000000..c4a7ec3fab
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/TypedReferenceValue.java
@@ -0,0 +1,620 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+import proguard.classfile.visitor.ClassCollector;
+
+import java.util.*;
+
+/**
+ * This ReferenceValue represents a partially evaluated reference value.
+ * It has a type and a flag that indicates whether the value could be
+ * <code>null</code>. If the type is <code>null</code>, the value is
+ * <code>null</code>.
+ *
+ * @author Eric Lafortune
+ */
+public class TypedReferenceValue extends ReferenceValue
+{
+ private static final boolean DEBUG = false;
+
+
+ protected final String type;
+ protected final Clazz referencedClass;
+ protected final boolean mayBeNull;
+
+
+ /**
+ * Creates a new TypedReferenceValue.
+ */
+ public TypedReferenceValue(String type,
+ Clazz referencedClass,
+ boolean mayBeNull)
+ {
+ this.type = type;
+ this.referencedClass = referencedClass;
+ this.mayBeNull = mayBeNull;
+ }
+
+
+ // Implementations for ReferenceValue.
+
+ public String getType()
+ {
+ return type;
+ }
+
+
+ public Clazz getReferencedClass()
+ {
+ return referencedClass;
+ }
+
+
+ // Implementations of unary methods of ReferenceValue.
+
+ public int isNull()
+ {
+ return type == null ? ALWAYS :
+ mayBeNull ? MAYBE :
+ NEVER;
+ }
+
+
+ public int instanceOf(String otherType, Clazz otherReferencedClass)
+ {
+ String thisType = this.type;
+
+ // If this type is null, it is never an instance of any class.
+ if (thisType == null)
+ {
+ return NEVER;
+ }
+
+ // Start taking into account the type dimensions.
+ int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType);
+ int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType);
+ int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount);
+
+ // Strip any common array prefixes.
+ thisType = thisType.substring(commonDimensionCount);
+ otherType = otherType.substring(commonDimensionCount);
+
+ // If either stripped type is a primitive type, we can tell right away.
+ if (commonDimensionCount > 0 &&
+ (ClassUtil.isInternalPrimitiveType(thisType.charAt(0)) ||
+ ClassUtil.isInternalPrimitiveType(otherType.charAt(0))))
+ {
+ return !thisType.equals(otherType) ? NEVER :
+ mayBeNull ? MAYBE :
+ ALWAYS;
+ }
+
+ // Strip the class type prefix and suffix of this type, if any.
+ if (thisDimensionCount == commonDimensionCount)
+ {
+ thisType = ClassUtil.internalClassNameFromClassType(thisType);
+ }
+
+ // Strip the class type prefix and suffix of the other type, if any.
+ if (otherDimensionCount == commonDimensionCount)
+ {
+ otherType = ClassUtil.internalClassNameFromClassType(otherType);
+ }
+
+ // If this type is an array type, and the other type is not
+ // java.lang.Object, java.lang.Cloneable, or java.io.Serializable,
+ // this type can never be an instance.
+ if (thisDimensionCount > otherDimensionCount &&
+ !ClassUtil.isInternalArrayInterfaceName(otherType))
+ {
+ return NEVER;
+ }
+
+ // If the other type is an array type, and this type is not
+ // java.lang.Object, java.lang.Cloneable, or java.io.Serializable,
+ // this type can never be an instance.
+ if (thisDimensionCount < otherDimensionCount &&
+ !ClassUtil.isInternalArrayInterfaceName(thisType))
+ {
+ return NEVER;
+ }
+
+ // If this type may be null, it might not be an instance of any class.
+ if (mayBeNull)
+ {
+ return MAYBE;
+ }
+
+ // If this type is equal to the other type, or if the other type is
+ // java.lang.Object, this type is always an instance.
+ if (thisType.equals(otherType) ||
+ ClassConstants.NAME_JAVA_LANG_OBJECT.equals(otherType))
+ {
+ return ALWAYS;
+ }
+
+ // If this type is an array type, it's ok.
+ if (thisDimensionCount > otherDimensionCount)
+ {
+ return ALWAYS;
+ }
+
+ // If the other type is an array type, it might be ok.
+ if (thisDimensionCount < otherDimensionCount)
+ {
+ return MAYBE;
+ }
+
+ // If the value extends the type, we're sure.
+ return referencedClass != null &&
+ otherReferencedClass != null &&
+ referencedClass.extendsOrImplements(otherReferencedClass) ?
+ ALWAYS :
+ MAYBE;
+ }
+
+
+ public ReferenceValue generalizeMayBeNull(boolean mayBeNull)
+ {
+ return this.mayBeNull == mayBeNull ?
+ this :
+ new TypedReferenceValue(type, referencedClass, true);
+ }
+
+
+ public ReferenceValue referenceArrayLoad(IntegerValue indexValue, ValueFactory valueFactory)
+ {
+ return
+ type == null ? ValueFactory.REFERENCE_VALUE_NULL :
+ !ClassUtil.isInternalArrayType(type) ? ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL :
+ valueFactory.createValue(type.substring(1),
+ referencedClass,
+ true).referenceValue();
+ }
+
+
+ // Implementations of binary methods of ReferenceValue.
+
+ public ReferenceValue generalize(ReferenceValue other)
+ {
+ return other.generalize(this);
+ }
+
+
+ public int equal(ReferenceValue other)
+ {
+ return other.equal(this);
+ }
+
+
+ // Implementations of binary ReferenceValue methods with TypedReferenceValue
+ // arguments.
+
+ public ReferenceValue generalize(TypedReferenceValue other)
+ {
+ // If both types are identical, the generalization is the same too.
+ if (this.equals(other))
+ {
+ return this;
+ }
+
+ String thisType = this.type;
+ String otherType = other.type;
+
+ // If both types are nul, the generalization is null too.
+ if (thisType == null && otherType == null)
+ {
+ return ValueFactory.REFERENCE_VALUE_NULL;
+ }
+
+ // If this type is null, the generalization is the other type, maybe null.
+ if (thisType == null)
+ {
+ return other.generalizeMayBeNull(true);
+ }
+
+ // If the other type is null, the generalization is this type, maybe null.
+ if (otherType == null)
+ {
+ return this.generalizeMayBeNull(true);
+ }
+
+ boolean mayBeNull = this.mayBeNull || other.mayBeNull;
+
+ // If the two types are equal, the generalization remains the same, maybe null.
+ if (thisType.equals(otherType))
+ {
+ return typedReferenceValue(this, mayBeNull);
+ }
+
+ // Start taking into account the type dimensions.
+ int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType);
+ int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType);
+ int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount);
+
+ if (thisDimensionCount == otherDimensionCount)
+ {
+ // See if we can take into account the referenced classes.
+ Clazz thisReferencedClass = this.referencedClass;
+ Clazz otherReferencedClass = other.referencedClass;
+
+ // Is one class simply an extension of the other one?
+ // We're checking the class name instead of the referenced class,
+ // in case the referenced class is not set, e.g. for a caught
+ // java.lang.Throwable.
+ if (thisReferencedClass != null &&
+ thisReferencedClass.extendsOrImplements(ClassUtil.internalClassNameFromClassType(otherType)))
+ {
+ return typedReferenceValue(other, mayBeNull);
+ }
+
+ if (otherReferencedClass != null &&
+ otherReferencedClass.extendsOrImplements(ClassUtil.internalClassNameFromClassType(thisType)))
+ {
+ return typedReferenceValue(this, mayBeNull);
+ }
+
+ // Otherwise, we really need both referenced classes,
+ // so we can investigate their hierarchies.
+ if (thisReferencedClass != null &&
+ otherReferencedClass != null)
+ {
+ // Do the classes have a non-trivial common superclass?
+ Clazz commonClass = findCommonClass(thisReferencedClass,
+ otherReferencedClass,
+ false);
+
+ if (commonClass.getName().equals(ClassConstants.NAME_JAVA_LANG_OBJECT))
+ {
+ // Otherwise, do the classes have a common interface?
+ Clazz commonInterface = findCommonClass(thisReferencedClass,
+ otherReferencedClass,
+ true);
+ if (commonInterface != null)
+ {
+ commonClass = commonInterface;
+ }
+ }
+
+ return new TypedReferenceValue(commonDimensionCount == 0 ?
+ commonClass.getName() :
+ ClassUtil.internalArrayTypeFromClassName(commonClass.getName(),
+ commonDimensionCount),
+ commonClass,
+ mayBeNull);
+ }
+ }
+ else if (thisDimensionCount > otherDimensionCount)
+ {
+ // See if the other type is an interface type of arrays.
+ if (ClassUtil.isInternalArrayInterfaceName(ClassUtil.internalClassNameFromClassType(otherType)))
+ {
+ return typedReferenceValue(other, mayBeNull);
+ }
+ }
+ else if (thisDimensionCount < otherDimensionCount)
+ {
+ // See if this type is an interface type of arrays.
+ if (ClassUtil.isInternalArrayInterfaceName(ClassUtil.internalClassNameFromClassType(thisType)))
+ {
+ return typedReferenceValue(this, mayBeNull);
+ }
+ }
+
+ // Reduce the common dimension count if either type is an array of
+ // primitives type of this dimension.
+ if (commonDimensionCount > 0 &&
+ (ClassUtil.isInternalPrimitiveType(otherType.charAt(commonDimensionCount)) ||
+ ClassUtil.isInternalPrimitiveType(thisType.charAt(commonDimensionCount))))
+ {
+ commonDimensionCount--;
+ }
+
+ // Fall back on a basic Object or array of Objects type.
+ return
+ commonDimensionCount != 0 ?
+ new TypedReferenceValue(ClassUtil.internalArrayTypeFromClassName(ClassConstants.NAME_JAVA_LANG_OBJECT, commonDimensionCount),
+ null,
+ mayBeNull) :
+ mayBeNull ?
+ ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL :
+ ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL;
+ }
+
+
+ /**
+ * Returns the most specific common superclass or interface of the given
+ * classes.
+ * @param class1 the first class.
+ * @param class2 the second class.
+ * @param interfaces specifies whether to look for a superclass or for an
+ * interface.
+ * @return the common class.
+ */
+ private Clazz findCommonClass(Clazz class1,
+ Clazz class2,
+ boolean interfaces)
+ {
+ // Collect the superclasses or the interfaces of this class.
+ Set superClasses1 = new HashSet();
+ class1.hierarchyAccept(!interfaces,
+ !interfaces,
+ interfaces,
+ false,
+ new ClassCollector(superClasses1));
+
+ int superClasses1Count = superClasses1.size();
+ if (superClasses1Count == 0)
+ {
+ if (interfaces)
+ {
+ return null;
+ }
+ else if (class1.getSuperName() != null)
+ {
+ throw new IllegalArgumentException("Can't find any super classes of ["+class1.getName()+"] (not even immediate super class ["+class1.getSuperName()+"])");
+ }
+ }
+
+ // Collect the superclasses or the interfaces of the other class.
+ Set superClasses2 = new HashSet();
+ class2.hierarchyAccept(!interfaces,
+ !interfaces,
+ interfaces,
+ false,
+ new ClassCollector(superClasses2));
+
+ int superClasses2Count = superClasses2.size();
+ if (superClasses2Count == 0)
+ {
+ if (interfaces)
+ {
+ return null;
+ }
+ else if (class2.getSuperName() != null)
+ {
+ throw new IllegalArgumentException("Can't find any super classes of ["+class2.getName()+"] (not even immediate super class ["+class2.getSuperName()+"])");
+ }
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("ReferenceValue.generalize this ["+class1.getName()+"] with other ["+class2.getName()+"] (interfaces = "+interfaces+")");
+ System.out.println(" This super classes: "+superClasses1);
+ System.out.println(" Other super classes: "+superClasses2);
+ }
+
+ // Find the common superclasses.
+ superClasses1.retainAll(superClasses2);
+
+ if (DEBUG)
+ {
+ System.out.println(" Common super classes: "+superClasses1);
+ }
+
+ if (interfaces && superClasses1.isEmpty())
+ {
+ return null;
+ }
+
+ // Find a class that is a subclass of all common superclasses,
+ // or that at least has the maximum number of common superclasses.
+ Clazz commonClass = null;
+
+ int maximumSuperClassCount = -1;
+
+ // Go over all common superclasses to find it. In case of
+ // multiple subclasses, keep the lowest one alphabetically,
+ // in order to ensure that the choice is deterministic.
+ Iterator commonSuperClasses = superClasses1.iterator();
+ while (commonSuperClasses.hasNext())
+ {
+ Clazz commonSuperClass = (Clazz)commonSuperClasses.next();
+
+ int superClassCount = superClassCount(commonSuperClass, superClasses1);
+ if (maximumSuperClassCount < superClassCount ||
+ (maximumSuperClassCount == superClassCount &&
+ commonClass != null &&
+ commonClass.getName().compareTo(commonSuperClass.getName()) > 0))
+ {
+ commonClass = commonSuperClass;
+ maximumSuperClassCount = superClassCount;
+ }
+ }
+
+ if (commonClass == null)
+ {
+ throw new IllegalArgumentException("Can't find common super class of ["+
+ class1.getName() +"] (with "+superClasses1Count +" known super classes) and ["+
+ class2.getName()+"] (with "+superClasses2Count+" known super classes)");
+ }
+
+ if (DEBUG)
+ {
+ System.out.println(" Best common class: ["+commonClass.getName()+"]");
+ }
+
+ return commonClass;
+ }
+
+
+ /**
+ * Returns the given reference value that may or may not be null, ensuring
+ * that it is a TypedReferenceValue, not a subclass.
+ */
+ private static ReferenceValue typedReferenceValue(TypedReferenceValue referenceValue,
+ boolean mayBeNull)
+ {
+ return referenceValue.getClass() == TypedReferenceValue.class ?
+ referenceValue.generalizeMayBeNull(mayBeNull) :
+ new TypedReferenceValue(referenceValue.type,
+ referenceValue.referencedClass,
+ mayBeNull);
+ }
+
+
+ /**
+ * Returns if the number of superclasses of the given class in the given
+ * set of classes.
+ */
+ private int superClassCount(Clazz subClass, Set classes)
+ {
+ int count = 0;
+
+ Iterator iterator = classes.iterator();
+
+ while (iterator.hasNext())
+ {
+ Clazz clazz = (Clazz)iterator.next();
+ if (subClass.extendsOrImplements(clazz))
+ {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+
+ public int equal(TypedReferenceValue other)
+ {
+ return this.type == null && other.type == null ? ALWAYS : MAYBE;
+ }
+
+
+ // Implementations of binary ReferenceValue methods with
+ // IdentifiedReferenceValue arguments.
+
+ public ReferenceValue generalize(IdentifiedReferenceValue other)
+ {
+ return generalize((TypedReferenceValue)other);
+ }
+
+
+ public int equal(IdentifiedReferenceValue other)
+ {
+ return equal((TypedReferenceValue)other);
+ }
+
+
+ // Implementations of binary ReferenceValue methods with
+ // ArrayReferenceValue arguments.
+
+ public ReferenceValue generalize(ArrayReferenceValue other)
+ {
+ return generalize((TypedReferenceValue)other);
+ }
+
+
+ public int equal(ArrayReferenceValue other)
+ {
+ return equal((TypedReferenceValue)other);
+ }
+
+
+ // Implementations of binary ReferenceValue methods with
+ // IdentifiedArrayReferenceValue arguments.
+
+ public ReferenceValue generalize(IdentifiedArrayReferenceValue other)
+ {
+ return generalize((ArrayReferenceValue)other);
+ }
+
+
+ public int equal(IdentifiedArrayReferenceValue other)
+ {
+ return equal((ArrayReferenceValue)other);
+ }
+
+
+ // Implementations of binary ReferenceValue methods with
+ // DetailedArrayReferenceValue arguments.
+
+ public ReferenceValue generalize(DetailedArrayReferenceValue other)
+ {
+ return generalize((IdentifiedArrayReferenceValue)other);
+ }
+
+
+ public int equal(DetailedArrayReferenceValue other)
+ {
+ return equal((IdentifiedArrayReferenceValue)other);
+ }
+
+
+ // Implementations for Value.
+
+ public boolean isParticular()
+ {
+ return type == null;
+ }
+
+
+ public final String internalType()
+ {
+ return
+ type == null ? ClassConstants.TYPE_JAVA_LANG_OBJECT :
+ ClassUtil.isInternalArrayType(type) ? type :
+ ClassConstants.TYPE_CLASS_START +
+ type +
+ ClassConstants.TYPE_CLASS_END;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ if (this == object)
+ {
+ return true;
+ }
+
+ if (object == null ||
+ this.getClass() != object.getClass())
+ {
+ return false;
+ }
+
+ TypedReferenceValue other = (TypedReferenceValue)object;
+ return this.type == null ? other.type == null :
+ (this.mayBeNull == other.mayBeNull &&
+ this.type.equals(other.type));
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode() ^
+ (type == null ? 0 : type.hashCode() ^ (mayBeNull ? 0 : 1));
+ }
+
+
+ public String toString()
+ {
+ return type == null ?
+ "null" :
+ type + (referencedClass == null ? "?" : "") + (mayBeNull ? "" : "!");
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownDoubleValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownDoubleValue.java
new file mode 100644
index 0000000000..7760baca74
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownDoubleValue.java
@@ -0,0 +1,125 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This class represents a partially evaluated double value.
+ *
+ * @author Eric Lafortune
+ */
+public class UnknownDoubleValue extends DoubleValue
+{
+ // Basic unary methods.
+
+ public DoubleValue negate()
+ {
+ return this;
+ }
+
+ public IntegerValue convertToInteger()
+ {
+ return ValueFactory.INTEGER_VALUE;
+ }
+
+ public LongValue convertToLong()
+ {
+ return ValueFactory.LONG_VALUE;
+ }
+
+ public FloatValue convertToFloat()
+ {
+ return ValueFactory.FLOAT_VALUE;
+ }
+
+
+ // Basic binary methods.
+
+ public DoubleValue generalize(DoubleValue other)
+ {
+ return this;
+ }
+
+ public DoubleValue add(DoubleValue other)
+ {
+ return this;
+ }
+
+ public DoubleValue subtract(DoubleValue other)
+ {
+ return this;
+ }
+
+ public DoubleValue subtractFrom(DoubleValue other)
+ {
+ return this;
+ }
+
+ public DoubleValue multiply(DoubleValue other)
+ {
+ return this;
+ }
+
+ public DoubleValue divide(DoubleValue other)
+ {
+ return this;
+ }
+
+ public DoubleValue divideOf(DoubleValue other)
+ {
+ return this;
+ }
+
+ public DoubleValue remainder(DoubleValue other)
+ {
+ return this;
+ }
+
+ public DoubleValue remainderOf(DoubleValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue compare(DoubleValue other)
+ {
+ return ValueFactory.INTEGER_VALUE;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return object != null &&
+ this.getClass() == object.getClass();
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "d";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownFloatValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownFloatValue.java
new file mode 100644
index 0000000000..b343f89f1a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownFloatValue.java
@@ -0,0 +1,125 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This class represents a partially evaluated float value.
+ *
+ * @author Eric Lafortune
+ */
+public class UnknownFloatValue extends FloatValue
+{
+ // Basic unary methods.
+
+ public FloatValue negate()
+ {
+ return this;
+ }
+
+ public IntegerValue convertToInteger()
+ {
+ return ValueFactory.INTEGER_VALUE;
+ }
+
+ public LongValue convertToLong()
+ {
+ return ValueFactory.LONG_VALUE;
+ }
+
+ public DoubleValue convertToDouble()
+ {
+ return ValueFactory.DOUBLE_VALUE;
+ }
+
+
+ // Basic binary methods.
+
+ public FloatValue generalize(FloatValue other)
+ {
+ return this;
+ }
+
+ public FloatValue add(FloatValue other)
+ {
+ return this;
+ }
+
+ public FloatValue subtract(FloatValue other)
+ {
+ return this;
+ }
+
+ public FloatValue subtractFrom(FloatValue other)
+ {
+ return this;
+ }
+
+ public FloatValue multiply(FloatValue other)
+ {
+ return this;
+ }
+
+ public FloatValue divide(FloatValue other)
+ {
+ return this;
+ }
+
+ public FloatValue divideOf(FloatValue other)
+ {
+ return this;
+ }
+
+ public FloatValue remainder(FloatValue other)
+ {
+ return this;
+ }
+
+ public FloatValue remainderOf(FloatValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue compare(FloatValue other)
+ {
+ return ValueFactory.INTEGER_VALUE;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return object != null &&
+ this.getClass() == object.getClass();
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "f";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownIntegerValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownIntegerValue.java
new file mode 100644
index 0000000000..51a55a007c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownIntegerValue.java
@@ -0,0 +1,216 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This class represents a partially evaluated integer value.
+ *
+ * @author Eric Lafortune
+ */
+public class UnknownIntegerValue extends IntegerValue
+{
+ // Basic unary methods.
+
+ public IntegerValue negate()
+ {
+ return this;
+ }
+
+ public IntegerValue convertToByte()
+ {
+ return this;
+ }
+
+ public IntegerValue convertToCharacter()
+ {
+ return this;
+ }
+
+ public IntegerValue convertToShort()
+ {
+ return this;
+ }
+
+ public LongValue convertToLong()
+ {
+ return ValueFactory.LONG_VALUE;
+ }
+
+ public FloatValue convertToFloat()
+ {
+ return ValueFactory.FLOAT_VALUE;
+ }
+
+ public DoubleValue convertToDouble()
+ {
+ return ValueFactory.DOUBLE_VALUE;
+ }
+
+
+ // Basic binary methods.
+
+ public IntegerValue generalize(IntegerValue other)
+ {
+ return this;
+ }
+
+
+ public IntegerValue add(IntegerValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue subtract(IntegerValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue subtractFrom(IntegerValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue multiply(IntegerValue other)
+ throws ArithmeticException
+ {
+ return this;
+ }
+
+ public IntegerValue divide(IntegerValue other)
+ throws ArithmeticException
+ {
+ return this;
+ }
+
+ public IntegerValue divideOf(IntegerValue other)
+ throws ArithmeticException
+ {
+ return this;
+ }
+
+ public IntegerValue remainder(IntegerValue other)
+ throws ArithmeticException
+ {
+ return this;
+ }
+
+ public IntegerValue remainderOf(IntegerValue other)
+ throws ArithmeticException
+ {
+ return this;
+ }
+
+ public IntegerValue shiftLeft(IntegerValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue shiftLeftOf(IntegerValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue shiftRight(IntegerValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue shiftRightOf(IntegerValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue unsignedShiftRight(IntegerValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue unsignedShiftRightOf(IntegerValue other)
+ {
+ return this;
+ }
+
+ public LongValue shiftLeftOf(LongValue other)
+ {
+ return ValueFactory.LONG_VALUE;
+ }
+
+ public LongValue shiftRightOf(LongValue other)
+ {
+ return ValueFactory.LONG_VALUE;
+ }
+
+ public LongValue unsignedShiftRightOf(LongValue other)
+ {
+ return ValueFactory.LONG_VALUE;
+ }
+
+ public IntegerValue and(IntegerValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue or(IntegerValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue xor(IntegerValue other)
+ {
+ return this;
+ }
+
+ public int equal(IntegerValue other)
+ {
+ return MAYBE;
+ }
+
+ public int lessThan(IntegerValue other)
+ {
+ return MAYBE;
+ }
+
+ public int lessThanOrEqual(IntegerValue other)
+ {
+ return MAYBE;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return object != null &&
+ this.getClass() == object.getClass();
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "i";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownLongValue.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownLongValue.java
new file mode 100644
index 0000000000..f431eb688f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/UnknownLongValue.java
@@ -0,0 +1,160 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This class represents a partially evaluated long value.
+ *
+ * @author Eric Lafortune
+ */
+public class UnknownLongValue extends LongValue
+{
+ // Basic unary methods.
+
+ public LongValue negate()
+ {
+ return this;
+ }
+
+ public IntegerValue convertToInteger()
+ {
+ return ValueFactory.INTEGER_VALUE;
+ }
+
+ public FloatValue convertToFloat()
+ {
+ return ValueFactory.FLOAT_VALUE;
+ }
+
+ public DoubleValue convertToDouble()
+ {
+ return ValueFactory.DOUBLE_VALUE;
+ }
+
+
+ // Basic binary methods.
+
+ public LongValue generalize(LongValue other)
+ {
+ return this;
+ }
+
+ public LongValue add(LongValue other)
+ {
+ return this;
+ }
+
+ public LongValue subtract(LongValue other)
+ {
+ return this;
+ }
+
+ public LongValue subtractFrom(LongValue other)
+ {
+ return this;
+ }
+
+ public LongValue multiply(LongValue other)
+ throws ArithmeticException
+ {
+ return this;
+ }
+
+ public LongValue divide(LongValue other)
+ throws ArithmeticException
+ {
+ return this;
+ }
+
+ public LongValue divideOf(LongValue other)
+ throws ArithmeticException
+ {
+ return this;
+ }
+
+ public LongValue remainder(LongValue other)
+ throws ArithmeticException
+ {
+ return this;
+ }
+
+ public LongValue remainderOf(LongValue other)
+ throws ArithmeticException
+ {
+ return this;
+ }
+
+ public LongValue shiftLeft(IntegerValue other)
+ {
+ return this;
+ }
+
+ public LongValue shiftRight(IntegerValue other)
+ {
+ return this;
+ }
+
+ public LongValue unsignedShiftRight(IntegerValue other)
+ {
+ return this;
+ }
+
+ public LongValue and(LongValue other)
+ {
+ return this;
+ }
+
+ public LongValue or(LongValue other)
+ {
+ return this;
+ }
+
+ public LongValue xor(LongValue other)
+ {
+ return this;
+ }
+
+ public IntegerValue compare(LongValue other)
+ {
+ return ValueFactory.INTEGER_VALUE;
+ }
+
+
+ // Implementations for Object.
+
+ public boolean equals(Object object)
+ {
+ return object != null &&
+ this.getClass() == object.getClass();
+ }
+
+
+ public int hashCode()
+ {
+ return this.getClass().hashCode();
+ }
+
+
+ public String toString()
+ {
+ return "l";
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Value.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Value.java
new file mode 100644
index 0000000000..58f09a8723
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/Value.java
@@ -0,0 +1,169 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+/**
+ * This abstract class represents a partially evaluated value.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class Value
+{
+ public static final int NEVER = -1;
+ public static final int MAYBE = 0;
+ public static final int ALWAYS = 1;
+
+ public static final int TYPE_INTEGER = 1;
+ public static final int TYPE_LONG = 2;
+ public static final int TYPE_FLOAT = 3;
+ public static final int TYPE_DOUBLE = 4;
+ public static final int TYPE_REFERENCE = 5;
+ public static final int TYPE_INSTRUCTION_OFFSET = 6;
+ public static final int TYPE_TOP = 7;
+
+
+ /**
+ * Returns this Value as a Category1Value.
+ */
+ public Category1Value category1Value()
+ {
+ throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a Category 1 value [" + this.getClass().getName() + "]");
+ }
+
+ /**
+ * Returns this Value as a Category2Value.
+ */
+ public Category2Value category2Value()
+ {
+ throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a Category 2 value [" + this.getClass().getName() + "]");
+ }
+
+
+ /**
+ * Returns this Value as an IntegerValue.
+ */
+ public IntegerValue integerValue()
+ {
+ throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not an integer value [" + this.getClass().getName() + "]");
+ }
+
+ /**
+ * Returns this Value as a LongValue.
+ */
+ public LongValue longValue()
+ {
+ throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a long value [" + this.getClass().getName() + "]");
+ }
+
+ /**
+ * Returns this Value as a FloatValue.
+ */
+ public FloatValue floatValue()
+ {
+ throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a float value [" + this.getClass().getName() + "]");
+ }
+
+ /**
+ * Returns this Value as a DoubleValue.
+ */
+ public DoubleValue doubleValue()
+ {
+ throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a double value [" + this.getClass().getName() + "]");
+ }
+
+ /**
+ * Returns this Value as a ReferenceValue.
+ */
+ public ReferenceValue referenceValue()
+ {
+ throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a reference value [" + this.getClass().getName() + "]");
+ }
+
+ /**
+ * Returns this Value as an InstructionOffsetValue.
+ */
+ public InstructionOffsetValue instructionOffsetValue()
+ {
+ throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not an instruction offset value [" + this.getClass().getName() + "]");
+ }
+
+
+ /**
+ * Returns whether this Value represents a single specific (but possibly
+ * unknown) value.
+ */
+ public boolean isSpecific()
+ {
+ return false;
+ }
+
+
+ /**
+ * Returns whether this Value represents a single particular (known)
+ * value.
+ */
+ public boolean isParticular()
+ {
+ return false;
+ }
+
+
+ /**
+ * Returns the generalization of this Value and the given other Value.
+ */
+ public abstract Value generalize(Value other);
+
+
+ /**
+ * Returns whether the computational type of this Value is a category 2 type.
+ * This means that it takes up the space of two category 1 types on the
+ * stack, for instance.
+ */
+ public abstract boolean isCategory2();
+
+
+ /**
+ * Returns the computational type of this Value.
+ * @return <code>TYPE_INTEGER</code>,
+ * <code>TYPE_LONG</code>,
+ * <code>TYPE_FLOAT</code>,
+ * <code>TYPE_DOUBLE</code>,
+ * <code>TYPE_REFERENCE</code>, or
+ * <code>TYPE_INSTRUCTION_OFFSET</code>.
+ */
+ public abstract int computationalType();
+
+
+ /**
+ * Returns the internal type of this Value.
+ * @return <code>ClassConstants.TYPE_BOOLEAN</code>,
+ * <code>ClassConstants.TYPE_BYTE</code>,
+ * <code>ClassConstants.TYPE_CHAR</code>,
+ * <code>ClassConstants.TYPE_SHORT</code>,
+ * <code>ClassConstants.TYPE_INT</code>,
+ * <code>ClassConstants.TYPE_LONG</code>,
+ * <code>ClassConstants.TYPE_FLOAT</code>,
+ * <code>ClassConstants.TYPE_DOUBLE</code>,
+ * <code>ClassConstants.TYPE_CLASS_START ... ClassConstants.TYPE_CLASS_END</code>, or
+ * an array type containing any of these types (always as String).
+ */
+ public abstract String internalType();
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ValueFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ValueFactory.java
new file mode 100644
index 0000000000..888f7326e1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/ValueFactory.java
@@ -0,0 +1,176 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.evaluation.value;
+
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+
+/**
+ * This class provides methods to create and reuse Value objects.
+ *
+ * @author Eric Lafortune
+ */
+public class ValueFactory
+{
+ // Shared copies of Value objects, to avoid creating a lot of objects.
+ static final IntegerValue INTEGER_VALUE = new UnknownIntegerValue();
+ static final LongValue LONG_VALUE = new UnknownLongValue();
+ static final FloatValue FLOAT_VALUE = new UnknownFloatValue();
+ static final DoubleValue DOUBLE_VALUE = new UnknownDoubleValue();
+
+ static final ReferenceValue REFERENCE_VALUE_NULL = new TypedReferenceValue(null, null, true);
+ static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL = new TypedReferenceValue(ClassConstants.NAME_JAVA_LANG_OBJECT, null, true);
+ static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL = new TypedReferenceValue(ClassConstants.NAME_JAVA_LANG_OBJECT, null, false);
+
+
+ /**
+ * Creates a new Value of the given type.
+ * The type must be a fully specified internal type for primitives, classes,
+ * or arrays.
+ */
+ public Value createValue(String type, Clazz referencedClass, boolean mayBeNull)
+ {
+ switch (type.charAt(0))
+ {
+ case ClassConstants.TYPE_VOID: return null;
+ case ClassConstants.TYPE_BOOLEAN:
+ case ClassConstants.TYPE_BYTE:
+ case ClassConstants.TYPE_CHAR:
+ case ClassConstants.TYPE_SHORT:
+ case ClassConstants.TYPE_INT: return createIntegerValue();
+ case ClassConstants.TYPE_LONG: return createLongValue();
+ case ClassConstants.TYPE_FLOAT: return createFloatValue();
+ case ClassConstants.TYPE_DOUBLE: return createDoubleValue();
+ default: return createReferenceValue(ClassUtil.isInternalArrayType(type) ?
+ type :
+ ClassUtil.internalClassNameFromClassType(type),
+ referencedClass,
+ mayBeNull);
+ }
+ }
+
+ /**
+ * Creates a new IntegerValue with an undefined value.
+ */
+ public IntegerValue createIntegerValue()
+ {
+ return INTEGER_VALUE;
+ }
+
+ /**
+ * Creates a new IntegerValue with a given particular value.
+ */
+ public IntegerValue createIntegerValue(int value)
+ {
+ return createIntegerValue();
+ }
+
+
+ /**
+ * Creates a new LongValue with an undefined value.
+ */
+ public LongValue createLongValue()
+ {
+ return LONG_VALUE;
+ }
+
+ /**
+ * Creates a new LongValue with a given particular value.
+ */
+ public LongValue createLongValue(long value)
+ {
+ return createLongValue();
+ }
+
+
+ /**
+ * Creates a new FloatValue with an undefined value.
+ */
+ public FloatValue createFloatValue()
+ {
+ return FLOAT_VALUE;
+ }
+
+ /**
+ * Creates a new FloatValue with a given particular value.
+ */
+ public FloatValue createFloatValue(float value)
+ {
+ return createFloatValue();
+ }
+
+
+ /**
+ * Creates a new DoubleValue with an undefined value.
+ */
+ public DoubleValue createDoubleValue()
+ {
+ return DOUBLE_VALUE;
+ }
+
+ /**
+ * Creates a new DoubleValue with a given particular value.
+ */
+ public DoubleValue createDoubleValue(double value)
+ {
+ return createDoubleValue();
+ }
+
+
+ /**
+ * Creates a new ReferenceValue that represents <code>null</code>.
+ */
+ public ReferenceValue createReferenceValueNull()
+ {
+ return REFERENCE_VALUE_NULL;
+ }
+
+
+ /**
+ * Creates a new ReferenceValue of the given type. The type must be an
+ * internal class name or an array type. If the type is <code>null</code>,
+ * the ReferenceValue represents <code>null</code>.
+ */
+ public ReferenceValue createReferenceValue(String type,
+ Clazz referencedClass,
+ boolean mayBeNull)
+ {
+ return type == null ? REFERENCE_VALUE_NULL :
+ !type.equals(ClassConstants.NAME_JAVA_LANG_OBJECT) ? new TypedReferenceValue(type, referencedClass, mayBeNull) :
+ mayBeNull ? REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL :
+ REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL;
+ }
+
+
+ /**
+ * Creates a new ReferenceValue for arrays of the given type and length.
+ * The type must be a fully specified internal type for primitives, classes,
+ * or arrays.
+ */
+ public ReferenceValue createArrayReferenceValue(String type,
+ Clazz referencedClass,
+ IntegerValue arrayLength)
+ {
+ return createReferenceValue(ClassConstants.TYPE_ARRAY + type,
+ referencedClass,
+ false);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/package.html
new file mode 100644
index 0000000000..71e1b13654
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/evaluation/value/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains classes that represent partial evaluation values.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gradle/ProGuardTask.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gradle/ProGuardTask.java
new file mode 100644
index 0000000000..3cd99afc3b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gradle/ProGuardTask.java
@@ -0,0 +1,1625 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gradle;
+
+import groovy.lang.Closure;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.file.*;
+import org.gradle.api.logging.*;
+import org.gradle.api.tasks.*;
+import org.gradle.api.tasks.Optional;
+import proguard.*;
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+import proguard.util.ListUtil;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This Task allows to configure and run ProGuard from Gradle.
+ *
+ * @author Eric Lafortune
+ */
+public class ProGuardTask extends DefaultTask
+{
+ // Accumulated input and output, for the sake of Gradle's lazy file
+ // resolution and lazy task execution.
+ private final List inJarFiles = new ArrayList();
+ private final List inJarFilters = new ArrayList();
+ private final List outJarFiles = new ArrayList();
+ private final List outJarFilters = new ArrayList();
+ private final List inJarCounts = new ArrayList();
+ private final List libraryJarFiles = new ArrayList();
+ private final List libraryJarFilters = new ArrayList();
+ private final List configurationFiles = new ArrayList();
+
+ // Accumulated configuration.
+ private final Configuration configuration = new Configuration();
+
+ // Field acting as a parameter for the class member specification methods.
+ private ClassSpecification classSpecification;
+
+
+ // Gradle task inputs and outputs, because annotations on the List fields
+ // (private or not) don't seem to work. Private methods don't work either,
+ // but package visible or protected methods are ok.
+
+ @InputFiles
+ protected FileCollection getInJarFileCollection()
+ {
+ return getProject().files(inJarFiles);
+ }
+
+ @Optional @OutputFiles
+ protected FileCollection getOutJarFileCollection()
+ {
+ return getProject().files(outJarFiles);
+ }
+
+ @InputFiles
+ protected FileCollection getLibraryJarFileCollection()
+ {
+ return getProject().files(libraryJarFiles);
+ }
+
+ @InputFiles
+ protected FileCollection getConfigurationFileCollection()
+ {
+ return getProject().files(configurationFiles);
+ }
+
+
+ // Convenience methods to retrieve settings from outside the task.
+
+ /**
+ * Returns the collected list of input files (directory, jar, aar, etc,
+ * represented as Object, String, File, etc).
+ */
+ public List getInJarFiles()
+ {
+ return inJarFiles;
+ }
+
+ /**
+ * Returns the collected list of filters (represented as argument Maps)
+ * corresponding to the list of input files.
+ */
+ public List getInJarFilters()
+ {
+ return inJarFilters;
+ }
+
+ /**
+ * Returns the collected list of output files (directory, jar, aar, etc,
+ * represented as Object, String, File, etc).
+ */
+ public List getOutJarFiles()
+ {
+ return outJarFiles;
+ }
+
+ /**
+ * Returns the collected list of filters (represented as argument Maps)
+ * corresponding to the list of output files.
+ */
+ public List getOutJarFilters()
+ {
+ return outJarFilters;
+ }
+
+ /**
+ * Returns the list with the numbers of input files that correspond to the
+ * list of output files.
+ *
+ * For instance, [2, 3] means that
+ * the contents of the first 2 input files go to the first output file and
+ * the contents of the next 3 input files go to the second output file.
+ */
+ public List getInJarCounts()
+ {
+ return inJarCounts;
+ }
+
+ /**
+ * Returns the collected list of library files (directory, jar, aar, etc,
+ * represented as Object, String, File, etc).
+ */
+ public List getLibraryJarFiles()
+ {
+ return libraryJarFiles;
+ }
+
+ /**
+ * Returns the collected list of filters (represented as argument Maps)
+ * corresponding to the list of library files.
+ */
+ public List getLibraryJarFilters()
+ {
+ return libraryJarFilters;
+ }
+
+ /**
+ * Returns the collected list of configuration files to be included
+ * (represented as Object, String, File, etc).
+ */
+ public List getConfigurationFiles()
+ {
+ return configurationFiles;
+ }
+
+
+ // Gradle task settings corresponding to all ProGuard options.
+
+ public void configuration(Object configurationFiles)
+ throws ParseException, IOException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.configurationFiles.add(configurationFiles);
+ }
+
+ public void injars(Object inJarFiles)
+ throws ParseException
+ {
+ injars(null, inJarFiles);
+ }
+
+ public void injars(Map filterArgs, Object inJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.inJarFiles.add(inJarFiles);
+ this.inJarFilters.add(filterArgs);
+ }
+
+ public void outjars(Object outJarFiles)
+ throws ParseException
+ {
+ outjars(null, outJarFiles);
+ }
+
+ public void outjars(Map filterArgs, Object outJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.outJarFiles.add(outJarFiles);
+ this.outJarFilters.add(filterArgs);
+ this.inJarCounts.add(Integer.valueOf(inJarFiles.size()));
+ }
+
+ public void libraryjars(Object libraryJarFiles)
+ throws ParseException
+ {
+ libraryjars(null, libraryJarFiles);
+ }
+
+ public void libraryjars(Map filterArgs, Object libraryJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.libraryJarFiles.add(libraryJarFiles);
+ this.libraryJarFilters.add(filterArgs);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getskipnonpubliclibraryclasses()
+ {
+ skipnonpubliclibraryclasses();
+ return null;
+ }
+
+ public void skipnonpubliclibraryclasses()
+ {
+ configuration.skipNonPublicLibraryClasses = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontskipnonpubliclibraryclassmembers()
+ {
+ dontskipnonpubliclibraryclassmembers();
+ return null;
+ }
+
+ public void dontskipnonpubliclibraryclassmembers()
+ {
+ configuration.skipNonPublicLibraryClassMembers = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepdirectories()
+ {
+ keepdirectories();
+ return null;
+ }
+
+ public void keepdirectories()
+ {
+ keepdirectories(null);
+ }
+
+ public void keepdirectories(String filter)
+ {
+ configuration.keepDirectories =
+ extendFilter(configuration.keepDirectories, filter);
+ }
+
+ public void target(String targetClassVersion)
+ {
+ configuration.targetClassVersion =
+ ClassUtil.internalClassVersion(targetClassVersion);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getforceprocessing()
+ {
+ forceprocessing();
+ return null;
+ }
+
+ public void forceprocessing()
+ {
+ configuration.lastModified = Long.MAX_VALUE;
+ }
+
+ public void keep(String classSpecificationString)
+ throws ParseException
+ {
+ keep(null, classSpecificationString);
+ }
+
+ public void keep(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ true,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keep(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keep(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keep(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ true,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclassmembers(String classSpecificationString)
+ throws ParseException
+ {
+ keepclassmembers(null, classSpecificationString);
+ }
+
+ public void keepclassmembers(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclassmembers(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclassmembers(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclassmembers(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclasseswithmembers(String classSpecificationString)
+ throws ParseException
+ {
+ keepclasseswithmembers(null, classSpecificationString);
+ }
+
+ public void keepclasseswithmembers(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ true,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclasseswithmembers(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclasseswithmembers(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclasseswithmembers(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ true,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepnames(String classSpecificationString)
+ throws ParseException
+ {
+ keepnames(null, classSpecificationString);
+ }
+
+ public void keepnames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ true,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepnames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepnames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepnames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ true,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclassmembernames(String classSpecificationString)
+ throws ParseException
+ {
+ keepclassmembernames(null, classSpecificationString);
+ }
+
+ public void keepclassmembernames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclassmembernames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclassmembernames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclassmembernames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclasseswithmembernames(String classSpecificationString)
+ throws ParseException
+ {
+ keepclasseswithmembernames(null, classSpecificationString);
+ }
+
+ public void keepclasseswithmembernames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ true,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclasseswithmembernames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclasseswithmembernames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclasseswithmembernames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ true,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintseeds()
+ {
+ printseeds();
+ return null;
+ }
+
+ public void printseeds()
+ {
+ configuration.printSeeds = Configuration.STD_OUT;
+ }
+
+ public void printseeds(Object printSeeds)
+ throws ParseException
+ {
+ configuration.printSeeds = getProject().file(printSeeds);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontshrink()
+ {
+ dontshrink();
+ return null;
+ }
+
+ public void dontshrink()
+ {
+ configuration.shrink = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintusage()
+ {
+ printusage();
+ return null;
+ }
+
+ public void printusage()
+ {
+ configuration.printUsage = Configuration.STD_OUT;
+ }
+
+ public void printusage(Object printUsage)
+ throws ParseException
+ {
+ configuration.printUsage = getProject().file(printUsage);
+ }
+
+ public void whyareyoukeeping(String classSpecificationString)
+ throws ParseException
+ {
+ configuration.whyAreYouKeeping =
+ extendClassSpecifications(configuration.whyAreYouKeeping,
+ createClassSpecification(classSpecificationString));
+ }
+
+ public void whyareyoukeeping(Map classSpecificationArgs)
+ throws ParseException
+ {
+ whyareyoukeeping(classSpecificationArgs, null);
+ }
+
+ public void whyareyoukeeping(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.whyAreYouKeeping =
+ extendClassSpecifications(configuration.whyAreYouKeeping,
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontoptimize()
+ {
+ dontoptimize();
+ return null;
+ }
+
+ public void dontoptimize()
+ {
+ configuration.optimize = false;
+ }
+
+ public void optimizations(String filter)
+ {
+ configuration.optimizations =
+ extendFilter(configuration.optimizations, filter);
+ }
+
+
+ public void optimizationpasses(int optimizationPasses)
+ {
+ configuration.optimizationPasses = optimizationPasses;
+ }
+
+ public void assumenosideeffects(String classSpecificationString)
+ throws ParseException
+ {
+ configuration.assumeNoSideEffects =
+ extendClassSpecifications(configuration.assumeNoSideEffects,
+ createClassSpecification(classSpecificationString));
+ }
+
+ public void assumenosideeffects(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.assumeNoSideEffects =
+ extendClassSpecifications(configuration.assumeNoSideEffects,
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getallowaccessmodification()
+ {
+ allowaccessmodification();
+ return null;
+ }
+
+ public void allowaccessmodification()
+ {
+ configuration.allowAccessModification = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getmergeinterfacesaggressively()
+ {
+ mergeinterfacesaggressively();
+ return null;
+ }
+
+ public void mergeinterfacesaggressively()
+ {
+ configuration.mergeInterfacesAggressively = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontobfuscate()
+ {
+ dontobfuscate();
+ return null;
+ }
+
+ public void dontobfuscate()
+ {
+ configuration.obfuscate = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintmapping()
+ {
+ printmapping();
+ return null;
+ }
+
+ public void printmapping()
+ {
+ configuration.printMapping = Configuration.STD_OUT;
+ }
+
+ public void printmapping(Object printMapping)
+ throws ParseException
+ {
+ configuration.printMapping = getProject().file(printMapping);
+ }
+
+ public void applymapping(Object applyMapping)
+ throws ParseException
+ {
+ configuration.applyMapping = getProject().file(applyMapping);
+ }
+
+ public void obfuscationdictionary(Object obfuscationDictionary)
+ throws ParseException
+ {
+ configuration.obfuscationDictionary =
+ getProject().file(obfuscationDictionary);
+ }
+
+ public void classobfuscationdictionary(Object classObfuscationDictionary)
+ throws ParseException
+ {
+ configuration.classObfuscationDictionary =
+ getProject().file(classObfuscationDictionary);
+ }
+
+ public void packageobfuscationdictionary(Object packageObfuscationDictionary)
+ throws ParseException
+ {
+ configuration.packageObfuscationDictionary =
+ getProject().file(packageObfuscationDictionary);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getoverloadaggressively()
+ {
+ overloadaggressively();
+ return null;
+ }
+
+ public void overloadaggressively()
+ {
+ configuration.overloadAggressively = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getuseuniqueclassmembernames()
+ {
+ useuniqueclassmembernames();
+ return null;
+ }
+
+ public void useuniqueclassmembernames()
+ {
+ configuration.useUniqueClassMemberNames = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontusemixedcaseclassnames()
+ {
+ dontusemixedcaseclassnames();
+ return null;
+ }
+
+ public void dontusemixedcaseclassnames()
+ {
+ configuration.useMixedCaseClassNames = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeeppackagenames()
+ {
+ keeppackagenames();
+ return null;
+ }
+
+ public void keeppackagenames()
+ {
+ keeppackagenames(null);
+ }
+
+ public void keeppackagenames(String filter)
+ {
+ configuration.keepPackageNames =
+ extendFilter(configuration.keepPackageNames, filter, true);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getflattenpackagehierarchy()
+ {
+ flattenpackagehierarchy();
+ return null;
+ }
+
+ public void flattenpackagehierarchy()
+ {
+ flattenpackagehierarchy("");
+ }
+
+ public void flattenpackagehierarchy(String flattenPackageHierarchy)
+ {
+ configuration.flattenPackageHierarchy =
+ ClassUtil.internalClassName(flattenPackageHierarchy);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getrepackageclasses()
+ {
+ repackageclasses();
+ return null;
+ }
+
+ public void repackageclasses()
+ {
+ repackageclasses("");
+ }
+
+ public void repackageclasses(String repackageClasses)
+ {
+ configuration.repackageClasses =
+ ClassUtil.internalClassName(repackageClasses);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepattributes()
+ {
+ keepattributes();
+ return null;
+ }
+
+ public void keepattributes()
+ {
+ keepattributes(null);
+ }
+
+ public void keepattributes(String filter)
+ {
+ configuration.keepAttributes =
+ extendFilter(configuration.keepAttributes, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepparameternames()
+ {
+ keepparameternames();
+ return null;
+ }
+
+ public void keepparameternames()
+ {
+ configuration.keepParameterNames = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getrenamesourcefileattribute()
+ {
+ renamesourcefileattribute();
+ return null;
+ }
+
+ public void renamesourcefileattribute()
+ {
+ renamesourcefileattribute("");
+ }
+
+ public void renamesourcefileattribute(String newSourceFileAttribute)
+ {
+ configuration.newSourceFileAttribute = newSourceFileAttribute;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptclassstrings()
+ {
+ adaptclassstrings();
+ return null;
+ }
+
+ public void adaptclassstrings()
+ {
+ adaptclassstrings(null);
+ }
+
+ public void adaptclassstrings(String filter)
+ {
+ configuration.adaptClassStrings =
+ extendFilter(configuration.adaptClassStrings, filter, true);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptresourcefilenames()
+ {
+ adaptresourcefilenames();
+ return null;
+ }
+
+ public void adaptresourcefilenames()
+ {
+ adaptresourcefilenames(null);
+ }
+
+ public void adaptresourcefilenames(String filter)
+ {
+ configuration.adaptResourceFileNames =
+ extendFilter(configuration.adaptResourceFileNames, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptresourcefilecontents()
+ {
+ adaptresourcefilecontents();
+ return null;
+ }
+
+ public void adaptresourcefilecontents()
+ {
+ adaptresourcefilecontents(null);
+ }
+
+ public void adaptresourcefilecontents(String filter)
+ {
+ configuration.adaptResourceFileContents =
+ extendFilter(configuration.adaptResourceFileContents, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontpreverify()
+ {
+ dontpreverify();
+ return null;
+ }
+
+ public void dontpreverify()
+ {
+ configuration.preverify = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getmicroedition()
+ {
+ microedition();
+ return null;
+ }
+
+ public void microedition()
+ {
+ configuration.microEdition = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getverbose()
+ {
+ verbose();
+ return null;
+ }
+
+ public void verbose()
+ {
+ configuration.verbose = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontnote()
+ {
+ dontnote();
+ return null;
+ }
+
+ public void dontnote()
+ {
+ dontnote(null);
+ }
+
+ public void dontnote(String filter)
+ {
+ configuration.note = extendFilter(configuration.note, filter, true);
+ }
+
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontwarn()
+ {
+ dontwarn();
+ return null;
+ }
+
+ public void dontwarn()
+ {
+ dontwarn(null);
+ }
+
+ public void dontwarn(String filter)
+ {
+ configuration.warn = extendFilter(configuration.warn, filter, true);
+ }
+
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getignorewarnings()
+ {
+ ignorewarnings();
+ return null;
+ }
+
+ public void ignorewarnings()
+ {
+ configuration.ignoreWarnings = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintconfiguration()
+ {
+ printconfiguration();
+ return null;
+ }
+
+ public void printconfiguration()
+ {
+ configuration.printConfiguration = Configuration.STD_OUT;
+ }
+
+ public void printconfiguration(Object printConfiguration)
+ throws ParseException
+ {
+ configuration.printConfiguration =
+ getProject().file(printConfiguration);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdump()
+ {
+ dump();
+ return null;
+ }
+
+ public void dump()
+ {
+ configuration.dump = Configuration.STD_OUT;
+ }
+
+ public void dump(Object dump)
+ throws ParseException
+ {
+ configuration.dump = getProject().file(dump);
+ }
+
+
+ // Class member methods.
+
+ public void field(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'field' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addField(createMemberSpecification(false,
+ false,
+ memberSpecificationArgs));
+ }
+
+
+ public void constructor(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'constructor' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addMethod(createMemberSpecification(true,
+ true,
+ memberSpecificationArgs));
+ }
+
+
+ public void method(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'method' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addMethod(createMemberSpecification(true,
+ false,
+ memberSpecificationArgs));
+ }
+
+
+ // Gradle task execution.
+
+ @TaskAction
+ public void proguard()
+ throws ParseException, IOException
+ {
+ // Let the logging manager capture the standard output and errors from
+ // ProGuard.
+ LoggingManager loggingManager = getLogging();
+ loggingManager.captureStandardOutput(LogLevel.INFO);
+ loggingManager.captureStandardError(LogLevel.WARN);
+
+ // Run ProGuard with the collected configuration.
+ new ProGuard(getConfiguration()).execute();
+
+ }
+
+
+ /**
+ * Returns the configuration collected so far, resolving files and
+ * reading included configurations.
+ */
+ private Configuration getConfiguration() throws IOException, ParseException
+ {
+ // Weave the input jars and the output jars into a single class path,
+ // with lazy resolution of the files.
+ configuration.programJars = new ClassPath();
+
+ int outJarIndex = 0;
+
+ int inJarCount = inJarCounts.size() == 0 ? -1 :
+ ((Integer)inJarCounts.get(0)).intValue();
+
+ for (int inJarIndex = 0; inJarIndex < inJarFiles.size(); inJarIndex++)
+ {
+ configuration.programJars =
+ extendClassPath(configuration.programJars,
+ inJarFiles.get(inJarIndex),
+ (Map)inJarFilters.get(inJarIndex),
+ false);
+
+ while (inJarIndex == inJarCount - 1)
+ {
+ configuration.programJars =
+ extendClassPath(configuration.programJars,
+ outJarFiles.get(outJarIndex),
+ (Map)outJarFilters.get(outJarIndex),
+ true);
+
+ outJarIndex++;
+
+ inJarCount = inJarCounts.size() == outJarIndex ? -1 :
+ ((Integer)inJarCounts.get(outJarIndex)).intValue();
+ }
+ }
+
+ // Copy the library jars into a single class path, with lazy resolution
+ // of the files.
+ configuration.libraryJars = new ClassPath();
+
+ for (int libraryJarIndex = 0; libraryJarIndex < libraryJarFiles.size(); libraryJarIndex++)
+ {
+ configuration.libraryJars =
+ extendClassPath(configuration.libraryJars,
+ libraryJarFiles.get(libraryJarIndex),
+ (Map)libraryJarFilters.get(libraryJarIndex),
+ false);
+ }
+
+ // Lazily apply the external configuration files.
+ ConfigurableFileCollection fileCollection =
+ getProject().files(configurationFiles);
+
+ Iterator<File> files = fileCollection.iterator();
+ while (files.hasNext())
+ {
+ ConfigurationParser parser =
+ new ConfigurationParser(files.next(), System.getProperties());
+
+ try
+ {
+ parser.parse(configuration);
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+
+ // Make sure the code is processed. Gradle has already checked that it
+ // was necessary.
+ configuration.lastModified = Long.MAX_VALUE;
+
+ return configuration;
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Extends the given class path with the given filtered input or output
+ * files.
+ */
+ private ClassPath extendClassPath(ClassPath classPath,
+ Object files,
+ Map filterArgs,
+ boolean output)
+ {
+ ConfigurableFileCollection fileCollection = getProject().files(files);
+
+ if (classPath == null)
+ {
+ classPath = new ClassPath();
+ }
+
+ Iterator fileIterator = fileCollection.iterator();
+ while (fileIterator.hasNext())
+ {
+ File file = (File)fileIterator.next();
+ if (output || file.exists())
+ {
+ // Create the class path entry.
+ ClassPathEntry classPathEntry = new ClassPathEntry(file, output);
+
+ // Add any filters to the class path entry.
+ if (filterArgs != null)
+ {
+ classPathEntry.setFilter(ListUtil.commaSeparatedList((String)filterArgs.get("filter")));
+ classPathEntry.setApkFilter(ListUtil.commaSeparatedList((String)filterArgs.get("apkfilter")));
+ classPathEntry.setJarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("jarfilter")));
+ classPathEntry.setAarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("aarfilter")));
+ classPathEntry.setWarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("warfilter")));
+ classPathEntry.setEarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("earfilter")));
+ classPathEntry.setZipFilter(ListUtil.commaSeparatedList((String)filterArgs.get("zipfilter")));
+ }
+
+ classPath.add(classPathEntry);
+ }
+ }
+
+ return classPath;
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ ClassSpecification classSpecification =
+ createClassSpecification(classSpecificationString);
+
+ return
+ createKeepClassSpecification(allowShrinking,
+ markClasses,
+ markConditionally,
+ keepArgs,
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ ClassSpecification classSpecification =
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure);
+ return
+ createKeepClassSpecification(allowShrinking,
+ markClasses,
+ markConditionally,
+ classSpecificationArgs,
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map keepArgs,
+ ClassSpecification classSpecification)
+ {
+ return
+ new KeepClassSpecification(markClasses,
+ markConditionally,
+ retrieveBoolean(keepArgs, "includedescriptorclasses", false),
+ retrieveBoolean(keepArgs, "allowshrinking", allowShrinking),
+ retrieveBoolean(keepArgs, "allowoptimization", false),
+ retrieveBoolean(keepArgs, "allowobfuscation", false),
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given ProGuard-style class specification.
+ */
+ private ClassSpecification createClassSpecification(String classSpecificationString)
+ throws ParseException
+ {
+ try
+ {
+ ConfigurationParser parser =
+ new ConfigurationParser(new String[] { classSpecificationString }, null);
+
+ try
+ {
+ return parser.parseClassSpecificationArguments();
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new ParseException(e.getMessage());
+ }
+ }
+
+
+ /**
+ * Creates a specification of classes and class members, based on the
+ * given parameters.
+ */
+ private ClassSpecification createClassSpecification(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ // Extract the arguments.
+ String access = (String)classSpecificationArgs.get("access");
+ String annotation = (String)classSpecificationArgs.get("annotation");
+ String type = (String)classSpecificationArgs.get("type");
+ String name = (String)classSpecificationArgs.get("name");
+ String extendsAnnotation = (String)classSpecificationArgs.get("extendsannotation");
+ String extends_ = (String)classSpecificationArgs.get("extends");
+ if (extends_ == null)
+ {
+ extends_ = (String)classSpecificationArgs.get("implements");
+ }
+
+ // Create the class specification.
+ ClassSpecification classSpecification =
+ new ClassSpecification(null,
+ requiredClassAccessFlags(true, access, type),
+ requiredClassAccessFlags(false, access, type),
+ annotation != null ? ClassUtil.internalType(annotation) : null,
+ name != null ? ClassUtil.internalClassName(name) : null,
+ extendsAnnotation != null ? ClassUtil.internalType(extendsAnnotation) : null,
+ extends_ != null ? ClassUtil.internalClassName(extends_) : null);
+
+ // Initialize the class specification with its closure.
+ if (classMembersClosure != null)
+ {
+ // Temporarily remember the class specification, so we can add
+ // class member specifications.
+ this.classSpecification = classSpecification;
+ classMembersClosure.call(classSpecification);
+ this.classSpecification = null;
+ }
+
+ return classSpecification;
+ }
+
+
+ /**
+ * Parses the class access flags that must be set (or not), based on the
+ * given ProGuard-style flag specification.
+ */
+ private int requiredClassAccessFlags(boolean set,
+ String access,
+ String type)
+ throws ParseException
+ {
+ int accessFlags = 0;
+
+ if (access != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(access, " ,");
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken();
+
+ if (token.startsWith("!") ^ set)
+ {
+ String strippedToken = token.startsWith("!") ?
+ token.substring(1) :
+ token;
+
+ int accessFlag =
+ strippedToken.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC :
+ strippedToken.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL :
+ strippedToken.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT :
+ strippedToken.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC :
+ strippedToken.equals(JavaConstants.ACC_ANNOTATION) ? ClassConstants.ACC_ANNOTATTION :
+ 0;
+
+ if (accessFlag == 0)
+ {
+ throw new ParseException("Incorrect class access modifier ["+strippedToken+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+ }
+ }
+
+ if (type != null && (type.startsWith("!") ^ set))
+ {
+ int accessFlag =
+ type.equals("class") ? 0 :
+ type.equals( JavaConstants.ACC_INTERFACE) ||
+ type.equals("!" + JavaConstants.ACC_INTERFACE) ? ClassConstants.ACC_INTERFACE :
+ type.equals( JavaConstants.ACC_ENUM) ||
+ type.equals("!" + JavaConstants.ACC_ENUM) ? ClassConstants.ACC_ENUM :
+ -1;
+ if (accessFlag == -1)
+ {
+ throw new ParseException("Incorrect class type ["+type+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+
+ return accessFlags;
+ }
+
+
+ /**
+ * Creates a specification of class members, based on the given parameters.
+ */
+ private MemberSpecification createMemberSpecification(boolean isMethod,
+ boolean isConstructor,
+ Map classSpecificationArgs)
+ throws ParseException
+ {
+ // Extract the arguments.
+ String access = (String)classSpecificationArgs.get("access");
+ String type = (String)classSpecificationArgs.get("type");
+ String annotation = (String)classSpecificationArgs.get("annotation");
+ String name = (String)classSpecificationArgs.get("name");
+ String parameters = (String)classSpecificationArgs.get("parameters");
+
+ // Perform some basic conversions and checks on the attributes.
+ if (annotation != null)
+ {
+ annotation = ClassUtil.internalType(annotation);
+ }
+
+ if (isMethod)
+ {
+ if (isConstructor)
+ {
+ if (type != null)
+ {
+ throw new ParseException("Type attribute not allowed in constructor specification ["+type+"]");
+ }
+
+ if (parameters != null)
+ {
+ type = JavaConstants.TYPE_VOID;
+ }
+
+ name = ClassConstants.METHOD_NAME_INIT;
+ }
+ else if ((type != null) ^ (parameters != null))
+ {
+ throw new ParseException("Type and parameters attributes must always be present in combination in method specification");
+ }
+ }
+ else
+ {
+ if (parameters != null)
+ {
+ throw new ParseException("Parameters attribute not allowed in field specification ["+parameters+"]");
+ }
+ }
+
+ List parameterList = ListUtil.commaSeparatedList(parameters);
+
+ String descriptor =
+ parameters != null ? ClassUtil.internalMethodDescriptor(type, parameterList) :
+ type != null ? ClassUtil.internalType(type) :
+ null;
+
+ return new MemberSpecification(requiredMemberAccessFlags(true, access),
+ requiredMemberAccessFlags(false, access),
+ annotation,
+ name,
+ descriptor);
+ }
+
+
+ /**
+ * Parses the class member access flags that must be set (or not), based on
+ * the given ProGuard-style flag specification.
+ */
+ private int requiredMemberAccessFlags(boolean set,
+ String access)
+ throws ParseException
+ {
+ int accessFlags = 0;
+
+ if (access != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(access, " ,");
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken();
+
+ if (token.startsWith("!") ^ set)
+ {
+ String strippedToken = token.startsWith("!") ?
+ token.substring(1) :
+ token;
+
+ int accessFlag =
+ strippedToken.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC :
+ strippedToken.equals(JavaConstants.ACC_PRIVATE) ? ClassConstants.ACC_PRIVATE :
+ strippedToken.equals(JavaConstants.ACC_PROTECTED) ? ClassConstants.ACC_PROTECTED :
+ strippedToken.equals(JavaConstants.ACC_STATIC) ? ClassConstants.ACC_STATIC :
+ strippedToken.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL :
+ strippedToken.equals(JavaConstants.ACC_SYNCHRONIZED) ? ClassConstants.ACC_SYNCHRONIZED :
+ strippedToken.equals(JavaConstants.ACC_VOLATILE) ? ClassConstants.ACC_VOLATILE :
+ strippedToken.equals(JavaConstants.ACC_TRANSIENT) ? ClassConstants.ACC_TRANSIENT :
+ strippedToken.equals(JavaConstants.ACC_BRIDGE) ? ClassConstants.ACC_BRIDGE :
+ strippedToken.equals(JavaConstants.ACC_VARARGS) ? ClassConstants.ACC_VARARGS :
+ strippedToken.equals(JavaConstants.ACC_NATIVE) ? ClassConstants.ACC_NATIVE :
+ strippedToken.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT :
+ strippedToken.equals(JavaConstants.ACC_STRICT) ? ClassConstants.ACC_STRICT :
+ strippedToken.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC :
+ 0;
+
+ if (accessFlag == 0)
+ {
+ throw new ParseException("Incorrect class member access modifier ["+strippedToken+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+ }
+ }
+
+ return accessFlags;
+ }
+
+
+ /**
+ * Retrieves a specified boolean flag from the given map.
+ */
+ private boolean retrieveBoolean(Map args, String name, boolean defaultValue)
+ {
+ if (args == null)
+ {
+ return defaultValue;
+ }
+
+ Object arg = args.get(name);
+
+ return arg == null ? defaultValue : ((Boolean)arg).booleanValue();
+ }
+
+
+ /**
+ * Adds the given class specification to the given list, creating a new list
+ * if necessary.
+ */
+ private List extendClassSpecifications(List classSpecifications,
+ ClassSpecification classSpecification)
+ {
+ if (classSpecifications == null)
+ {
+ classSpecifications = new ArrayList();
+ }
+
+ classSpecifications.add(classSpecification);
+
+ return classSpecifications;
+ }
+
+
+ /**
+ * Adds the given class specifications to the given list, creating a new
+ * list if necessary.
+ */
+ private List extendClassSpecifications(List classSpecifications,
+ List additionalClassSpecifications)
+ {
+ if (additionalClassSpecifications != null)
+ {
+ if (classSpecifications == null)
+ {
+ classSpecifications = new ArrayList();
+ }
+
+ classSpecifications.addAll(additionalClassSpecifications);
+ }
+
+ return classSpecifications;
+ }
+
+
+ /**
+ * Adds the given filter to the given list, creating a new list if
+ * necessary.
+ */
+ private List extendFilter(List filter,
+ String filterString)
+ {
+ return extendFilter(filter, filterString, false);
+ }
+
+
+ /**
+ * Adds the given filter to the given list, creating a new list if
+ * necessary. External class names are converted to internal class names,
+ * if requested.
+ */
+ private List extendFilter(List filter,
+ String filterString,
+ boolean convertExternalClassNames)
+ {
+ if (filter == null)
+ {
+ filter = new ArrayList();
+ }
+
+ if (filterString == null)
+ {
+ // Clear the filter to keep all names.
+ filter.clear();
+ }
+ else
+ {
+ if (convertExternalClassNames)
+ {
+ filterString = ClassUtil.internalClassName(filterString);
+ }
+
+ // Append the filter.
+ filter.addAll(ListUtil.commaSeparatedList(filterString));
+ }
+
+ return filter;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassPathPanel.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassPathPanel.java
new file mode 100644
index 0000000000..a347fda8d4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassPathPanel.java
@@ -0,0 +1,447 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import proguard.*;
+import proguard.util.ListUtil;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.File;
+import java.util.List;
+
+/**
+ * This <code>ListPanel</code> allows the user to add, edit, filter, move, and
+ * remove ClassPathEntry objects in a ClassPath object.
+ *
+ * @author Eric Lafortune
+ */
+class ClassPathPanel extends ListPanel
+{
+ private final JFrame owner;
+ private final boolean inputAndOutput;
+ private final JFileChooser chooser;
+ private final FilterDialog filterDialog;
+
+
+ public ClassPathPanel(JFrame owner, boolean inputAndOutput)
+ {
+ super();
+
+ super.firstSelectionButton = inputAndOutput ? 3 : 2;
+
+ this.owner = owner;
+ this.inputAndOutput = inputAndOutput;
+
+ list.setCellRenderer(new MyListCellRenderer());
+
+ chooser = new JFileChooser("");
+ chooser.setMultiSelectionEnabled(true);
+ chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
+ chooser.addChoosableFileFilter(
+ new ExtensionFileFilter(msg("jarExtensions"),
+ new String[] { ".apk", ".ap_", ".jar", ".aar", ".war", ".ear", ".zip" }));
+ chooser.setApproveButtonText(msg("ok"));
+
+ filterDialog = new FilterDialog(owner, msg("enterFilter"));
+
+ addAddButton(inputAndOutput, false);
+ if (inputAndOutput)
+ {
+ addAddButton(inputAndOutput, true);
+ }
+ addEditButton();
+ addFilterButton();
+ addRemoveButton();
+ addUpButton();
+ addDownButton();
+
+ enableSelectionButtons();
+ }
+
+
+ protected void addAddButton(boolean inputAndOutput,
+ final boolean isOutput)
+ {
+ JButton addButton = new JButton(msg(inputAndOutput ?
+ isOutput ? "addOutput" :
+ "addInput" :
+ "add"));
+ addButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ chooser.setDialogTitle(msg("addJars"));
+ chooser.setSelectedFile(null);
+ chooser.setSelectedFiles(null);
+
+ int returnValue = chooser.showOpenDialog(owner);
+ if (returnValue == JFileChooser.APPROVE_OPTION)
+ {
+ File[] selectedFiles = chooser.getSelectedFiles();
+ ClassPathEntry[] entries = classPathEntries(selectedFiles, isOutput);
+
+ // Add the new elements.
+ addElements(entries);
+ }
+ }
+ });
+
+ addButton(tip(addButton, inputAndOutput ?
+ isOutput ? "addOutputTip" :
+ "addInputTip" :
+ "addTip"));
+ }
+
+
+ protected void addEditButton()
+ {
+ JButton editButton = new JButton(msg("edit"));
+ editButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ boolean isOutput = false;
+
+ int[] selectedIndices = list.getSelectedIndices();
+
+ // Copy the Object array into a File array.
+ File[] selectedFiles = new File[selectedIndices.length];
+ for (int index = 0; index < selectedFiles.length; index++)
+ {
+ ClassPathEntry entry =
+ (ClassPathEntry)listModel.getElementAt(selectedIndices[index]);
+
+ isOutput = entry.isOutput();
+
+ selectedFiles[index] = entry.getFile();
+ }
+
+ chooser.setDialogTitle(msg("chooseJars"));
+
+ // Up to JDK 1.3.1, setSelectedFiles doesn't show in the file
+ // chooser, so we just use setSelectedFile first. It also sets
+ // the current directory.
+ chooser.setSelectedFile(selectedFiles[0].getAbsoluteFile());
+ chooser.setSelectedFiles(selectedFiles);
+
+ int returnValue = chooser.showOpenDialog(owner);
+ if (returnValue == JFileChooser.APPROVE_OPTION)
+ {
+ selectedFiles = chooser.getSelectedFiles();
+ ClassPathEntry[] entries = classPathEntries(selectedFiles, isOutput);
+
+ // If there are the same number of files selected now as
+ // there were before, we can just replace the old ones.
+ if (selectedIndices.length == selectedFiles.length)
+ {
+ // Replace the old elements.
+ setElementsAt(entries, selectedIndices);
+ }
+ else
+ {
+ // Remove the old elements.
+ removeElementsAt(selectedIndices);
+
+ // Add the new elements.
+ addElements(entries);
+ }
+ }
+ }
+ });
+
+ addButton(tip(editButton, "editTip"));
+ }
+
+
+ protected void addFilterButton()
+ {
+ JButton filterButton = new JButton(msg("filter"));
+ filterButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ if (!list.isSelectionEmpty())
+ {
+ int[] selectedIndices = list.getSelectedIndices();
+
+ // Put the filters of the first selected entry in the dialog.
+ getFiltersFrom(selectedIndices[0]);
+
+ int returnValue = filterDialog.showDialog();
+ if (returnValue == FilterDialog.APPROVE_OPTION)
+ {
+ // Apply the entered filters to all selected entries.
+ setFiltersAt(selectedIndices);
+ }
+ }
+ }
+ });
+
+ addButton(tip(filterButton, "filterTip"));
+ }
+
+
+ /**
+ * Sets the ClassPath to be represented in this panel.
+ */
+ public void setClassPath(ClassPath classPath)
+ {
+ listModel.clear();
+
+ if (classPath != null)
+ {
+ for (int index = 0; index < classPath.size(); index++)
+ {
+ listModel.addElement(classPath.get(index));
+ }
+ }
+
+ // Make sure the selection buttons are properly enabled,
+ // since the clear method doesn't seem to notify the listener.
+ enableSelectionButtons();
+ }
+
+
+ /**
+ * Returns the ClassPath currently represented in this panel.
+ */
+ public ClassPath getClassPath()
+ {
+ int size = listModel.size();
+ if (size == 0)
+ {
+ return null;
+ }
+
+ ClassPath classPath = new ClassPath();
+ for (int index = 0; index < size; index++)
+ {
+ classPath.add((ClassPathEntry)listModel.get(index));
+ }
+
+ return classPath;
+ }
+
+
+ /**
+ * Converts the given array of File objects into a corresponding array of
+ * ClassPathEntry objects.
+ */
+ private ClassPathEntry[] classPathEntries(File[] files, boolean isOutput)
+ {
+ ClassPathEntry[] entries = new ClassPathEntry[files.length];
+ for (int index = 0; index < entries.length; index++)
+ {
+ entries[index] = new ClassPathEntry(files[index], isOutput);
+ }
+ return entries;
+ }
+
+
+ /**
+ * Sets up the filter dialog with the filters from the specified class path
+ * entry.
+ */
+ private void getFiltersFrom(int index)
+ {
+ ClassPathEntry firstEntry = (ClassPathEntry)listModel.get(index);
+
+ filterDialog.setFilter(firstEntry.getFilter());
+ filterDialog.setApkFilter(firstEntry.getApkFilter());
+ filterDialog.setJarFilter(firstEntry.getJarFilter());
+ filterDialog.setAarFilter(firstEntry.getAarFilter());
+ filterDialog.setWarFilter(firstEntry.getWarFilter());
+ filterDialog.setEarFilter(firstEntry.getEarFilter());
+ filterDialog.setZipFilter(firstEntry.getZipFilter());
+ }
+
+
+ /**
+ * Applies the entered filter to the specified class path entries.
+ * Any previously set filters are discarded.
+ */
+ private void setFiltersAt(int[] indices)
+ {
+ for (int index = indices.length - 1; index >= 0; index--)
+ {
+ ClassPathEntry entry = (ClassPathEntry)listModel.get(indices[index]);
+ entry.setFilter(filterDialog.getFilter());
+ entry.setApkFilter(filterDialog.getApkFilter());
+ entry.setJarFilter(filterDialog.getJarFilter());
+ entry.setAarFilter(filterDialog.getAarFilter());
+ entry.setWarFilter(filterDialog.getWarFilter());
+ entry.setEarFilter(filterDialog.getEarFilter());
+ entry.setZipFilter(filterDialog.getZipFilter());
+ }
+
+ // Make sure they are selected and thus repainted.
+ list.setSelectedIndices(indices);
+ }
+
+
+ /**
+ * Attaches the tool tip from the GUI resources that corresponds to the
+ * given key, to the given component.
+ */
+ private static JComponent tip(JComponent component, String messageKey)
+ {
+ component.setToolTipText(msg(messageKey));
+
+ return component;
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private static String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+
+
+ /**
+ * This ListCellRenderer renders ClassPathEntry objects.
+ */
+ private class MyListCellRenderer implements ListCellRenderer
+ {
+ private static final String ARROW_IMAGE_FILE = "arrow.gif";
+
+ private final JPanel cellPanel = new JPanel(new GridBagLayout());
+ private final JLabel iconLabel = new JLabel("", JLabel.RIGHT);
+ private final JLabel jarNameLabel = new JLabel("", JLabel.RIGHT);
+ private final JLabel filterLabel = new JLabel("", JLabel.RIGHT);
+
+ private final Icon arrowIcon;
+
+
+ public MyListCellRenderer()
+ {
+ GridBagConstraints jarNameLabelConstraints = new GridBagConstraints();
+ jarNameLabelConstraints.anchor = GridBagConstraints.WEST;
+ jarNameLabelConstraints.insets = new Insets(1, 2, 1, 2);
+
+ GridBagConstraints filterLabelConstraints = new GridBagConstraints();
+ filterLabelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ filterLabelConstraints.fill = GridBagConstraints.HORIZONTAL;
+ filterLabelConstraints.weightx = 1.0;
+ filterLabelConstraints.anchor = GridBagConstraints.EAST;
+ filterLabelConstraints.insets = jarNameLabelConstraints.insets;
+
+ arrowIcon = new ImageIcon(Toolkit.getDefaultToolkit().getImage(this.getClass().getResource(ARROW_IMAGE_FILE)));
+
+ cellPanel.add(iconLabel, jarNameLabelConstraints);
+ cellPanel.add(jarNameLabel, jarNameLabelConstraints);
+ cellPanel.add(filterLabel, filterLabelConstraints);
+ }
+
+
+ // Implementations for ListCellRenderer.
+
+ public Component getListCellRendererComponent(JList list,
+ Object value,
+ int index,
+ boolean isSelected,
+ boolean cellHasFocus)
+ {
+ ClassPathEntry entry = (ClassPathEntry)value;
+
+ // Prepend an arrow to the output entries.
+ if (inputAndOutput && entry.isOutput())
+ {
+ iconLabel.setIcon(arrowIcon);
+ }
+ else
+ {
+ iconLabel.setIcon(null);
+ }
+
+ // Set the entry name text.
+ jarNameLabel.setText(entry.getName());
+
+ // Set the filter text.
+ StringBuffer filter = null;
+ filter = appendFilter(filter, entry.getZipFilter());
+ filter = appendFilter(filter, entry.getEarFilter());
+ filter = appendFilter(filter, entry.getWarFilter());
+ filter = appendFilter(filter, entry.getAarFilter());
+ filter = appendFilter(filter, entry.getJarFilter());
+ filter = appendFilter(filter, entry.getApkFilter());
+ filter = appendFilter(filter, entry.getFilter());
+
+ if (filter != null)
+ {
+ filter.append(')');
+ }
+
+ filterLabel.setText(filter != null ? filter.toString() : "");
+
+ // Set the colors.
+ if (isSelected)
+ {
+ cellPanel.setBackground(list.getSelectionBackground());
+ jarNameLabel.setForeground(list.getSelectionForeground());
+ filterLabel.setForeground(list.getSelectionForeground());
+ }
+ else
+ {
+ cellPanel.setBackground(list.getBackground());
+ jarNameLabel.setForeground(list.getForeground());
+ filterLabel.setForeground(list.getForeground());
+ }
+
+ // Make the font color red if this is an input file that can't be read.
+ if (!(inputAndOutput && entry.isOutput()) &&
+ !entry.getFile().canRead())
+ {
+ jarNameLabel.setForeground(Color.red);
+ }
+
+ cellPanel.setOpaque(true);
+
+ return cellPanel;
+ }
+
+
+ private StringBuffer appendFilter(StringBuffer filter, List additionalFilter)
+ {
+ if (filter != null)
+ {
+ filter.append(';');
+ }
+
+ if (additionalFilter != null)
+ {
+ if (filter == null)
+ {
+ filter = new StringBuffer().append('(');
+ }
+
+ filter.append(ListUtil.commaSeparatedString(additionalFilter, true));
+ }
+
+ return filter;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassSpecificationDialog.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassSpecificationDialog.java
new file mode 100644
index 0000000000..7ac06335d8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassSpecificationDialog.java
@@ -0,0 +1,562 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import proguard.*;
+import proguard.classfile.ClassConstants;
+import proguard.classfile.util.ClassUtil;
+
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.List;
+
+/**
+ * This <code>JDialog</code> allows the user to enter a String.
+ *
+ * @author Eric Lafortune
+ */
+final class ClassSpecificationDialog extends JDialog
+{
+ /**
+ * Return value if the dialog is canceled (with the Cancel button or by
+ * closing the dialog window).
+ */
+ public static final int CANCEL_OPTION = 1;
+
+ /**
+ * Return value if the dialog is approved (with the Ok button).
+ */
+ public static final int APPROVE_OPTION = 0;
+
+
+ private final JTextArea commentsTextArea = new JTextArea(4, 20);
+
+ private final JRadioButton keepClassesAndMembersRadioButton = new JRadioButton(msg("keep"));
+ private final JRadioButton keepClassMembersRadioButton = new JRadioButton(msg("keepClassMembers"));
+ private final JRadioButton keepClassesWithMembersRadioButton = new JRadioButton(msg("keepClassesWithMembers"));
+
+ private final JCheckBox keepDescriptorClassesCheckBox = new JCheckBox(msg("keepDescriptorClasses"));
+
+ private final JCheckBox allowShrinkingCheckBox = new JCheckBox(msg("allowShrinking"));
+ private final JCheckBox allowOptimizationCheckBox = new JCheckBox(msg("allowOptimization"));
+ private final JCheckBox allowObfuscationCheckBox = new JCheckBox(msg("allowObfuscation"));
+
+
+ private final JRadioButton[] publicRadioButtons;
+ private final JRadioButton[] finalRadioButtons;
+ private final JRadioButton[] abstractRadioButtons;
+ private final JRadioButton[] interfaceRadioButtons;
+ private final JRadioButton[] annotationRadioButtons;
+ private final JRadioButton[] enumRadioButtons;
+ private final JRadioButton[] syntheticRadioButtons;
+
+ private final JTextField annotationTypeTextField = new JTextField(20);
+ private final JTextField classNameTextField = new JTextField(20);
+ private final JTextField extendsAnnotationTypeTextField = new JTextField(20);
+ private final JTextField extendsClassNameTextField = new JTextField(20);
+
+ private final MemberSpecificationsPanel memberSpecificationsPanel;
+
+ private int returnValue;
+
+
+ public ClassSpecificationDialog(JFrame owner, boolean fullKeepOptions)
+ {
+ super(owner, msg("specifyClasses"), true);
+ setResizable(true);
+
+ // Create some constraints that can be reused.
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.anchor = GridBagConstraints.WEST;
+ constraints.insets = new Insets(1, 2, 1, 2);
+
+ GridBagConstraints constraintsStretch = new GridBagConstraints();
+ constraintsStretch.fill = GridBagConstraints.HORIZONTAL;
+ constraintsStretch.weightx = 1.0;
+ constraintsStretch.anchor = GridBagConstraints.WEST;
+ constraintsStretch.insets = constraints.insets;
+
+ GridBagConstraints constraintsLast = new GridBagConstraints();
+ constraintsLast.gridwidth = GridBagConstraints.REMAINDER;
+ constraintsLast.anchor = GridBagConstraints.WEST;
+ constraintsLast.insets = constraints.insets;
+
+ GridBagConstraints constraintsLastStretch = new GridBagConstraints();
+ constraintsLastStretch.gridwidth = GridBagConstraints.REMAINDER;
+ constraintsLastStretch.fill = GridBagConstraints.HORIZONTAL;
+ constraintsLastStretch.weightx = 1.0;
+ constraintsLastStretch.anchor = GridBagConstraints.WEST;
+ constraintsLastStretch.insets = constraints.insets;
+
+ GridBagConstraints panelConstraints = new GridBagConstraints();
+ panelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ panelConstraints.fill = GridBagConstraints.HORIZONTAL;
+ panelConstraints.weightx = 1.0;
+ panelConstraints.weighty = 0.0;
+ panelConstraints.anchor = GridBagConstraints.NORTHWEST;
+ panelConstraints.insets = constraints.insets;
+
+ GridBagConstraints stretchPanelConstraints = new GridBagConstraints();
+ stretchPanelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ stretchPanelConstraints.fill = GridBagConstraints.BOTH;
+ stretchPanelConstraints.weightx = 1.0;
+ stretchPanelConstraints.weighty = 1.0;
+ stretchPanelConstraints.anchor = GridBagConstraints.NORTHWEST;
+ stretchPanelConstraints.insets = constraints.insets;
+
+ GridBagConstraints labelConstraints = new GridBagConstraints();
+ labelConstraints.anchor = GridBagConstraints.CENTER;
+ labelConstraints.insets = new Insets(2, 10, 2, 10);
+
+ GridBagConstraints lastLabelConstraints = new GridBagConstraints();
+ lastLabelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ lastLabelConstraints.anchor = GridBagConstraints.CENTER;
+ lastLabelConstraints.insets = labelConstraints.insets;
+
+ GridBagConstraints advancedButtonConstraints = new GridBagConstraints();
+ advancedButtonConstraints.weightx = 1.0;
+ advancedButtonConstraints.weighty = 1.0;
+ advancedButtonConstraints.anchor = GridBagConstraints.SOUTHWEST;
+ advancedButtonConstraints.insets = new Insets(4, 4, 8, 4);
+
+ GridBagConstraints okButtonConstraints = new GridBagConstraints();
+ okButtonConstraints.weightx = 1.0;
+ okButtonConstraints.weighty = 1.0;
+ okButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ okButtonConstraints.insets = advancedButtonConstraints.insets;
+
+ GridBagConstraints cancelButtonConstraints = new GridBagConstraints();
+ cancelButtonConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ cancelButtonConstraints.weighty = 1.0;
+ cancelButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ cancelButtonConstraints.insets = advancedButtonConstraints.insets;
+
+ GridBagLayout layout = new GridBagLayout();
+
+ Border etchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
+
+ // Create the comments panel.
+ JPanel commentsPanel = new JPanel(layout);
+ commentsPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("comments")));
+
+ JScrollPane commentsScrollPane = new JScrollPane(commentsTextArea);
+ commentsScrollPane.setBorder(classNameTextField.getBorder());
+
+ commentsPanel.add(tip(commentsScrollPane, "commentsTip"), constraintsLastStretch);
+
+ // Create the keep option panel.
+ ButtonGroup keepButtonGroup = new ButtonGroup();
+ keepButtonGroup.add(keepClassesAndMembersRadioButton);
+ keepButtonGroup.add(keepClassMembersRadioButton);
+ keepButtonGroup.add(keepClassesWithMembersRadioButton);
+
+ JPanel keepOptionPanel = new JPanel(layout);
+ keepOptionPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("keepTitle")));
+
+ keepOptionPanel.add(tip(keepClassesAndMembersRadioButton, "keepTip"), constraintsLastStretch);
+ keepOptionPanel.add(tip(keepClassMembersRadioButton, "keepClassMembersTip"), constraintsLastStretch);
+ keepOptionPanel.add(tip(keepClassesWithMembersRadioButton, "keepClassesWithMembersTip"), constraintsLastStretch);
+ keepOptionPanel.add(tip(keepDescriptorClassesCheckBox, "keepDescriptorClassesTip"), constraintsLastStretch);
+
+ // Create the also keep panel.
+ final JPanel alsoKeepOptionPanel = new JPanel(layout);
+ alsoKeepOptionPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("alsoKeepTitle")));
+
+ alsoKeepOptionPanel.add(tip(keepDescriptorClassesCheckBox, "keepDescriptorClassesTip"), constraintsLastStretch);
+
+ // Create the allow option panel.
+ final JPanel allowOptionPanel = new JPanel(layout);
+ allowOptionPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("allowTitle")));
+
+ allowOptionPanel.add(tip(allowShrinkingCheckBox, "allowShrinkingTip"), constraintsLastStretch);
+ allowOptionPanel.add(tip(allowOptimizationCheckBox, "allowOptimizationTip"), constraintsLastStretch);
+ allowOptionPanel.add(tip(allowObfuscationCheckBox, "allowObfuscationTip"), constraintsLastStretch);
+
+ // Create the access panel.
+ JPanel accessPanel = new JPanel(layout);
+ accessPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("access")));
+
+ accessPanel.add(Box.createGlue(), labelConstraints);
+ accessPanel.add(tip(new JLabel(msg("required")), "requiredTip"), labelConstraints);
+ accessPanel.add(tip(new JLabel(msg("not")), "notTip"), labelConstraints);
+ accessPanel.add(tip(new JLabel(msg("dontCare")), "dontCareTip"), labelConstraints);
+ accessPanel.add(Box.createGlue(), constraintsLastStretch);
+
+ publicRadioButtons = addRadioButtonTriplet("Public", accessPanel);
+ finalRadioButtons = addRadioButtonTriplet("Final", accessPanel);
+ abstractRadioButtons = addRadioButtonTriplet("Abstract", accessPanel);
+ interfaceRadioButtons = addRadioButtonTriplet("Interface", accessPanel);
+ annotationRadioButtons = addRadioButtonTriplet("Annotation", accessPanel);
+ enumRadioButtons = addRadioButtonTriplet("Enum", accessPanel);
+ syntheticRadioButtons = addRadioButtonTriplet("Synthetic", accessPanel);
+
+ // Create the annotation type panel.
+ final JPanel annotationTypePanel = new JPanel(layout);
+ annotationTypePanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("annotation")));
+
+ annotationTypePanel.add(tip(annotationTypeTextField, "classNameTip"), constraintsLastStretch);
+
+ // Create the class name panel.
+ JPanel classNamePanel = new JPanel(layout);
+ classNamePanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("class")));
+
+ classNamePanel.add(tip(classNameTextField, "classNameTip"), constraintsLastStretch);
+
+ // Create the extends annotation type panel.
+ final JPanel extendsAnnotationTypePanel = new JPanel(layout);
+ extendsAnnotationTypePanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("extendsImplementsAnnotation")));
+
+ extendsAnnotationTypePanel.add(tip(extendsAnnotationTypeTextField, "classNameTip"), constraintsLastStretch);
+
+ // Create the extends class name panel.
+ JPanel extendsClassNamePanel = new JPanel(layout);
+ extendsClassNamePanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("extendsImplementsClass")));
+
+ extendsClassNamePanel.add(tip(extendsClassNameTextField, "classNameTip"), constraintsLastStretch);
+
+
+ // Create the class member list panel.
+ memberSpecificationsPanel = new MemberSpecificationsPanel(this, fullKeepOptions);
+ memberSpecificationsPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("classMembers")));
+
+ // Create the Advanced button.
+ final JButton advancedButton = new JButton(msg("basic"));
+ advancedButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ boolean visible = !alsoKeepOptionPanel.isVisible();
+
+ alsoKeepOptionPanel .setVisible(visible);
+ allowOptionPanel .setVisible(visible);
+ annotationTypePanel .setVisible(visible);
+ extendsAnnotationTypePanel.setVisible(visible);
+
+ advancedButton.setText(msg(visible ? "basic" : "advanced"));
+
+ pack();
+ }
+ });
+ advancedButton.doClick();
+
+ // Create the Ok button.
+ JButton okButton = new JButton(msg("ok"));
+ okButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ returnValue = APPROVE_OPTION;
+ hide();
+ }
+ });
+
+ // Create the Cancel button.
+ JButton cancelButton = new JButton(msg("cancel"));
+ cancelButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ hide();
+ }
+ });
+
+ // Add all panels to the main panel.
+ JPanel mainPanel = new JPanel(layout);
+ mainPanel.add(tip(commentsPanel, "commentsTip"), panelConstraints);
+ if (fullKeepOptions)
+ {
+ mainPanel.add(tip(keepOptionPanel, "keepTitleTip"), panelConstraints);
+ mainPanel.add(tip(alsoKeepOptionPanel, "alsoKeepTitleTip"), panelConstraints);
+ mainPanel.add(tip(allowOptionPanel, "allowTitleTip"), panelConstraints);
+ }
+ mainPanel.add(tip(accessPanel, "accessTip"), panelConstraints);
+ mainPanel.add(tip(annotationTypePanel, "annotationTip"), panelConstraints);
+ mainPanel.add(tip(classNamePanel, "classTip"), panelConstraints);
+ mainPanel.add(tip(extendsAnnotationTypePanel, "extendsImplementsAnnotationTip"), panelConstraints);
+ mainPanel.add(tip(extendsClassNamePanel, "extendsImplementsClassTip"), panelConstraints);
+ mainPanel.add(tip(memberSpecificationsPanel, "classMembersTip"), stretchPanelConstraints);
+
+ mainPanel.add(tip(advancedButton, "advancedTip"), advancedButtonConstraints);
+ mainPanel.add(okButton, okButtonConstraints);
+ mainPanel.add(cancelButton, cancelButtonConstraints);
+
+ getContentPane().add(new JScrollPane(mainPanel));
+ }
+
+
+ /**
+ * Adds a JLabel and three JRadioButton instances in a ButtonGroup to the
+ * given panel with a GridBagLayout, and returns the buttons in an array.
+ */
+ private JRadioButton[] addRadioButtonTriplet(String labelText,
+ JPanel panel)
+ {
+ GridBagConstraints labelConstraints = new GridBagConstraints();
+ labelConstraints.anchor = GridBagConstraints.WEST;
+ labelConstraints.insets = new Insets(2, 10, 2, 10);
+
+ GridBagConstraints buttonConstraints = new GridBagConstraints();
+ buttonConstraints.insets = labelConstraints.insets;
+
+ GridBagConstraints lastGlueConstraints = new GridBagConstraints();
+ lastGlueConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ lastGlueConstraints.weightx = 1.0;
+
+ // Create the radio buttons.
+ JRadioButton radioButton0 = new JRadioButton();
+ JRadioButton radioButton1 = new JRadioButton();
+ JRadioButton radioButton2 = new JRadioButton();
+
+ // Put them in a button group.
+ ButtonGroup buttonGroup = new ButtonGroup();
+ buttonGroup.add(radioButton0);
+ buttonGroup.add(radioButton1);
+ buttonGroup.add(radioButton2);
+
+ // Add the label and the buttons to the panel.
+ panel.add(new JLabel(labelText), labelConstraints);
+ panel.add(radioButton0, buttonConstraints);
+ panel.add(radioButton1, buttonConstraints);
+ panel.add(radioButton2, buttonConstraints);
+ panel.add(Box.createGlue(), lastGlueConstraints);
+
+ return new JRadioButton[]
+ {
+ radioButton0,
+ radioButton1,
+ radioButton2
+ };
+ }
+
+
+ /**
+ * Sets the KeepClassSpecification to be represented in this dialog.
+ */
+ public void setKeepSpecification(KeepClassSpecification keepClassSpecification)
+ {
+ boolean markClasses = keepClassSpecification.markClasses;
+ boolean markConditionally = keepClassSpecification.markConditionally;
+ boolean markDescriptorClasses = keepClassSpecification.markDescriptorClasses;
+ boolean allowShrinking = keepClassSpecification.allowShrinking;
+ boolean allowOptimization = keepClassSpecification.allowOptimization;
+ boolean allowObfuscation = keepClassSpecification.allowObfuscation;
+
+ // Figure out the proper keep radio button and set it.
+ JRadioButton keepOptionRadioButton =
+ markConditionally ? keepClassesWithMembersRadioButton :
+ markClasses ? keepClassesAndMembersRadioButton :
+ keepClassMembersRadioButton;
+
+ keepOptionRadioButton.setSelected(true);
+
+ // Set the other check boxes.
+ keepDescriptorClassesCheckBox.setSelected(markDescriptorClasses);
+ allowShrinkingCheckBox .setSelected(allowShrinking);
+ allowOptimizationCheckBox .setSelected(allowOptimization);
+ allowObfuscationCheckBox .setSelected(allowObfuscation);
+
+ setClassSpecification(keepClassSpecification);
+ }
+
+
+ /**
+ * Sets the ClassSpecification to be represented in this dialog.
+ */
+ public void setClassSpecification(ClassSpecification classSpecification)
+ {
+ String comments = classSpecification.comments;
+ String annotationType = classSpecification.annotationType;
+ String className = classSpecification.className;
+ String extendsAnnotationType = classSpecification.extendsAnnotationType;
+ String extendsClassName = classSpecification.extendsClassName;
+ List keepFieldOptions = classSpecification.fieldSpecifications;
+ List keepMethodOptions = classSpecification.methodSpecifications;
+
+ // Set the comments text area.
+ commentsTextArea.setText(comments == null ? "" : comments);
+
+ // Set the access radio buttons.
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_PUBLIC, publicRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_FINAL, finalRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ABSTRACT, abstractRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_INTERFACE, interfaceRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ANNOTATTION, annotationRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ENUM, enumRadioButtons);
+ setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_SYNTHETIC, syntheticRadioButtons);
+
+ // Set the class and annotation text fields.
+ annotationTypeTextField .setText(annotationType == null ? "" : ClassUtil.externalType(annotationType));
+ classNameTextField .setText(className == null ? "*" : ClassUtil.externalClassName(className));
+ extendsAnnotationTypeTextField.setText(extendsAnnotationType == null ? "" : ClassUtil.externalType(extendsAnnotationType));
+ extendsClassNameTextField .setText(extendsClassName == null ? "" : ClassUtil.externalClassName(extendsClassName));
+
+ // Set the keep class member option list.
+ memberSpecificationsPanel.setMemberSpecifications(keepFieldOptions, keepMethodOptions);
+ }
+
+
+ /**
+ * Returns the KeepClassSpecification currently represented in this dialog.
+ */
+ public KeepClassSpecification getKeepSpecification()
+ {
+ boolean markClasses = !keepClassMembersRadioButton .isSelected();
+ boolean markConditionally = keepClassesWithMembersRadioButton.isSelected();
+ boolean markDescriptorClasses = keepDescriptorClassesCheckBox .isSelected();
+ boolean allowShrinking = allowShrinkingCheckBox .isSelected();
+ boolean allowOptimization = allowOptimizationCheckBox .isSelected();
+ boolean allowObfuscation = allowObfuscationCheckBox .isSelected();
+
+ return new KeepClassSpecification(markClasses,
+ markConditionally,
+ markDescriptorClasses,
+ allowShrinking,
+ allowOptimization,
+ allowObfuscation,
+ getClassSpecification());
+ }
+
+
+ /**
+ * Returns the ClassSpecification currently represented in this dialog.
+ */
+ public ClassSpecification getClassSpecification()
+ {
+ String comments = commentsTextArea.getText();
+ String annotationType = annotationTypeTextField.getText();
+ String className = classNameTextField.getText();
+ String extendsAnnotationType = extendsAnnotationTypeTextField.getText();
+ String extendsClassName = extendsClassNameTextField.getText();
+
+ ClassSpecification classSpecification =
+ new ClassSpecification(comments.equals("") ? null : comments,
+ 0,
+ 0,
+ annotationType.equals("") ? null : ClassUtil.internalType(annotationType),
+ className.equals("") ||
+ className.equals("*") ? null : ClassUtil.internalClassName(className),
+ extendsAnnotationType.equals("") ? null : ClassUtil.internalType(extendsAnnotationType),
+ extendsClassName.equals("") ? null : ClassUtil.internalClassName(extendsClassName));
+
+ // Also get the access radio button settings.
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_PUBLIC, publicRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_FINAL, finalRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ABSTRACT, abstractRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_INTERFACE, interfaceRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ANNOTATTION, annotationRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ENUM, enumRadioButtons);
+ getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_SYNTHETIC, syntheticRadioButtons);
+
+ // Get the keep class member option lists.
+ classSpecification.fieldSpecifications = memberSpecificationsPanel.getMemberSpecifications(true);
+ classSpecification.methodSpecifications = memberSpecificationsPanel.getMemberSpecifications(false);
+
+ return classSpecification;
+ }
+
+
+ /**
+ * Shows this dialog. This method only returns when the dialog is closed.
+ *
+ * @return <code>CANCEL_OPTION</code> or <code>APPROVE_OPTION</code>,
+ * depending on the choice of the user.
+ */
+ public int showDialog()
+ {
+ returnValue = CANCEL_OPTION;
+
+ // Open the dialog in the right place, then wait for it to be closed,
+ // one way or another.
+ pack();
+ setLocationRelativeTo(getOwner());
+ show();
+
+ return returnValue;
+ }
+
+
+ /**
+ * Sets the appropriate radio button of a given triplet, based on the access
+ * flags of the given keep option.
+ */
+ private void setClassSpecificationRadioButtons(ClassSpecification classSpecification,
+ int flag,
+ JRadioButton[] radioButtons)
+ {
+ int index = (classSpecification.requiredSetAccessFlags & flag) != 0 ? 0 :
+ (classSpecification.requiredUnsetAccessFlags & flag) != 0 ? 1 :
+ 2;
+ radioButtons[index].setSelected(true);
+ }
+
+
+ /**
+ * Updates the access flag of the given keep option, based on the given radio
+ * button triplet.
+ */
+ private void getClassSpecificationRadioButtons(ClassSpecification classSpecification,
+ int flag,
+ JRadioButton[] radioButtons)
+ {
+ if (radioButtons[0].isSelected())
+ {
+ classSpecification.requiredSetAccessFlags |= flag;
+ }
+ else if (radioButtons[1].isSelected())
+ {
+ classSpecification.requiredUnsetAccessFlags |= flag;
+ }
+ }
+
+
+ /**
+ * Attaches the tool tip from the GUI resources that corresponds to the
+ * given key, to the given component.
+ */
+ private static JComponent tip(JComponent component, String messageKey)
+ {
+ component.setToolTipText(msg(messageKey));
+
+ return component;
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private static String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassSpecificationsPanel.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassSpecificationsPanel.java
new file mode 100644
index 0000000000..de11ab87ba
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ClassSpecificationsPanel.java
@@ -0,0 +1,231 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import proguard.ClassSpecification;
+import proguard.classfile.util.ClassUtil;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.util.List;
+
+
+/**
+ * This <code>ListPanel</code> allows the user to add, edit, move, and remove
+ * ClassSpecification entries in a list.
+ *
+ * @author Eric Lafortune
+ */
+class ClassSpecificationsPanel extends ListPanel
+{
+ protected final ClassSpecificationDialog classSpecificationDialog;
+
+
+ public ClassSpecificationsPanel(JFrame owner, boolean fullKeepOptions)
+ {
+ super();
+
+ list.setCellRenderer(new MyListCellRenderer());
+
+ classSpecificationDialog = new ClassSpecificationDialog(owner, fullKeepOptions);
+
+ addAddButton();
+ addEditButton();
+ addRemoveButton();
+ addUpButton();
+ addDownButton();
+
+ enableSelectionButtons();
+ }
+
+
+ protected void addAddButton()
+ {
+ JButton addButton = new JButton(msg("add"));
+ addButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ setClassSpecification(createClassSpecification());
+ int returnValue = classSpecificationDialog.showDialog();
+ if (returnValue == ClassSpecificationDialog.APPROVE_OPTION)
+ {
+ // Add the new element.
+ addElement(getClassSpecification());
+ }
+ }
+ });
+
+ addButton(tip(addButton, "addTip"));
+ }
+
+
+ protected void addEditButton()
+ {
+ JButton editButton = new JButton(msg("edit"));
+ editButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ ClassSpecification selectedClassSpecification =
+ (ClassSpecification)list.getSelectedValue();
+
+ setClassSpecification(selectedClassSpecification);
+ int returnValue = classSpecificationDialog.showDialog();
+ if (returnValue == ClassSpecificationDialog.APPROVE_OPTION)
+ {
+ // Replace the old element.
+ setElementAt(getClassSpecification(),
+ list.getSelectedIndex());
+ }
+ }
+ });
+
+ addButton(tip(editButton, "editTip"));
+ }
+
+
+ protected ClassSpecification createClassSpecification()
+ {
+ return new ClassSpecification();
+ }
+
+
+ protected void setClassSpecification(ClassSpecification classSpecification)
+ {
+ classSpecificationDialog.setClassSpecification(classSpecification);
+ }
+
+
+ protected ClassSpecification getClassSpecification()
+ {
+ return classSpecificationDialog.getClassSpecification();
+ }
+
+
+ /**
+ * Sets the ClassSpecification objects to be represented in this panel.
+ */
+ public void setClassSpecifications(List classSpecifications)
+ {
+ listModel.clear();
+
+ if (classSpecifications != null)
+ {
+ for (int index = 0; index < classSpecifications.size(); index++)
+ {
+ listModel.addElement(classSpecifications.get(index));
+ }
+ }
+
+ // Make sure the selection buttons are properly enabled,
+ // since the clear method doesn't seem to notify the listener.
+ enableSelectionButtons();
+ }
+
+
+ /**
+ * Returns the ClassSpecification objects currently represented in this panel.
+ */
+ public List getClassSpecifications()
+ {
+ int size = listModel.size();
+ if (size == 0)
+ {
+ return null;
+ }
+
+ List classSpecifications = new ArrayList(size);
+ for (int index = 0; index < size; index++)
+ {
+ classSpecifications.add(listModel.get(index));
+ }
+
+ return classSpecifications;
+ }
+
+
+ /**
+ * Attaches the tool tip from the GUI resources that corresponds to the
+ * given key, to the given component.
+ */
+ private static JComponent tip(JComponent component, String messageKey)
+ {
+ component.setToolTipText(msg(messageKey));
+
+ return component;
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private static String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+
+
+ /**
+ * This ListCellRenderer renders ClassSpecification objects.
+ */
+ private static class MyListCellRenderer implements ListCellRenderer
+ {
+ private final JLabel label = new JLabel();
+
+
+ // Implementations for ListCellRenderer.
+
+ public Component getListCellRendererComponent(JList list,
+ Object value,
+ int index,
+ boolean isSelected,
+ boolean cellHasFocus)
+ {
+ ClassSpecification classSpecification = (ClassSpecification)value;
+
+ String comments = classSpecification.comments;
+
+ label.setText(comments != null ? comments.trim() :
+ classSpecification.className != null ? (msg("class") + ' ' + ClassUtil.externalClassName(classSpecification.className)) :
+ classSpecification.extendsClassName != null ? (msg("extensionsOf") + ' ' + ClassUtil.externalClassName(classSpecification.extendsClassName)) :
+ (msg("specificationNumber") + index));
+
+ if (isSelected)
+ {
+ label.setBackground(list.getSelectionBackground());
+ label.setForeground(list.getSelectionForeground());
+ }
+ else
+ {
+ label.setBackground(list.getBackground());
+ label.setForeground(list.getForeground());
+ }
+
+ label.setOpaque(true);
+
+ return label;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ExtensionFileFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ExtensionFileFilter.java
new file mode 100644
index 0000000000..21759c8943
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ExtensionFileFilter.java
@@ -0,0 +1,78 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import javax.swing.filechooser.FileFilter;
+import java.io.File;
+
+
+/**
+ * This <code>FileFilter</code> accepts files that end in one of the given
+ * extensions.
+ *
+ * @author Eric Lafortune
+ */
+final class ExtensionFileFilter extends FileFilter
+{
+ private final String description;
+ private final String[] extensions;
+
+
+ /**
+ * Creates a new ExtensionFileFilter.
+ * @param description a description of the filter.
+ * @param extensions an array of acceptable extensions.
+ */
+ public ExtensionFileFilter(String description, String[] extensions)
+ {
+ this.description = description;
+ this.extensions = extensions;
+ }
+
+
+ // Implemntations for FileFilter
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+
+ public boolean accept(File file)
+ {
+ if (file.isDirectory())
+ {
+ return true;
+ }
+
+ String fileName = file.getName().toLowerCase();
+
+ for (int index = 0; index < extensions.length; index++)
+ {
+ if (fileName.endsWith(extensions[index]))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/FilterBuilder.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/FilterBuilder.java
new file mode 100644
index 0000000000..b824aee9e2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/FilterBuilder.java
@@ -0,0 +1,208 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import javax.swing.*;
+
+/**
+ * This class builds filters corresponding to the selections and names of a
+ * given list of check boxes.
+ */
+public class FilterBuilder
+{
+ private JCheckBox[] checkBoxes;
+ private char separator;
+
+
+ /**
+ * Creates a new FilterBuilder.
+ * @param checkBoxes the check boxes with names and selections that should
+ * be reflected in the output filter.
+ * @param separator the separator for the names in the check boxes.
+ */
+ public FilterBuilder(JCheckBox[] checkBoxes, char separator)
+ {
+ this.checkBoxes = checkBoxes;
+ this.separator = separator;
+ }
+
+
+ /**
+ * Builds a filter for the current names and selections of the check boxes.
+ */
+ public String buildFilter()
+ {
+ StringBuffer positive = new StringBuffer();
+ StringBuffer negative = new StringBuffer();
+
+ buildFilter("", positive, negative);
+
+ return positive.length() <= negative.length() ?
+ positive.toString() :
+ negative.toString();
+ }
+
+
+ /**
+ * Builds two versions of the filter for the given prefix.
+ * @param prefix the prefix.
+ * @param positive the filter to be extended, assuming the matching
+ * strings are accepted.
+ * @param negative the filter to be extended, assuming the matching
+ * strings are rejected.
+ */
+ private void buildFilter(String prefix,
+ StringBuffer positive,
+ StringBuffer negative)
+ {
+ int positiveCount = 0;
+ int negativeCount = 0;
+
+ // Count all selected and unselected check boxes with the prefix.
+ for (int index = 0; index < checkBoxes.length; index++)
+ {
+ JCheckBox checkBox = checkBoxes[index];
+ String name = checkBox.getText();
+
+ if (name.startsWith(prefix))
+ {
+ if (checkBox.isSelected())
+ {
+ positiveCount++;
+ }
+ else
+ {
+ negativeCount++;
+ }
+ }
+ }
+
+ // Are there only unselected check boxes?
+ if (positiveCount == 0)
+ {
+ // Extend the positive filter with exceptions and return.
+ if (positive.length() > 0)
+ {
+ positive.append(',');
+ }
+ positive.append('!').append(prefix);
+ if (prefix.length() == 0 ||
+ prefix.charAt(prefix.length()-1) == separator)
+ {
+ positive.append('*');
+ }
+
+ return;
+ }
+
+ // Are there only selected check boxes?
+ if (negativeCount == 0)
+ {
+ // Extend the negative filter with exceptions and return.
+ if (negative.length() > 0)
+ {
+ negative.append(',');
+ }
+ negative.append(prefix);
+ if (prefix.length() == 0 ||
+ prefix.charAt(prefix.length()-1) == separator)
+ {
+ negative.append('*');
+ }
+
+ return;
+ }
+
+ // Create new positive and negative filters for names starting with the
+ // prefix only.
+ StringBuffer positiveFilter = new StringBuffer();
+ StringBuffer negativeFilter = new StringBuffer();
+
+ String newPrefix = null;
+
+ for (int index = 0; index < checkBoxes.length; index++)
+ {
+ String name = checkBoxes[index].getText();
+
+ if (name.startsWith(prefix))
+ {
+ if (newPrefix == null ||
+ !name.startsWith(newPrefix))
+ {
+ int prefixIndex =
+ name.indexOf(separator, prefix.length()+1);
+
+ newPrefix = prefixIndex >= 0 ?
+ name.substring(0, prefixIndex+1) :
+ name;
+
+ buildFilter(newPrefix,
+ positiveFilter,
+ negativeFilter);
+ }
+ }
+ }
+
+ // Extend the positive filter.
+ if (positiveFilter.length() <= negativeFilter.length() + prefix.length() + 3)
+ {
+ if (positive.length() > 0 &&
+ positiveFilter.length() > 0)
+ {
+ positive.append(',');
+ }
+
+ positive.append(positiveFilter);
+ }
+ else
+ {
+ if (positive.length() > 0 &&
+ negativeFilter.length() > 0)
+ {
+ positive.append(',');
+ }
+
+ positive.append(negativeFilter).append(",!").append(prefix).append('*');
+ }
+
+ // Extend the negative filter.
+ if (negativeFilter.length() <= positiveFilter.length() + prefix.length() + 4)
+ {
+ if (negative.length() > 0 &&
+ negativeFilter.length() > 0)
+ {
+ negative.append(',');
+ }
+
+ negative.append(negativeFilter);
+ }
+ else
+ {
+ if (negative.length() > 0 &&
+ positiveFilter.length() > 0)
+ {
+ negative.append(',');
+ }
+
+ negative.append(positiveFilter).append(',').append(prefix).append('*');
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/FilterDialog.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/FilterDialog.java
new file mode 100644
index 0000000000..2c7b49fa88
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/FilterDialog.java
@@ -0,0 +1,373 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import proguard.util.ListUtil;
+
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.List;
+
+/**
+ * This <code>JDialog</code> allows the user to enter a String.
+ *
+ * @author Eric Lafortune
+ */
+public class FilterDialog extends JDialog
+{
+ /**
+ * Return value if the dialog is canceled (with the Cancel button or by
+ * closing the dialog window).
+ */
+ public static final int CANCEL_OPTION = 1;
+
+ /**
+ * Return value if the dialog is approved (with the Ok button).
+ */
+ public static final int APPROVE_OPTION = 0;
+
+ private static final String DEFAULT_FILTER = "**";
+ private static final String DEFAULT_APK_FILTER = "**.apk";
+ private static final String DEFAULT_JAR_FILTER = "**.jar";
+ private static final String DEFAULT_AAR_FILTER = "**.aar";
+ private static final String DEFAULT_WAR_FILTER = "**.war";
+ private static final String DEFAULT_EAR_FILTER = "**.ear";
+ private static final String DEFAULT_ZIP_FILTER = "**.zip";
+
+
+ private final JTextField filterTextField = new JTextField(40);
+ private final JTextField apkFilterTextField = new JTextField(40);
+ private final JTextField jarFilterTextField = new JTextField(40);
+ private final JTextField aarFilterTextField = new JTextField(40);
+ private final JTextField warFilterTextField = new JTextField(40);
+ private final JTextField earFilterTextField = new JTextField(40);
+ private final JTextField zipFilterTextField = new JTextField(40);
+
+ private int returnValue;
+
+
+ public FilterDialog(JFrame owner,
+ String explanation)
+ {
+ super(owner, true);
+ setResizable(true);
+
+ // Create some constraints that can be reused.
+ GridBagConstraints textConstraints = new GridBagConstraints();
+ textConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ textConstraints.fill = GridBagConstraints.HORIZONTAL;
+ textConstraints.weightx = 1.0;
+ textConstraints.weighty = 1.0;
+ textConstraints.anchor = GridBagConstraints.NORTHWEST;
+ textConstraints.insets = new Insets(10, 10, 10, 10);
+
+ GridBagConstraints labelConstraints = new GridBagConstraints();
+ labelConstraints.anchor = GridBagConstraints.WEST;
+ labelConstraints.insets = new Insets(1, 2, 1, 2);
+
+ GridBagConstraints textFieldConstraints = new GridBagConstraints();
+ textFieldConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ textFieldConstraints.fill = GridBagConstraints.HORIZONTAL;
+ textFieldConstraints.weightx = 1.0;
+ textFieldConstraints.anchor = GridBagConstraints.WEST;
+ textFieldConstraints.insets = labelConstraints.insets;
+
+ GridBagConstraints panelConstraints = new GridBagConstraints();
+ panelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ panelConstraints.fill = GridBagConstraints.HORIZONTAL;
+ panelConstraints.weightx = 1.0;
+ panelConstraints.weighty = 0.0;
+ panelConstraints.anchor = GridBagConstraints.NORTHWEST;
+ panelConstraints.insets = labelConstraints.insets;
+
+ GridBagConstraints okButtonConstraints = new GridBagConstraints();
+ okButtonConstraints.weightx = 1.0;
+ okButtonConstraints.weighty = 1.0;
+ okButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ okButtonConstraints.insets = new Insets(4, 4, 8, 4);
+
+ GridBagConstraints cancelButtonConstraints = new GridBagConstraints();
+ cancelButtonConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ cancelButtonConstraints.weighty = 1.0;
+ cancelButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ cancelButtonConstraints.insets = okButtonConstraints.insets;
+
+ GridBagLayout layout = new GridBagLayout();
+
+ Border etchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
+
+ // Create the panel with the explanation.
+ JTextArea explanationTextArea = new JTextArea(explanation, 3, 0);
+ explanationTextArea.setOpaque(false);
+ explanationTextArea.setEditable(false);
+ explanationTextArea.setLineWrap(true);
+ explanationTextArea.setWrapStyleWord(true);
+
+ // Create the filter labels.
+ JLabel filterLabel = new JLabel(msg("nameFilter"));
+ JLabel apkFilterLabel = new JLabel(msg("apkNameFilter"));
+ JLabel jarFilterLabel = new JLabel(msg("jarNameFilter"));
+ JLabel aarFilterLabel = new JLabel(msg("aarNameFilter"));
+ JLabel warFilterLabel = new JLabel(msg("warNameFilter"));
+ JLabel earFilterLabel = new JLabel(msg("earNameFilter"));
+ JLabel zipFilterLabel = new JLabel(msg("zipNameFilter"));
+
+ // Create the filter panel.
+ JPanel filterPanel = new JPanel(layout);
+ filterPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("filters")));
+
+ filterPanel.add(explanationTextArea, textConstraints);
+
+ filterPanel.add(tip(filterLabel, "nameFilterTip"), labelConstraints);
+ filterPanel.add(tip(filterTextField, "fileNameFilterTip"), textFieldConstraints);
+
+ filterPanel.add(tip(apkFilterLabel, "apkNameFilterTip"), labelConstraints);
+ filterPanel.add(tip(apkFilterTextField, "fileNameFilterTip"), textFieldConstraints);
+
+ filterPanel.add(tip(jarFilterLabel, "jarNameFilterTip"), labelConstraints);
+ filterPanel.add(tip(jarFilterTextField, "fileNameFilterTip"), textFieldConstraints);
+
+ filterPanel.add(tip(aarFilterLabel, "aarNameFilterTip"), labelConstraints);
+ filterPanel.add(tip(aarFilterTextField, "fileNameFilterTip"), textFieldConstraints);
+
+ filterPanel.add(tip(warFilterLabel, "warNameFilterTip"), labelConstraints);
+ filterPanel.add(tip(warFilterTextField, "fileNameFilterTip"), textFieldConstraints);
+
+ filterPanel.add(tip(earFilterLabel, "earNameFilterTip"), labelConstraints);
+ filterPanel.add(tip(earFilterTextField, "fileNameFilterTip"), textFieldConstraints);
+
+ filterPanel.add(tip(zipFilterLabel, "zipNameFilterTip"), labelConstraints);
+ filterPanel.add(tip(zipFilterTextField, "fileNameFilterTip"), textFieldConstraints);
+
+
+ JButton okButton = new JButton(msg("ok"));
+ okButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ returnValue = APPROVE_OPTION;
+ hide();
+ }
+ });
+
+ JButton cancelButton = new JButton(msg("cancel"));
+ cancelButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ hide();
+ }
+ });
+
+ // Add all panels to the main panel.
+ JPanel mainPanel = new JPanel(layout);
+ mainPanel.add(filterPanel, panelConstraints);
+ mainPanel.add(okButton, okButtonConstraints);
+ mainPanel.add(cancelButton, cancelButtonConstraints);
+
+ getContentPane().add(mainPanel);
+ }
+
+
+ /**
+ * Sets the filter to be represented in this dialog.
+ */
+ public void setFilter(List filter)
+ {
+ filterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_FILTER);
+ }
+
+
+ /**
+ * Returns the filter currently represented in this dialog.
+ */
+ public List getFilter()
+ {
+ String filter = filterTextField.getText();
+
+ return filter.equals(DEFAULT_FILTER) ? null : ListUtil.commaSeparatedList(filter);
+ }
+
+
+ /**
+ * Sets the apk filter to be represented in this dialog.
+ */
+ public void setApkFilter(List filter)
+ {
+ apkFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_APK_FILTER);
+ }
+
+
+ /**
+ * Returns the apk filter currently represented in this dialog.
+ */
+ public List getApkFilter()
+ {
+ String filter = apkFilterTextField.getText();
+
+ return filter.equals(DEFAULT_APK_FILTER) ? null : ListUtil.commaSeparatedList(filter);
+ }
+
+
+ /**
+ * Sets the jar filter to be represented in this dialog.
+ */
+ public void setJarFilter(List filter)
+ {
+ jarFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_JAR_FILTER);
+ }
+
+
+ /**
+ * Returns the jar filter currently represented in this dialog.
+ */
+ public List getJarFilter()
+ {
+ String filter = jarFilterTextField.getText();
+
+ return filter.equals(DEFAULT_JAR_FILTER) ? null : ListUtil.commaSeparatedList(filter);
+ }
+
+
+ /**
+ * Sets the aar filter to be represented in this dialog.
+ */
+ public void setAarFilter(List filter)
+ {
+ aarFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_AAR_FILTER);
+ }
+
+
+ /**
+ * Returns the aar filter currently represented in this dialog.
+ */
+ public List getAarFilter()
+ {
+ String filter = aarFilterTextField.getText();
+
+ return filter.equals(DEFAULT_AAR_FILTER) ? null : ListUtil.commaSeparatedList(filter);
+ }
+
+
+ /**
+ * Sets the war filter to be represented in this dialog.
+ */
+ public void setWarFilter(List filter)
+ {
+ warFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_WAR_FILTER);
+ }
+
+
+ /**
+ * Returns the war filter currently represented in this dialog.
+ */
+ public List getWarFilter()
+ {
+ String filter = warFilterTextField.getText();
+
+ return filter.equals(DEFAULT_WAR_FILTER) ? null : ListUtil.commaSeparatedList(filter);
+ }
+
+
+ /**
+ * Sets the ear filter to be represented in this dialog.
+ */
+ public void setEarFilter(List filter)
+ {
+ earFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_EAR_FILTER);
+ }
+
+
+ /**
+ * Returns the ear filter currently represented in this dialog.
+ */
+ public List getEarFilter()
+ {
+ String filter = earFilterTextField.getText();
+
+ return filter.equals(DEFAULT_EAR_FILTER) ? null : ListUtil.commaSeparatedList(filter);
+ }
+
+
+ /**
+ * Sets the zip filter to be represented in this dialog.
+ */
+ public void setZipFilter(List filter)
+ {
+ zipFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_ZIP_FILTER);
+ }
+
+
+ /**
+ * Returns the zip filter currently represented in this dialog.
+ */
+ public List getZipFilter()
+ {
+ String filter = zipFilterTextField.getText();
+
+ return filter.equals(DEFAULT_ZIP_FILTER) ? null : ListUtil.commaSeparatedList(filter);
+ }
+
+
+ /**
+ * Shows this dialog. This method only returns when the dialog is closed.
+ *
+ * @return <code>CANCEL_OPTION</code> or <code>APPROVE_OPTION</code>,
+ * depending on the choice of the user.
+ */
+ public int showDialog()
+ {
+ returnValue = CANCEL_OPTION;
+
+ // Open the dialog in the right place, then wait for it to be closed,
+ // one way or another.
+ pack();
+ setLocationRelativeTo(getOwner());
+ show();
+
+ return returnValue;
+ }
+
+
+ /**
+ * Attaches the tool tip from the GUI resources that corresponds to the
+ * given key, to the given component.
+ */
+ private static JComponent tip(JComponent component, String messageKey)
+ {
+ component.setToolTipText(msg(messageKey));
+
+ return component;
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private static String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/GUIResources.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/GUIResources.java
new file mode 100644
index 0000000000..bc3deddd09
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/GUIResources.java
@@ -0,0 +1,56 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+
+/**
+ * This class provides some utility methods for working with resource bundles.
+ *
+ * @author Eric Lafortune
+ */
+class GUIResources
+{
+ private static final ResourceBundle messages = ResourceBundle.getBundle(GUIResources.class.getName());
+ private static final MessageFormat formatter = new MessageFormat("");
+
+
+ /**
+ * Returns an internationalized message, based on its key.
+ */
+ public static String getMessage(String messageKey)
+ {
+ return messages.getString(messageKey);
+ }
+
+
+ /**
+ * Returns an internationalized, formatted message, based on its key, with
+ * the given arguments.
+ */
+ public static String getMessage(String messageKey, Object[] messageArguments)
+ {
+ formatter.applyPattern(messages.getString(messageKey));
+ return formatter.format(messageArguments);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/GUIResources.properties b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/GUIResources.properties
new file mode 100644
index 0000000000..3ff9149ef5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/GUIResources.properties
@@ -0,0 +1,659 @@
+# ProGuard -- shrinking, optimization, and obfuscation of Java class files.
+# Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+
+#
+# Tab names.
+#
+proGuardTab = ProGuard
+inputOutputTab = Input/Output
+shrinkingTab = Shrinking
+obfuscationTab = Obfuscation
+optimizationTab = Optimization
+informationTab = Information
+processTab = Process
+reTraceTab = ReTrace
+
+#
+# Splash text.
+#
+developed = Developed by Eric Lafortune
+shrinking = Shrinking
+optimization = Optimization
+obfuscation = Obfuscation
+preverification = Preverification
+
+#
+# Panel titles.
+#
+welcome = Welcome to ProGuard, version 5.3.3
+options = Options
+keepAdditional = Keep additional classes and class members
+keepNamesAdditional = Keep additional class names and class member names
+assumeNoSideEffectsAdditional = Assume no side effects for additional methods
+whyAreYouKeeping = Why are you keeping
+preverificationAndTargeting = Preverification and targeting
+consistencyAndCorrectness = Consistency and correctness
+processingConsole = Processing console
+reTraceSettings = ReTrace settings
+deobfuscatedStackTrace = De-obfuscated stack trace
+
+keepAdditionalTip = \
+ If required, keep additional classes, fields, and methods as entry points.
+keepNamesAdditionalTip = \
+ If required, keep the names of additional classes, fields, and methods.
+assumeNoSideEffectsAdditionalTip = \
+ <html>Optionally specify additional methods that don't have any side effects.<br>\
+ <i>Only add entries if you know what you're doing!</i></html>
+whyAreYouKeepingTip = \
+ Ask ProGuard why it is keeping certain classes, fields, or methods.
+
+#
+# Info texts.
+#
+proGuardInfo = \
+ <html>ProGuard is a free class file shrinker, optimizer, obfuscator, and preverifier.\
+ <p>\
+ With this GUI, you can create, load, modify, and save ProGuard configurations.\
+ <br>\
+ You can then process your code right away, or you can run ProGuard from the \
+ command line using your saved configuration.\
+ <p>\
+ With the ReTrace part of this GUI you can de-obfuscate your stack traces.\
+ <p>\
+ ProGuard and ReTrace are written and maintained by Eric Lafortune.\
+ <p>\
+ Official site at Sourceforge: \
+ <a href="http://proguard.sourceforge.net/\">http://proguard.sourceforge.net/</a>\
+ <br>\
+ Professional support by GuardSquare: \
+ <a href="http://www.guardsquare.com/\">http://www.guardsquare.com/</a>\
+ <p>\
+ Distributed under the GNU General Public License.\
+ <br>\
+ Copyright &copy; 2002-2017.</html>
+
+processingInfo = \
+ You can now start processing your code, \
+ or you can run ProGuard from the command line using your saved configuration.
+
+reTraceInfo = \
+ If you had ProGuard write out a mapping file, \
+ you can de-obfuscate your obfuscated stack traces with ReTrace!\
+ \n\n\
+ You can load an obfuscated stack trace from a file, \
+ or you can paste it straight into the text area above.
+
+#
+# Titles and labels corresponding to common ProGuard options.
+#
+programJars = Program jars, aars, wars, ears, zips, apks, and directories
+libraryJars = Library jars, aars, wars, ears, zips, apks, and directories
+
+shrink = Shrink
+printUsage = Print usage
+
+optimize = Optimize
+allowAccessModification = Allow access modification
+mergeInterfacesAggressively = Merge interfaces aggressively
+optimizations = Optimizations
+optimizationPasses = Optimization passes
+
+obfuscate = Obfuscate
+printMapping = Print mapping
+applyMapping = Apply mapping
+obfuscationDictionary = Obfuscation dictionary
+classObfuscationDictionary = Class obfuscation dictionary
+packageObfuscationDictionary = Package obfuscation dictionary
+overloadAggressively = Overload aggressively
+useUniqueClassMemberNames = Use unique class member names
+keepPackageNames = Keep package names
+flattenPackageHierarchy = Flatten package hierarchy
+repackageClasses = Repackage classes
+useMixedCaseClassNames = Use mixed-case class names
+keepAttributes = Keep attributes
+keepParameterNames = Keep parameter names
+renameSourceFileAttribute = Rename SourceFile attribute
+adaptClassStrings = Adapt class strings
+adaptResourceFileNames = Adapt resource file names
+adaptResourceFileContents = Adapt resource file contents
+
+preverify = Preverify
+microEdition = Micro Edition
+
+verbose = Verbose
+note = Note potential mistakes in the configuration
+warn = Warn about possibly erroneous input
+ignoreWarnings = Ignore warnings about possibly erroneous input
+skipNonPublicLibraryClasses = Skip non-public library classes
+skipNonPublicLibraryClassMembers = Skip non-public library class members
+keepDirectories = Keep directories
+forceProcessing = Force processing
+target = Target
+targets = 1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8
+printSeeds = Print seeds
+printConfiguration = Print configuration
+dump = Print class files
+
+mappingFile = Mapping file
+obfuscatedStackTrace = Obfuscated stack trace
+
+programJarsTip = \
+ <html>The input jars (aars, wars, ears, zips, apks, directories), followed by<br>\
+ their corresponding output jars (wars, ears, zips, apks, directories).</html>
+libraryJarsTip = \
+ <html>The library jars (aars, wars, ears, zips, directories), on which the program jars depend.<br>\
+ The library jars are required for processing, but they are not copied to the output.</html>
+
+shrinkTip = \
+ Remove unused classes, fields, and methods from the output.
+printUsageTip = \
+ Print out the list of unused classes, fields, and methods.
+
+optimizeTip = \
+ Optimize the bytecode of the processed classes.
+allowAccessModificationTip = \
+ Allow the optimization step to modify the access modifiers of classes, fields, and methods.
+mergeInterfacesAggressivelyTip = \
+ <html>Allow interfaces to be merged, even if their implementations don't implement all<br>\
+ interface methods. This is not allowed in the Java language, but it is allowed in bytecode.</html>
+optimizationsTip = \
+ Specify the types of optimizations to be performed.
+optimizationsFilterTip = \
+ A filter for the names of the optimizations to be performed.
+optimizationsSelectTip = \
+ Select from the currently available optimizations...
+optimizationPassesTip = \
+ Specify the number of optimization passes to be performed.
+
+obfuscateTip = \
+ Obfuscate the names of the processed classes, fields, and methods.
+printMappingTip = \
+ Print out the obfuscation mapping of original names to obfuscated names.
+applyMappingTip = \
+ Apply the given mapping of original names to obfuscated names.
+obfuscationDictionaryTip = \
+ Use the words in the given file for obfuscating field names and method names.
+classObfuscationDictionaryTip = \
+ Use the words in the given file for obfuscating class names.
+packageObfuscationDictionaryTip = \
+ Use the words in the given file for obfuscating package names.
+overloadAggressivelyTip = \
+ <html>Allow fields and methods to get the same obfuscated names, even if only their types or<br>\
+ return types differ. This is not allowed in the Java language, but it is allowed in bytecode.</html>
+useUniqueClassMemberNamesTip = \
+ <html>Make sure fields and methods get the same obfuscation mapping across classes, even<br>\
+ if they are unrelated. This is advisable if the output is to be obfuscated incrementally.</html>
+keepPackageNamesTip = \
+ Keep the specified package names from being obfuscated.
+packageNamesTip = \
+ <html>An optional comma-separated list of package names,<br>\
+ e.g. <code>myapplication,mylibrary.**</code><br>\
+ Possible wildcards:\
+ <ul>\
+ <li><code>?</code> for any single character, except the package separator.\
+ <li><code>*</code> for any number of any characters, except the package separator.\
+ <li><code>**</code> for any number of any characters.\
+ </ul>\
+ The negator <code>!</code> is also supported.</html>
+flattenPackageHierarchyTip = \
+ Move all packages that are renamed into the given parent package.
+repackageClassesTip = \
+ Move all classes that are renamed into the given package.
+packageTip = \
+ The optional package name.
+useMixedCaseClassNamesTip = \
+ <html>Generate mixed-case obfucated class names. This will complicate unpacking<br>\
+ the resulting jars on case-insensitive file systems, should that be necessary.</html>
+keepAttributesTip = \
+ Keep the specified optional class file attributes.
+attributesTip = \
+ <html>An optional comma-separated list of class file attributes.\
+ <ul>\
+ <li>"Exceptions,Innerclasses, Signature" are necessary if the output is to be used as a library.\
+ <li>"Deprecated" is optional if the output is to be used as a library.\
+ <li>"LocalVariable*Table" can be useful for debugging.\
+ <li>"Sourcefile,LineNumberTable" are necessary for generating stack traces.\
+ <li>"*Annotations*" is necessary for preserving annotations.\
+ </ul>\
+ The wildcard <code>*</code> and the negator <code>!</code> are allowed.</html>
+keepParameterNamesTip = \
+ <html>Keep parameter names and types in "LocalVariable*Table" attributes<br>\
+ in methods that are not obfuscated.</html>
+renameSourceFileAttributeTip = \
+ <html>Put the given string in the "SourceFile" attribute of the processed class files.<br>\
+ It will appear as the file name of the classes in stack traces.</html>
+sourceFileAttributeTip = \
+ The replacement "SourceFile" string.
+adaptClassStringsTip = \
+ <html>Adapt string constants in the specified classes, based<br>\
+ on the obfuscated names of corresponding classes.</html>
+adaptResourceFileNamesTip = \
+ <html>Rename the specified resource files, based on the<br>\
+ obfuscated names of the corresponding class files.</html>
+adaptResourceFileContentsTip = \
+ <html>Adapt the contents of the specified resource files, based<br>\
+ on the obfuscated names of the processed classes.</html>
+fileNameFilterTip = \
+ <html>A filter on file names,<br>\
+ e.g. <code>mydirectory1/**,mydirectory2/**</code><br>\
+ Possible wildcards:\
+ <ul>\
+ <li><code>?</code> for any single character, except the directory separator.\
+ <li><code>*</code> for any number of any characters, except the directory separator.\
+ <li><code>**</code> for any number of any characters.\
+ </ul>\
+ The negator <code>!</code> is also supported.</html>
+
+preverifyTip = \
+ Preverify the processed classes, for Java Micro Edition or for Java 6.
+microEditionTip = \
+ Target Java Micro Edition.
+
+verboseTip = \
+ Print out verbose messages while processing.
+noteTip = \
+ Print out notes about special or unusual input.
+noteFilterTip = \
+ A filter matching classes for which no notes should be printed.
+warnTip = \
+ <html>Print out warnings about possibly erroneous input.<br>\
+ <i>Only unset this option if you know what you're doing!</i></html>
+warnFilterTip = \
+ A filter matching classes for which no warnings should be printed.
+ignoreWarningsTip = \
+ <html>Ignore any warnings about possibly erroneous input.<br>\
+ <i>Only set this option if you know what you're doing!</i></html>
+skipNonPublicLibraryClassesTip = \
+ <html>Skip reading non-public library classes, for efficiency.<br>\
+ You may have to unset this option if ProGuard complains about missing classes.</html>
+skipNonPublicLibraryClassMembersTip = \
+ <html>Skip reading non-public library fields and methods, for efficiency.<br>\
+ You may have to unset this option if ProGuard complains about missing class members.</html>
+keepDirectoriesTip = \
+ Keep the specified directories in the output jars, wars, ears, zips, apks, or directories.
+directoriesTip = \
+ <html>A filter on directory names,<br>\
+ e.g. <code>mydirectory1,mydirectory2/**</code><br>\
+ Possible wildcards:\
+ <ul>\
+ <li><code>?</code> for any single character, except the directory separator.\
+ <li><code>*</code> for any number of any characters, except the directory separator.\
+ <li><code>**</code> for any number of any characters.\
+ </ul>\
+ The negator <code>!</code> is also supported.</html>
+forceProcessingTip = \
+ Always process the input, even if the output seems up to date.
+targetTip = \
+ Target the specified version of Java.
+printSeedsTip = \
+ Print out the list of kept classes, fields, and methods.
+printConfigurationTip = \
+ Print out the configuration.
+dumpTip = \
+ Print out the internal structure of the processed class files.
+
+mappingFileTip = \
+ The file containing the mapping of original names to obfuscated names.
+obfuscatedStackTraceTip = \
+ A stack trace produced by previously obfuscated code.
+
+#
+# Titles and labels corresponding to ProGuard keep options.
+#
+keepTitle = Keep
+
+keep = Keep classes and class members
+keepClassMembers = Keep class members only
+keepClassesWithMembers = Keep classes and class members, if members are present
+
+alsoKeepTitle = Also keep
+
+keepDescriptorClasses = Keep descriptor classes
+
+allowTitle = Allow
+
+allowShrinking = Allow shrinking
+allowOptimization = Allow optimization
+allowObfuscation = Allow obfuscation
+
+keepTitleTip = Keep the specified classes and/or their fields and methods.
+
+keepTip = \
+ <html>Keep the specified classes, fields, and methods as entry points.<br>\
+ This is the most common option.</html>
+keepClassMembersTip = \
+ Only keep the specified fields and methods as entry points.
+keepClassesWithMembersTip = \
+ <html>Keep the specified classes, fields, and methods,<br>\
+ on the condition that the fields and methods are present.</html>
+
+alsoKeepTitleTip = \
+ <html>Optionally keeping more classes.<br>\
+ <i>These are advanced options.</i></html>
+
+keepDescriptorClassesTip = \
+ <html>Automatically keep the classes in the descriptors of matching<br>\
+ fields and methods. Mostly useful for keeping their names.</html>
+
+allowTitleTip = \
+ <html>Optionally relax keeping the specified classes, fields, and methods.<br>\
+ <i>These are advanced options.</i></html>
+
+allowShrinkingTip = \
+ Remove the specified classes, fields, and methods anyway, if they are not used.
+allowOptimizationTip = \
+ <html>Optimize the specified classes, fields, and methods as entry points anyway.<br>\
+ <i>Only set this option if you know what you're doing!</i></html>
+allowObfuscationTip = \
+ <html>Obfuscate the names of the specified classes, fields, and methods anyway.<br>\
+ <i>Only set this option if you know what you're doing!</i></html>
+
+#
+# Further keep titles and labels.
+#
+specifyClasses = Specify classes and class members...
+specifyFields = Specify fields...
+specifyMethods = Specify methods...
+
+comments = Comments
+access = Access
+required = Required
+not = Not
+dontCare = Don't care
+annotation = Annotation
+class = Class
+extendsImplementsAnnotation = Extends/implements class with annotation
+extendsImplementsClass = Extends/implements class
+classMembers = Class members
+
+extensionsOf = Extensions of
+specificationNumber = Specification #
+
+fieldType = Field type
+returnType = Return type
+name = Name
+argumentTypes = Argument types
+
+commentsTip = \
+ Optionally add a comment for this option in the configuration file.
+accessTip = \
+ <html>Optionally place constraints on the access modifiers of this element.<br>\
+ E.g. only match public elements.</html>
+requiredTip = \
+ The access modifier has to be set.
+notTip = \
+ The access modifier must not be set.
+dontCareTip = \
+ The access modifier is irrelevant.
+annotationTip = \
+ <html>Optionally require the given annotation to be present on this element.<br>\
+ E.g. only match elements that have an annotation <code>myPackage.MyAnnotation</code>.<br>\
+ <i>This is an advanced option.</i></html>
+classTip = \
+ The name of the class or interface.
+extendsImplementsAnnotationTip = \
+ <html>Optionally require the given annotation to be present on the<br>\
+ extended or implemented class or interface.<br>\
+ E.g. only match classes that extend a class that has an annotation<br>\
+ <code>myPackage.MyAnnotation</code>.<br>\
+ <i>This is an advanced option.</i></html>
+extendsImplementsClassTip = \
+ <html>Optionally require the class to implement or extend the given class or interface.<br>\
+ E.g. only match classes that implement an interface <code>myPackage.MyInterface</code>.</html>
+classMembersTip = \
+ <html>Optionally keep fields and methods as entry points in the matching class or classes.<br>\
+ E.g. keep all public '<code>get*</code>' methods as entry points.</html>
+
+fieldTypeTip = The field type.
+returnTypeTip = The method return type, if any.
+nameTip = The name.
+argumentTypesTip = The method argument types, if any.
+
+classNameTip = \
+ <html>The class name, e.g. <code>myPackage.MyClass</code><br>\
+ Possible wildcards:\
+ <ul>\
+ <li><code>?</code> for any single character, except the package separator.\
+ <li><code>*</code> for any number of any characters, except the package separator.\
+ <li><code>**</code> for any number of any characters.\
+ </ul></html>
+classNamesTip = \
+ <html>A regular expression to further constrain the class names,<br>\
+ e.g. <code>myPackage1.MyClass,myPackage2.**</code><br>\
+ Possible wildcards:\
+ <ul>\
+ <li><code>?</code> for any single character, except the package separator.\
+ <li><code>*</code> for any number of any characters, except the package separator.\
+ <li><code>**</code> for any number of any characters.\
+ </ul>\
+ The negator <code>!</code> is also supported.</html>
+typeTip = \
+ <html>The type, e.g. <code>int</code>, or <code>java.lang.String[]</code><br>\
+ Possible wildcards:\
+ <ul>\
+ <li><code>%</code> for any primitive type.\
+ <li><code>?</code> for any single character, except the package separator.\
+ <li><code>*</code> for any number of any characters, except the package separator.\
+ <li><code>**</code> for any number of any characters.\
+ <li><code>***</code> (or empty) for any type.\
+ </ul></html>
+fieldNameTip = \
+ <html>The field name, e.g. <code>myField</code><br>\
+ Possible wildcards:\
+ <ul>\
+ <li><code>?</code> for any single character.\
+ <li><code>*</code> for any number of any characters.\
+ </ul></html>
+methodNameTip = \
+ <html>The method name, e.g. <code>myMethod</code><br>\
+ Possible wildcards:\
+ <ul>\
+ <li><code>?</code> for any single character.\
+ <li><code>*</code> for any number of any characters.\
+ </ul></html>
+argumentTypes2Tip = \
+ <html>The comma-separated list of argument types,<br>\
+ e.g. <code>java.lang.String[],int,boolean</code><br>\
+ Possible wildcards:\
+ <ul>\
+ <li><code>%</code> for any primitive type.\
+ <li><code>?</code> for any single character, except the package separator.\
+ <li><code>*</code> for any number of any characters, except the package separator.\
+ <li><code>**</code> for any number of any characters.\
+ <li><code>***</code> for any type.\
+ <li><code>...</code> for any number of any arguments.\
+ </ul></html>
+
+#
+# Titles and labels corresponding to optimization options.
+#
+selectOptimizations = Select optimizations...
+
+field = Field
+method = Method
+code = Code
+
+class_marking_finalTip = \
+ Mark classes as final, whenever possible.
+class_merging_verticalTip = \
+ Merge classes vertically in the class hierarchy, whenever possible.
+class_merging_horizontalTip = \
+ Merge classes horizontally in the class hierarchy, whenever possible.
+field_removal_writeonlyTip = \
+ Remove write-only fields.
+field_marking_privateTip = \
+ Mark fields as private, whenever possible.
+field_propagation_valueTip = \
+ Propagate the values of fields across methods.
+method_marking_privateTip = \
+ Mark methods as private, whenever possible (devirtualization).
+method_marking_staticTip = \
+ Mark methods as static, whenever possible (devirtualization).
+method_marking_finalTip = \
+ Mark methods as final, whenever possible.
+method_removal_parameterTip = \
+ Remove unused method parameters.
+method_propagation_parameterTip = \
+ Propagate the values of method parameters from method invocations to \
+ the invoked methods.
+method_propagation_returnvalueTip = \
+ Propagate the values of method return values from methods to their \
+ invocations.
+method_inlining_shortTip = \
+ Inline short methods.
+method_inlining_uniqueTip = \
+ Inline methods that are only called once.
+method_inlining_tailrecursionTip = \
+ Simplify tail recursion calls, whenever possible.
+code_mergingTip = \
+ Merge identical blocks of code by modifying branch targets.
+code_simplification_variableTip = \
+ Perform peephole optimizations for variable loading and storing.
+code_simplification_arithmeticTip = \
+ Perform peephole optimizations for arithmetic instructions.
+code_simplification_castTip = \
+ Perform peephole optimizations for casting operations.
+code_simplification_fieldTip = \
+ Perform peephole optimizations for field loading and storing.
+code_simplification_branchTip = \
+ Perform peephole optimizations for branch instructions.
+code_simplification_stringTip = \
+ Perform peephole optimizations for constant strings.
+code_simplification_advancedTip = \
+ Simplify code based on control flow analysis and data flow analysis.
+code_removal_advancedTip = \
+ Remove dead code based on control flow analysis and data flow analysis.
+code_removal_simpleTip = \
+ Remove dead code based on a simple control flow analysis.
+code_removal_variableTip = \
+ Remove unused variables from the local variable frame.
+code_removal_exceptionTip = \
+ Remove exceptions with empty try blocks.
+code_allocation_variableTip = \
+ Optimize variable allocation on the local variable frame.
+
+
+#
+# File selection titles.
+#
+selectConfigurationFile = Select a configuration file...
+saveConfigurationFile = Save configuration...
+selectUsageFile = Select a usage output file...
+selectPrintMappingFile = Select an output mapping file...
+selectApplyMappingFile = Select an input mapping file...
+selectObfuscationDictionaryFile = Select an obfuscation dictionary...
+selectSeedsFile = Select a seeds output file...
+selectDumpFile = Select a class dump file...
+selectStackTraceFile = Select a stack trace file...
+
+cantOpenConfigurationFile = Can''t open the configuration file [{0}]
+cantParseConfigurationFile = Can''t parse the configuration file [{0}]
+cantSaveConfigurationFile = Can''t save the configuration file [{0}]
+cantOpenStackTraceFile = Can''t open the stack trace file [{0}]
+
+jarExtensions = *.jar, *.aar, *.war, *.ear, *.zip, *.apk, *.ap_ (archives and directories)
+proExtension = *.pro (ProGuard configurations)
+
+addJars = Add one or more jars or directories...
+chooseJars = Choose different jars or directories...
+enterFilter = Optionally filter the file names contained in the selected entries.
+
+filters = Filters
+nameFilter = File name filter
+apkNameFilter = Apk name filter
+jarNameFilter = Jar name filter
+aarNameFilter = Aar name filter
+warNameFilter = War name filter
+earNameFilter = Ear name filter
+zipNameFilter = Zip name filter
+
+outputFileTip = The optional output file.
+inputFileTip = The input file.
+
+nameFilterTip = A filter on plain class file names and resource file names.
+apkNameFilterTip = A filter on apk file names.
+jarNameFilterTip = A filter on jar file names.
+aarNameFilterTip = A filter on aar file names.
+warNameFilterTip = A filter on war file names.
+earNameFilterTip = A filter on ear file names.
+zipNameFilterTip = A filter on zip file names.
+
+#
+# Simple button texts.
+#
+previous = Previous
+next = Next
+browse = Browse...
+advanced = Advanced options
+basic = Basic options
+selectAll = Select all
+selectNone = Select none
+ok = Ok
+cancel = Cancel
+
+add = Add...
+addInput = Add input...
+addOutput = Add output...
+edit = Edit...
+filter = Filter...
+remove = Remove
+moveUp = Move up
+moveDown = Move down
+
+moveToLibraries = Move to libraries
+moveToProgram = Move to program
+
+addField = Add field...
+addMethod = Add method...
+
+select = Select...
+
+loadConfiguration = Load configuration...
+viewConfiguration = View configuration
+saveConfiguration = Save configuration...
+loadStackTrace = Load stack trace...
+process = Process!
+reTrace = ReTrace!
+
+advancedTip = Toggle between showing basic options and advanced options.
+
+addInputTip = Add an input jar, aar, war, ear, zip, apk, or directory.
+addOutputTip = Add an output jar, aar, war, ear, zip, apk, or directory.
+addTip = Add an entry.
+editTip = Edit the selected entries.
+filterTip = Put filters on the contents of the selected entries.
+removeTip = Remove the selected entries.
+moveUpTip = Move the selected entries up in the list.
+moveDownTip = Move the selected entries down in the list.
+
+moveToLibrariesTip = Move to selected entries to the libraries.
+moveToProgramTip = Move to selected entries to the program.
+
+addFieldTip = Add a field to the specification.
+addMethodTip = Add a method to the specification.
+
+loadConfigurationTip = Optionally load an initial configuration.
+viewConfigurationTip = View the current configuration.
+saveConfigurationTip = Save the current configuration.
+loadStackTraceTip = Load a stack trace from a file.
+processTip = Start processing, based on the current configuration.
+reTraceTip = De-obfuscate the given stack trace.
+
+#
+# Progress messages and error messages.
+#
+warning = Warning
+outOfMemory = Out of memory
+outOfMemoryInfo = \n\
+ You should run the ProGuard GUI with a larger java heap size, \
+ with a command like\
+ \n\n\t\
+ java -Xms128m -Xmx192m -jar proguardgui.jar {0}\
+ \n\n\
+ or you can try running ProGuard from the command line. \
+ with a command like\
+ \n\n\t\
+ java -jar proguard.jar @{0}
+sampleConfigurationFileName = configuration.pro
+errorProcessing = Error during processing
+errorReTracing = Error during retracing
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/KeepSpecificationsPanel.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/KeepSpecificationsPanel.java
new file mode 100644
index 0000000000..4d1c548bfc
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/KeepSpecificationsPanel.java
@@ -0,0 +1,85 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import proguard.*;
+
+import javax.swing.*;
+
+/**
+ * This <code>ListPanel</code> allows the user to add, edit, move, and remove
+ * KeepClassSpecification entries in a list.
+ *
+ * @author Eric Lafortune
+ */
+final class KeepSpecificationsPanel extends ClassSpecificationsPanel
+{
+ private final boolean markClasses;
+ private final boolean markConditionally;
+ private final boolean markDescriptorClasses;
+ private final boolean allowShrinking;
+ private final boolean allowOptimization;
+ private final boolean allowObfuscation;
+
+
+ public KeepSpecificationsPanel(JFrame owner,
+ boolean markClasses,
+ boolean markConditionally,
+ boolean markDescriptorClasses,
+ boolean allowShrinking,
+ boolean allowOptimization,
+ boolean allowObfuscation)
+ {
+ super(owner, true);
+
+ this.markClasses = markClasses;
+ this.markConditionally = markConditionally;
+ this.markDescriptorClasses = markDescriptorClasses;
+ this.allowShrinking = allowShrinking;
+ this.allowOptimization = allowOptimization;
+ this.allowObfuscation = allowObfuscation;
+ }
+
+
+ // Factory methods for ClassSpecificationsPanel.
+
+ protected ClassSpecification createClassSpecification()
+ {
+ return new KeepClassSpecification(markClasses,
+ markConditionally,
+ markDescriptorClasses,
+ allowShrinking,
+ allowOptimization,
+ allowObfuscation);
+ }
+
+
+ protected void setClassSpecification(ClassSpecification classSpecification)
+ {
+ classSpecificationDialog.setKeepSpecification((KeepClassSpecification)classSpecification);
+ }
+
+
+ protected ClassSpecification getClassSpecification()
+ {
+ return classSpecificationDialog.getKeepSpecification();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ListPanel.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ListPanel.java
new file mode 100644
index 0000000000..97063edb5a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ListPanel.java
@@ -0,0 +1,340 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import javax.swing.*;
+import javax.swing.event.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.util.List;
+
+/**
+ * This <code>Jpanel</code> allows the user to move and remove entries in a
+ * list and between lists. Extensions of this class should add buttons to add
+ * and possibly edit entries, and to set and get the resulting list.
+ *
+ * @author Eric Lafortune
+ */
+abstract class ListPanel extends JPanel
+{
+ protected final DefaultListModel listModel = new DefaultListModel();
+ protected final JList list = new JList(listModel);
+
+ protected int firstSelectionButton = 2;
+
+
+ protected ListPanel()
+ {
+ GridBagLayout layout = new GridBagLayout();
+ setLayout(layout);
+
+ GridBagConstraints listConstraints = new GridBagConstraints();
+ listConstraints.gridheight = GridBagConstraints.REMAINDER;
+ listConstraints.fill = GridBagConstraints.BOTH;
+ listConstraints.weightx = 1.0;
+ listConstraints.weighty = 1.0;
+ listConstraints.anchor = GridBagConstraints.NORTHWEST;
+ listConstraints.insets = new Insets(0, 2, 0, 2);
+
+ // Make sure some buttons are disabled or enabled depending on whether
+ // the selection is empty or not.
+ list.addListSelectionListener(new ListSelectionListener()
+ {
+ public void valueChanged(ListSelectionEvent e)
+ {
+ enableSelectionButtons();
+ }
+ });
+
+ add(new JScrollPane(list), listConstraints);
+
+ // something like the following calls are up to the extending class:
+ //addAddButton();
+ //addEditButton();
+ //addRemoveButton();
+ //addUpButton();
+ //addDownButton();
+ //
+ //enableSelectionButtons();
+ }
+
+
+ protected void addRemoveButton()
+ {
+ JButton removeButton = new JButton(msg("remove"));
+ removeButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ // Remove the selected elements.
+ removeElementsAt(list.getSelectedIndices());
+ }
+ });
+
+ addButton(tip(removeButton, "removeTip"));
+ }
+
+
+ protected void addUpButton()
+ {
+ JButton upButton = new JButton(msg("moveUp"));
+ upButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ int[] selectedIndices = list.getSelectedIndices();
+ if (selectedIndices.length > 0 &&
+ selectedIndices[0] > 0)
+ {
+ // Move the selected elements up.
+ moveElementsAt(selectedIndices, -1);
+ }
+ }
+ });
+
+ addButton(tip(upButton, "moveUpTip"));
+ }
+
+
+ protected void addDownButton()
+ {
+ JButton downButton = new JButton(msg("moveDown"));
+ downButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ int[] selectedIndices = list.getSelectedIndices();
+ if (selectedIndices.length > 0 &&
+ selectedIndices[selectedIndices.length-1] < listModel.getSize()-1)
+ {
+ // Move the selected elements down.
+ moveElementsAt(selectedIndices, 1);
+ }
+ }
+ });
+
+ addButton(tip(downButton, "moveDownTip"));
+ }
+
+
+ /**
+ * Adds a button that allows to copy or move entries to another ListPanel.
+ *
+ * @param buttonTextKey the button text key.
+ * @param tipKey the tool tip key.
+ * @param panel the other ListPanel.
+ */
+ public void addCopyToPanelButton(String buttonTextKey,
+ String tipKey,
+ final ListPanel panel)
+ {
+ JButton moveButton = new JButton(msg(buttonTextKey));
+ moveButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ int[] selectedIndices = list.getSelectedIndices();
+ Object[] selectedElements = list.getSelectedValues();
+
+ // Remove the selected elements from this panel.
+ removeElementsAt(selectedIndices);
+
+ // Add the elements to the other panel.
+ panel.addElements(selectedElements);
+ }
+ });
+
+ addButton(tip(moveButton, tipKey));
+ }
+
+
+ protected void addButton(JComponent button)
+ {
+ GridBagConstraints buttonConstraints = new GridBagConstraints();
+ buttonConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ buttonConstraints.fill = GridBagConstraints.HORIZONTAL;
+ buttonConstraints.anchor = GridBagConstraints.NORTHWEST;
+ buttonConstraints.insets = new Insets(0, 2, 0, 2);
+
+ add(button, buttonConstraints);
+ }
+
+
+ /**
+ * Returns a list of all right-hand side buttons.
+ */
+ public List getButtons()
+ {
+ List list = new ArrayList(getComponentCount()-1);
+
+ // Add all buttons.
+ for (int index = 1; index < getComponentCount(); index++)
+ {
+ list.add(getComponent(index));
+ }
+
+ return list;
+ }
+
+
+ protected void addElement(Object element)
+ {
+ listModel.addElement(element);
+
+ // Make sure it is selected.
+ list.setSelectedIndex(listModel.size() - 1);
+ }
+
+
+ protected void addElements(Object[] elements)
+ {
+ // Add the elements one by one.
+ for (int index = 0; index < elements.length; index++)
+ {
+ listModel.addElement(elements[index]);
+ }
+
+ // Make sure they are selected.
+ int[] selectedIndices = new int[elements.length];
+ for (int index = 0; index < selectedIndices.length; index++)
+ {
+ selectedIndices[index] =
+ listModel.size() - selectedIndices.length + index;
+ }
+ list.setSelectedIndices(selectedIndices);
+ }
+
+
+ protected void moveElementsAt(int[] indices, int offset)
+ {
+ // Remember the selected elements.
+ Object[] selectedElements = list.getSelectedValues();
+
+ // Remove the selected elements.
+ removeElementsAt(indices);
+
+ // Update the element indices.
+ for (int index = 0; index < indices.length; index++)
+ {
+ indices[index] += offset;
+ }
+
+ // Reinsert the selected elements.
+ insertElementsAt(selectedElements, indices);
+ }
+
+
+ protected void insertElementsAt(Object[] elements, int[] indices)
+ {
+ for (int index = 0; index < elements.length; index++)
+ {
+ listModel.insertElementAt(elements[index], indices[index]);
+ }
+
+ // Make sure they are selected.
+ list.setSelectedIndices(indices);
+ }
+
+
+ protected void setElementAt(Object element, int index)
+ {
+ listModel.setElementAt(element, index);
+
+ // Make sure it is selected.
+ list.setSelectedIndex(index);
+ }
+
+
+ protected void setElementsAt(Object[] elements, int[] indices)
+ {
+ for (int index = 0; index < elements.length; index++)
+ {
+ listModel.setElementAt(elements[index], indices[index]);
+ }
+
+ // Make sure they are selected.
+ list.setSelectedIndices(indices);
+ }
+
+
+ protected void removeElementsAt(int[] indices)
+ {
+ for (int index = indices.length - 1; index >= 0; index--)
+ {
+ listModel.removeElementAt(indices[index]);
+ }
+
+ // Make sure nothing is selected.
+ list.clearSelection();
+
+ // Make sure the selection buttons are properly enabled,
+ // since the above method doesn't seem to notify the listener.
+ enableSelectionButtons();
+ }
+
+
+ protected void removeAllElements()
+ {
+ listModel.removeAllElements();
+
+ // Make sure the selection buttons are properly enabled,
+ // since the above method doesn't seem to notify the listener.
+ enableSelectionButtons();
+ }
+
+
+ /**
+ * Enables or disables the buttons that depend on a selection.
+ */
+ protected void enableSelectionButtons()
+ {
+ boolean selected = !list.isSelectionEmpty();
+
+ // Loop over all components, except the list itself and the Add button.
+ for (int index = firstSelectionButton; index < getComponentCount(); index++)
+ {
+ getComponent(index).setEnabled(selected);
+ }
+ }
+
+
+ /**
+ * Attaches the tool tip from the GUI resources that corresponds to the
+ * given key, to the given component.
+ */
+ private static JComponent tip(JComponent component, String messageKey)
+ {
+ component.setToolTipText(msg(messageKey));
+
+ return component;
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private static String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MANIFEST.MF b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MANIFEST.MF
new file mode 100644
index 0000000000..05403b4915
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: proguard.gui.ProGuardGUI
+Class-Path: proguard.jar retrace.jar
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MemberSpecificationDialog.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MemberSpecificationDialog.java
new file mode 100644
index 0000000000..56b7952edb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MemberSpecificationDialog.java
@@ -0,0 +1,509 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import proguard.MemberSpecification;
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+import proguard.util.ListUtil;
+
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.*;
+import java.awt.event.*;
+
+/**
+ * This <code>JDialog</code> allows the user to enter a String.
+ *
+ * @author Eric Lafortune
+ */
+final class MemberSpecificationDialog extends JDialog
+{
+ /**
+ * Return value if the dialog is canceled (with the Cancel button or by
+ * closing the dialog window).
+ */
+ public static final int CANCEL_OPTION = 1;
+
+ /**
+ * Return value if the dialog is approved (with the Ok button).
+ */
+ public static final int APPROVE_OPTION = 0;
+
+
+ private final boolean isField;
+
+ private final JRadioButton[] publicRadioButtons;
+ private final JRadioButton[] privateRadioButtons;
+ private final JRadioButton[] protectedRadioButtons;
+ private final JRadioButton[] staticRadioButtons;
+ private final JRadioButton[] finalRadioButtons;
+ private final JRadioButton[] syntheticRadioButtons;
+
+ private JRadioButton[] volatileRadioButtons;
+ private JRadioButton[] transientRadioButtons;
+
+ private JRadioButton[] synchronizedRadioButtons;
+ private JRadioButton[] nativeRadioButtons;
+ private JRadioButton[] abstractRadioButtons;
+ private JRadioButton[] strictRadioButtons;
+ private JRadioButton[] bridgeRadioButtons;
+ private JRadioButton[] varargsRadioButtons;
+
+ private final JTextField annotationTypeTextField = new JTextField(20);
+ private final JTextField nameTextField = new JTextField(20);
+ private final JTextField typeTextField = new JTextField(20);
+ private final JTextField argumentTypesTextField = new JTextField(20);
+
+ private int returnValue;
+
+
+ public MemberSpecificationDialog(JDialog owner, boolean isField)
+ {
+ super(owner, msg(isField ? "specifyFields" : "specifyMethods"), true);
+ setResizable(true);
+
+ // Create some constraints that can be reused.
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.anchor = GridBagConstraints.WEST;
+ constraints.insets = new Insets(1, 2, 1, 2);
+
+ GridBagConstraints constraintsStretch = new GridBagConstraints();
+ constraintsStretch.fill = GridBagConstraints.HORIZONTAL;
+ constraintsStretch.weightx = 1.0;
+ constraintsStretch.anchor = GridBagConstraints.WEST;
+ constraintsStretch.insets = constraints.insets;
+
+ GridBagConstraints constraintsLast = new GridBagConstraints();
+ constraintsLast.gridwidth = GridBagConstraints.REMAINDER;
+ constraintsLast.anchor = GridBagConstraints.WEST;
+ constraintsLast.insets = constraints.insets;
+
+ GridBagConstraints constraintsLastStretch = new GridBagConstraints();
+ constraintsLastStretch.gridwidth = GridBagConstraints.REMAINDER;
+ constraintsLastStretch.fill = GridBagConstraints.HORIZONTAL;
+ constraintsLastStretch.weightx = 1.0;
+ constraintsLastStretch.anchor = GridBagConstraints.WEST;
+ constraintsLastStretch.insets = constraints.insets;
+
+ GridBagConstraints panelConstraints = new GridBagConstraints();
+ panelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ panelConstraints.fill = GridBagConstraints.HORIZONTAL;
+ panelConstraints.weightx = 1.0;
+ panelConstraints.weighty = 0.0;
+ panelConstraints.anchor = GridBagConstraints.NORTHWEST;
+ panelConstraints.insets = constraints.insets;
+
+ GridBagConstraints stretchPanelConstraints = new GridBagConstraints();
+ stretchPanelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ stretchPanelConstraints.fill = GridBagConstraints.BOTH;
+ stretchPanelConstraints.weightx = 1.0;
+ stretchPanelConstraints.weighty = 1.0;
+ stretchPanelConstraints.anchor = GridBagConstraints.NORTHWEST;
+ stretchPanelConstraints.insets = constraints.insets;
+
+ GridBagConstraints labelConstraints = new GridBagConstraints();
+ labelConstraints.anchor = GridBagConstraints.CENTER;
+ labelConstraints.insets = new Insets(2, 10, 2, 10);
+
+ GridBagConstraints lastLabelConstraints = new GridBagConstraints();
+ lastLabelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ lastLabelConstraints.anchor = GridBagConstraints.CENTER;
+ lastLabelConstraints.insets = labelConstraints.insets;
+
+ GridBagConstraints advancedButtonConstraints = new GridBagConstraints();
+ advancedButtonConstraints.weightx = 1.0;
+ advancedButtonConstraints.weighty = 1.0;
+ advancedButtonConstraints.anchor = GridBagConstraints.SOUTHWEST;
+ advancedButtonConstraints.insets = new Insets(4, 4, 8, 4);
+
+ GridBagConstraints okButtonConstraints = new GridBagConstraints();
+ okButtonConstraints.weightx = 1.0;
+ okButtonConstraints.weighty = 1.0;
+ okButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ okButtonConstraints.insets = advancedButtonConstraints.insets;
+
+ GridBagConstraints cancelButtonConstraints = new GridBagConstraints();
+ cancelButtonConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ cancelButtonConstraints.weighty = 1.0;
+ cancelButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ cancelButtonConstraints.insets = okButtonConstraints.insets;
+
+ GridBagLayout layout = new GridBagLayout();
+
+ Border etchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
+
+ this.isField = isField;
+
+ // Create the access panel.
+ JPanel accessPanel = new JPanel(layout);
+ accessPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("access")));
+
+ accessPanel.add(Box.createGlue(), labelConstraints);
+ accessPanel.add(tip(new JLabel(msg("required")), "requiredTip"), labelConstraints);
+ accessPanel.add(tip(new JLabel(msg("not")), "notTip"), labelConstraints);
+ accessPanel.add(tip(new JLabel(msg("dontCare")), "dontCareTip"), labelConstraints);
+ accessPanel.add(Box.createGlue(), constraintsLastStretch);
+
+ publicRadioButtons = addRadioButtonTriplet("Public", accessPanel);
+ privateRadioButtons = addRadioButtonTriplet("Private", accessPanel);
+ protectedRadioButtons = addRadioButtonTriplet("Protected", accessPanel);
+ staticRadioButtons = addRadioButtonTriplet("Static", accessPanel);
+ finalRadioButtons = addRadioButtonTriplet("Final", accessPanel);
+ syntheticRadioButtons = addRadioButtonTriplet("Synthetic", accessPanel);
+
+ if (isField)
+ {
+ volatileRadioButtons = addRadioButtonTriplet("Volatile", accessPanel);
+ transientRadioButtons = addRadioButtonTriplet("Transient", accessPanel);
+ }
+ else
+ {
+ synchronizedRadioButtons = addRadioButtonTriplet("Synchronized", accessPanel);
+ nativeRadioButtons = addRadioButtonTriplet("Native", accessPanel);
+ abstractRadioButtons = addRadioButtonTriplet("Abstract", accessPanel);
+ strictRadioButtons = addRadioButtonTriplet("Strict", accessPanel);
+ bridgeRadioButtons = addRadioButtonTriplet("Bridge", accessPanel);
+ varargsRadioButtons = addRadioButtonTriplet("Varargs", accessPanel);
+ }
+
+ // Create the type panel.
+ JPanel typePanel = new JPanel(layout);
+ typePanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg(isField ? "fieldType" :
+ "returnType")));
+
+ typePanel.add(tip(typeTextField, "typeTip"), constraintsLastStretch);
+
+ // Create the annotation type panel.
+ final JPanel annotationTypePanel = new JPanel(layout);
+ annotationTypePanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("annotation")));
+
+ annotationTypePanel.add(tip(annotationTypeTextField, "classNameTip"), constraintsLastStretch);
+
+ // Create the name panel.
+ JPanel namePanel = new JPanel(layout);
+ namePanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("name")));
+
+ namePanel.add(tip(nameTextField, isField ? "fieldNameTip" :
+ "methodNameTip"), constraintsLastStretch);
+
+ // Create the arguments panel.
+ JPanel argumentsPanel = new JPanel(layout);
+ argumentsPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
+ msg("argumentTypes")));
+
+ argumentsPanel.add(tip(argumentTypesTextField, "argumentTypes2Tip"), constraintsLastStretch);
+
+ // Create the Advanced button.
+ final JButton advancedButton = new JButton(msg("basic"));
+ advancedButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ boolean visible = !annotationTypePanel.isVisible();
+
+ annotationTypePanel.setVisible(visible);
+
+ advancedButton.setText(msg(visible ? "basic" : "advanced"));
+
+ pack();
+ }
+ });
+ advancedButton.doClick();
+
+ // Create the Ok button.
+ JButton okButton = new JButton(msg("ok"));
+ okButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ returnValue = APPROVE_OPTION;
+ hide();
+ }
+ });
+
+ // Create the Cancel button.
+ JButton cancelButton = new JButton(msg("cancel"));
+ cancelButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ hide();
+ }
+ });
+
+ // Add all panels to the main panel.
+ JPanel mainPanel = new JPanel(layout);
+ mainPanel.add(tip(accessPanel, "accessTip"), panelConstraints);
+ mainPanel.add(tip(annotationTypePanel, "annotationTip"), panelConstraints);
+ mainPanel.add(tip(typePanel, isField ? "fieldTypeTip" :
+ "returnTypeTip"), panelConstraints);
+ mainPanel.add(tip(namePanel, "nameTip"), panelConstraints);
+
+ if (!isField)
+ {
+ mainPanel.add(tip(argumentsPanel, "argumentTypesTip"), panelConstraints);
+ }
+
+ mainPanel.add(tip(advancedButton, "advancedTip"), advancedButtonConstraints);
+ mainPanel.add(okButton, okButtonConstraints);
+ mainPanel.add(cancelButton, cancelButtonConstraints);
+
+ getContentPane().add(new JScrollPane(mainPanel));
+ }
+
+
+ /**
+ * Adds a JLabel and three JRadioButton instances in a ButtonGroup to the
+ * given panel with a GridBagLayout, and returns the buttons in an array.
+ */
+ private JRadioButton[] addRadioButtonTriplet(String labelText,
+ JPanel panel)
+ {
+ GridBagConstraints labelConstraints = new GridBagConstraints();
+ labelConstraints.anchor = GridBagConstraints.WEST;
+ labelConstraints.insets = new Insets(2, 10, 2, 10);
+
+ GridBagConstraints buttonConstraints = new GridBagConstraints();
+ buttonConstraints.insets = labelConstraints.insets;
+
+ GridBagConstraints lastGlueConstraints = new GridBagConstraints();
+ lastGlueConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ lastGlueConstraints.weightx = 1.0;
+
+ // Create the radio buttons.
+ JRadioButton radioButton0 = new JRadioButton();
+ JRadioButton radioButton1 = new JRadioButton();
+ JRadioButton radioButton2 = new JRadioButton();
+
+ // Put them in a button group.
+ ButtonGroup buttonGroup = new ButtonGroup();
+ buttonGroup.add(radioButton0);
+ buttonGroup.add(radioButton1);
+ buttonGroup.add(radioButton2);
+
+ // Add the label and the buttons to the panel.
+ panel.add(new JLabel(labelText), labelConstraints);
+ panel.add(radioButton0, buttonConstraints);
+ panel.add(radioButton1, buttonConstraints);
+ panel.add(radioButton2, buttonConstraints);
+ panel.add(Box.createGlue(), lastGlueConstraints);
+
+ return new JRadioButton[]
+ {
+ radioButton0,
+ radioButton1,
+ radioButton2
+ };
+ }
+
+
+ /**
+ * Sets the MemberSpecification to be represented in this dialog.
+ */
+ public void setMemberSpecification(MemberSpecification memberSpecification)
+ {
+ String annotationType = memberSpecification.annotationType;
+ String name = memberSpecification.name;
+ String descriptor = memberSpecification.descriptor;
+
+ // Set the class name text fields.
+ annotationTypeTextField.setText(annotationType == null ? "" : ClassUtil.externalType(annotationType));
+
+ // Set the access radio buttons.
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PUBLIC, publicRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PRIVATE, privateRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PROTECTED, protectedRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_STATIC, staticRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_FINAL, finalRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_SYNTHETIC, syntheticRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_VOLATILE, volatileRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_TRANSIENT, transientRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_SYNCHRONIZED, synchronizedRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_NATIVE, nativeRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_ABSTRACT, abstractRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_STRICT, strictRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_BRIDGE, bridgeRadioButtons);
+ setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_VARARGS, varargsRadioButtons);
+
+ // Set the class name text fields.
+ nameTextField.setText(name == null ? "*" : name);
+
+ if (isField)
+ {
+ typeTextField .setText(descriptor == null ? "***" : ClassUtil.externalType(descriptor));
+ }
+ else
+ {
+ typeTextField .setText(descriptor == null ? "***" : ClassUtil.externalMethodReturnType(descriptor));
+ argumentTypesTextField.setText(descriptor == null ? "..." : ClassUtil.externalMethodArguments(descriptor));
+ }
+ }
+
+
+ /**
+ * Returns the MemberSpecification currently represented in this dialog.
+ */
+ public MemberSpecification getMemberSpecification()
+ {
+ String annotationType = annotationTypeTextField.getText();
+ String name = nameTextField.getText();
+ String type = typeTextField.getText();
+ String arguments = argumentTypesTextField.getText();
+
+ // Convert all class member specifications into the internal format.
+ annotationType =
+ annotationType.equals("") ||
+ annotationType.equals("***") ? null : ClassUtil.internalType(annotationType);
+
+ if (name.equals("") ||
+ name.equals("*"))
+ {
+ name = null;
+ }
+
+ if (isField)
+ {
+ type =
+ type.equals("") ||
+ type.equals("***") ? null : ClassUtil.internalType(type);
+ }
+ else
+ {
+ if (type.equals(""))
+ {
+ type = JavaConstants.TYPE_VOID;
+ }
+
+ type =
+ type .equals("***") &&
+ arguments.equals("...") ? null :
+ ClassUtil.internalMethodDescriptor(type, ListUtil.commaSeparatedList(arguments));
+ }
+
+ MemberSpecification memberSpecification =
+ new MemberSpecification(0, 0, annotationType, name, type);
+
+ // Also get the access radio button settings.
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PUBLIC, publicRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PRIVATE, privateRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PROTECTED, protectedRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_STATIC, staticRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_FINAL, finalRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_SYNTHETIC, syntheticRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_VOLATILE, volatileRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_TRANSIENT, transientRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_SYNCHRONIZED, synchronizedRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_NATIVE, nativeRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_ABSTRACT, abstractRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_STRICT, strictRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_BRIDGE, bridgeRadioButtons);
+ getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_VARARGS, varargsRadioButtons);
+
+ return memberSpecification;
+ }
+
+
+ /**
+ * Shows this dialog. This method only returns when the dialog is closed.
+ *
+ * @return <code>CANCEL_OPTION</code> or <code>APPROVE_OPTION</code>,
+ * depending on the choice of the user.
+ */
+ public int showDialog()
+ {
+ returnValue = CANCEL_OPTION;
+
+ // Open the dialog in the right place, then wait for it to be closed,
+ // one way or another.
+ pack();
+ setLocationRelativeTo(getOwner());
+ show();
+
+ return returnValue;
+ }
+
+
+ /**
+ * Sets the appropriate radio button of a given triplet, based on the access
+ * flags of the given keep option.
+ */
+ private void setMemberSpecificationRadioButtons(MemberSpecification memberSpecification,
+ int flag,
+ JRadioButton[] radioButtons)
+ {
+ if (radioButtons != null)
+ {
+ int index = (memberSpecification.requiredSetAccessFlags & flag) != 0 ? 0 :
+ (memberSpecification.requiredUnsetAccessFlags & flag) != 0 ? 1 :
+ 2;
+ radioButtons[index].setSelected(true);
+ }
+ }
+
+
+ /**
+ * Updates the access flag of the given keep option, based on the given radio
+ * button triplet.
+ */
+ private void getMemberSpecificationRadioButtons(MemberSpecification memberSpecification,
+ int flag,
+ JRadioButton[] radioButtons)
+ {
+ if (radioButtons != null)
+ {
+ if (radioButtons[0].isSelected())
+ {
+ memberSpecification.requiredSetAccessFlags |= flag;
+ }
+ else if (radioButtons[1].isSelected())
+ {
+ memberSpecification.requiredUnsetAccessFlags |= flag;
+ }
+ }
+ }
+
+
+ /**
+ * Attaches the tool tip from the GUI resources that corresponds to the
+ * given key, to the given component.
+ */
+ private static JComponent tip(JComponent component, String messageKey)
+ {
+ component.setToolTipText(msg(messageKey));
+
+ return component;
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private static String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MemberSpecificationsPanel.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MemberSpecificationsPanel.java
new file mode 100644
index 0000000000..521df9ce15
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MemberSpecificationsPanel.java
@@ -0,0 +1,304 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import proguard.MemberSpecification;
+import proguard.classfile.ClassConstants;
+import proguard.classfile.util.ClassUtil;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.util.List;
+
+
+/**
+ * This <code>ListPanel</code> allows the user to add, edit, move, and remove
+ * MemberSpecification entries in a list.
+ *
+ * @author Eric Lafortune
+ */
+final class MemberSpecificationsPanel extends ListPanel
+{
+ private final MemberSpecificationDialog fieldSpecificationDialog;
+ private final MemberSpecificationDialog methodSpecificationDialog;
+
+
+ public MemberSpecificationsPanel(JDialog owner, boolean fullKeepOptions)
+ {
+ super();
+
+ super.firstSelectionButton = fullKeepOptions ? 3 : 2;
+
+ list.setCellRenderer(new MyListCellRenderer());
+
+ fieldSpecificationDialog = new MemberSpecificationDialog(owner, true);
+ methodSpecificationDialog = new MemberSpecificationDialog(owner, false);
+
+ if (fullKeepOptions)
+ {
+ addAddFieldButton();
+ }
+ addAddMethodButton();
+ addEditButton();
+ addRemoveButton();
+ addUpButton();
+ addDownButton();
+
+ enableSelectionButtons();
+ }
+
+
+ protected void addAddFieldButton()
+ {
+ JButton addFieldButton = new JButton(msg("addField"));
+ addFieldButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ fieldSpecificationDialog.setMemberSpecification(new MemberSpecification());
+ int returnValue = fieldSpecificationDialog.showDialog();
+ if (returnValue == MemberSpecificationDialog.APPROVE_OPTION)
+ {
+ // Add the new element.
+ addElement(new MyMemberSpecificationWrapper(fieldSpecificationDialog.getMemberSpecification(),
+ true));
+ }
+ }
+ });
+
+ addButton(tip(addFieldButton, "addFieldTip"));
+ }
+
+
+ protected void addAddMethodButton()
+ {
+ JButton addMethodButton = new JButton(msg("addMethod"));
+ addMethodButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ methodSpecificationDialog.setMemberSpecification(new MemberSpecification());
+ int returnValue = methodSpecificationDialog.showDialog();
+ if (returnValue == MemberSpecificationDialog.APPROVE_OPTION)
+ {
+ // Add the new element.
+ addElement(new MyMemberSpecificationWrapper(methodSpecificationDialog.getMemberSpecification(),
+ false));
+ }
+ }
+ });
+
+ addButton(tip(addMethodButton, "addMethodTip"));
+ }
+
+
+ protected void addEditButton()
+ {
+ JButton editButton = new JButton(msg("edit"));
+ editButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ MyMemberSpecificationWrapper wrapper =
+ (MyMemberSpecificationWrapper)list.getSelectedValue();
+
+ MemberSpecificationDialog memberSpecificationDialog =
+ wrapper.isField ?
+ fieldSpecificationDialog :
+ methodSpecificationDialog;
+
+ memberSpecificationDialog.setMemberSpecification(wrapper.memberSpecification);
+ int returnValue = memberSpecificationDialog.showDialog();
+ if (returnValue == MemberSpecificationDialog.APPROVE_OPTION)
+ {
+ // Replace the old element.
+ wrapper.memberSpecification = memberSpecificationDialog.getMemberSpecification();
+ setElementAt(wrapper,
+ list.getSelectedIndex());
+ }
+ }
+ });
+
+ addButton(tip(editButton, "editTip"));
+ }
+
+
+ /**
+ * Sets the MemberSpecification instances to be represented in this panel.
+ */
+ public void setMemberSpecifications(List fieldSpecifications,
+ List methodSpecifications)
+ {
+ listModel.clear();
+
+ if (fieldSpecifications != null)
+ {
+ for (int index = 0; index < fieldSpecifications.size(); index++)
+ {
+ listModel.addElement(
+ new MyMemberSpecificationWrapper((MemberSpecification)fieldSpecifications.get(index),
+ true));
+ }
+ }
+
+ if (methodSpecifications != null)
+ {
+ for (int index = 0; index < methodSpecifications.size(); index++)
+ {
+ listModel.addElement(
+ new MyMemberSpecificationWrapper((MemberSpecification)methodSpecifications.get(index),
+ false));
+ }
+ }
+
+ // Make sure the selection buttons are properly enabled,
+ // since the clear method doesn't seem to notify the listener.
+ enableSelectionButtons();
+ }
+
+
+ /**
+ * Returns the MemberSpecification instances currently represented in
+ * this panel, referring to fields or to methods.
+ *
+ * @param isField specifies whether specifications referring to fields or
+ * specifications referring to methods should be returned.
+ */
+ public List getMemberSpecifications(boolean isField)
+ {
+ int size = listModel.size();
+ if (size == 0)
+ {
+ return null;
+ }
+
+ List memberSpecifications = new ArrayList(size);
+ for (int index = 0; index < size; index++)
+ {
+ MyMemberSpecificationWrapper wrapper =
+ (MyMemberSpecificationWrapper)listModel.get(index);
+
+ if (wrapper.isField == isField)
+ {
+ memberSpecifications.add(wrapper.memberSpecification);
+ }
+ }
+
+ return memberSpecifications;
+ }
+
+
+ /**
+ * This ListCellRenderer renders MemberSpecification objects.
+ */
+ private static class MyListCellRenderer implements ListCellRenderer
+ {
+ private final JLabel label = new JLabel();
+
+
+ // Implementations for ListCellRenderer.
+
+ public Component getListCellRendererComponent(JList list,
+ Object value,
+ int index,
+ boolean isSelected,
+ boolean cellHasFocus)
+ {
+ MyMemberSpecificationWrapper wrapper = (MyMemberSpecificationWrapper)value;
+
+ MemberSpecification option = wrapper.memberSpecification;
+ String name = option.name;
+ String descriptor = option.descriptor;
+
+ label.setText(wrapper.isField ?
+ (descriptor == null ? name == null ?
+ "<fields>" :
+ "***" + ' ' + name :
+ ClassUtil.externalFullFieldDescription(0,
+ name == null ? "*" : name,
+ descriptor)) :
+ (descriptor == null ? name == null ?
+ "<methods>" :
+ "***" + ' ' + name + "(...)" :
+ ClassUtil.externalFullMethodDescription(ClassConstants.METHOD_NAME_INIT,
+ 0,
+ name == null ? "*" : name,
+ descriptor)));
+
+ if (isSelected)
+ {
+ label.setBackground(list.getSelectionBackground());
+ label.setForeground(list.getSelectionForeground());
+ }
+ else
+ {
+ label.setBackground(list.getBackground());
+ label.setForeground(list.getForeground());
+ }
+
+ label.setOpaque(true);
+
+ return label;
+ }
+ }
+
+
+ /**
+ * Attaches the tool tip from the GUI resources that corresponds to the
+ * given key, to the given component.
+ */
+ private static JComponent tip(JComponent component, String messageKey)
+ {
+ component.setToolTipText(msg(messageKey));
+
+ return component;
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private static String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+
+
+ /**
+ * This class wraps a MemberSpecification, additionally storing whether
+ * the option refers to a field or to a method.
+ */
+ private static class MyMemberSpecificationWrapper
+ {
+ public MemberSpecification memberSpecification;
+ public final boolean isField;
+
+ public MyMemberSpecificationWrapper(MemberSpecification memberSpecification,
+ boolean isField)
+ {
+ this.memberSpecification = memberSpecification;
+ this.isField = isField;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MessageDialogRunnable.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MessageDialogRunnable.java
new file mode 100644
index 0000000000..c057b129e9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/MessageDialogRunnable.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import javax.swing.*;
+import java.awt.*;
+
+
+/**
+ * This <code>Runnable</code> can show a message dialog.
+ *
+ * @author Eric Lafortune
+ */
+final class MessageDialogRunnable implements Runnable
+{
+ private final Component parentComponent;
+ private final Object message;
+ private final String title;
+ private final int messageType;
+
+
+ /**
+ * Creates a new MessageDialogRunnable object.
+ * @see JOptionPane#showMessageDialog(Component, Object, String, int)
+ */
+ public static void showMessageDialog(Component parentComponent,
+ Object message,
+ String title,
+ int messageType)
+ {
+ try
+ {
+ SwingUtil.invokeAndWait(new MessageDialogRunnable(parentComponent,
+ message,
+ title,
+ messageType));
+ }
+ catch (Exception e)
+ {
+ // Nothing.
+ }
+ }
+
+
+ /**
+ * Creates a new MessageDialogRunnable object.
+ * @see JOptionPane#showMessageDialog(Component, Object, String, int)
+ */
+ public MessageDialogRunnable(Component parentComponent,
+ Object message,
+ String title,
+ int messageType)
+ {
+ this.parentComponent = parentComponent;
+ this.message = message;
+ this.title = title;
+ this.messageType = messageType;
+ }
+
+
+
+ // Implementation for Runnable.
+
+ public void run()
+ {
+ JOptionPane.showMessageDialog(parentComponent,
+ message,
+ title,
+ messageType);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/OptimizationsDialog.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/OptimizationsDialog.java
new file mode 100644
index 0000000000..d844b5b768
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/OptimizationsDialog.java
@@ -0,0 +1,251 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import proguard.optimize.Optimizer;
+import proguard.util.*;
+
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.*;
+import java.awt.event.*;
+
+/**
+ * This <code>JDialog</code> allows the user to enter a String.
+ *
+ * @author Eric Lafortune
+ */
+final class OptimizationsDialog extends JDialog
+{
+ /**
+ * Return value if the dialog is canceled (with the Cancel button or by
+ * closing the dialog window).
+ */
+ public static final int CANCEL_OPTION = 1;
+
+ /**
+ * Return value if the dialog is approved (with the Ok button).
+ */
+ public static final int APPROVE_OPTION = 0;
+
+
+ private final JCheckBox[] optimizationCheckBoxes = new JCheckBox[Optimizer.OPTIMIZATION_NAMES.length];
+
+ private int returnValue;
+
+
+ public OptimizationsDialog(JFrame owner)
+ {
+ super(owner, msg("selectOptimizations"), true);
+ setResizable(true);
+
+ // Create some constraints that can be reused.
+ GridBagConstraints constraintsLast = new GridBagConstraints();
+ constraintsLast.gridwidth = GridBagConstraints.REMAINDER;
+ constraintsLast.anchor = GridBagConstraints.WEST;
+ constraintsLast.insets = new Insets(1, 2, 1, 2);
+
+ GridBagConstraints constraintsLastStretch = new GridBagConstraints();
+ constraintsLastStretch.gridwidth = GridBagConstraints.REMAINDER;
+ constraintsLastStretch.fill = GridBagConstraints.HORIZONTAL;
+ constraintsLastStretch.weightx = 1.0;
+ constraintsLastStretch.anchor = GridBagConstraints.WEST;
+ constraintsLastStretch.insets = constraintsLast.insets;
+
+ GridBagConstraints panelConstraints = new GridBagConstraints();
+ panelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ panelConstraints.fill = GridBagConstraints.HORIZONTAL;
+ panelConstraints.weightx = 1.0;
+ panelConstraints.weighty = 0.0;
+ panelConstraints.anchor = GridBagConstraints.NORTHWEST;
+ panelConstraints.insets = constraintsLast.insets;
+
+ GridBagConstraints selectButtonConstraints = new GridBagConstraints();
+ selectButtonConstraints.weighty = 1.0;
+ selectButtonConstraints.anchor = GridBagConstraints.SOUTHWEST;
+ selectButtonConstraints.insets = new Insets(4, 4, 8, 4);
+
+ GridBagConstraints okButtonConstraints = new GridBagConstraints();
+ okButtonConstraints.weightx = 1.0;
+ okButtonConstraints.weighty = 1.0;
+ okButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ okButtonConstraints.insets = selectButtonConstraints.insets;
+
+ GridBagConstraints cancelButtonConstraints = new GridBagConstraints();
+ cancelButtonConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ cancelButtonConstraints.weighty = 1.0;
+ cancelButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ cancelButtonConstraints.insets = selectButtonConstraints.insets;
+
+ GridBagLayout layout = new GridBagLayout();
+
+ Border etchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
+
+ // Create the optimizations panel.
+ JPanel optimizationsPanel = new JPanel(layout);
+ JPanel optimizationSubpanel = null;
+ String lastOptimizationPrefix = null;
+
+ for (int index = 0; index < Optimizer.OPTIMIZATION_NAMES.length; index++)
+ {
+ String optimizationName = Optimizer.OPTIMIZATION_NAMES[index];
+
+ String optimizationPrefix = optimizationName.substring(0, optimizationName.indexOf('/'));
+
+ if (optimizationSubpanel == null || !optimizationPrefix.equals(lastOptimizationPrefix))
+ {
+ // Create a new keep subpanel and add it.
+ optimizationSubpanel = new JPanel(layout);
+ optimizationSubpanel.setBorder(BorderFactory.createTitledBorder(etchedBorder, msg(optimizationPrefix)));
+ optimizationsPanel.add(optimizationSubpanel, panelConstraints);
+
+ lastOptimizationPrefix = optimizationPrefix;
+ }
+
+ JCheckBox optimizationCheckBox = new JCheckBox(optimizationName);
+ optimizationCheckBoxes[index] = optimizationCheckBox;
+
+ optimizationSubpanel.add(tip(optimizationCheckBox, optimizationName.replace('/', '_')+"Tip"), constraintsLastStretch);
+ }
+
+ // Create the Select All button.
+ JButton selectAllButton = new JButton(msg("selectAll"));
+ selectAllButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ for (int index = 0; index < optimizationCheckBoxes.length; index++)
+ {
+ optimizationCheckBoxes[index].setSelected(true);
+ }
+ }
+ });
+
+ // Create the Select All button.
+ JButton selectNoneButton = new JButton(msg("selectNone"));
+ selectNoneButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ for (int index = 0; index < optimizationCheckBoxes.length; index++)
+ {
+ optimizationCheckBoxes[index].setSelected(false);
+ }
+ }
+ });
+
+ // Create the Ok button.
+ JButton okButton = new JButton(msg("ok"));
+ okButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ returnValue = APPROVE_OPTION;
+ hide();
+ }
+ });
+
+ // Create the Cancel button.
+ JButton cancelButton = new JButton(msg("cancel"));
+ cancelButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ hide();
+ }
+ });
+
+ // Add all panels to the main panel.
+ optimizationsPanel.add(selectAllButton, selectButtonConstraints);
+ optimizationsPanel.add(selectNoneButton, selectButtonConstraints);
+ optimizationsPanel.add(okButton, okButtonConstraints);
+ optimizationsPanel.add(cancelButton, cancelButtonConstraints);
+
+ getContentPane().add(new JScrollPane(optimizationsPanel));
+ }
+
+
+ /**
+ * Sets the initial optimization filter to be used by the dialog.
+ */
+ public void setFilter(String optimizations)
+ {
+ StringMatcher filter = optimizations != null && optimizations.length() > 0 ?
+ new ListParser(new NameParser()).parse(optimizations) :
+ new FixedStringMatcher("");
+
+ for (int index = 0; index < Optimizer.OPTIMIZATION_NAMES.length; index++)
+ {
+ optimizationCheckBoxes[index].setSelected(filter.matches(Optimizer.OPTIMIZATION_NAMES[index]));
+ }
+ }
+
+
+ /**
+ * Returns the optimization filter composed from the settings in the dialog.
+ */
+ public String getFilter()
+ {
+ return new FilterBuilder(optimizationCheckBoxes, '/').buildFilter();
+ }
+
+
+ /**
+ * Shows this dialog. This method only returns when the dialog is closed.
+ *
+ * @return <code>CANCEL_OPTION</code> or <code>APPROVE_OPTION</code>,
+ * depending on the choice of the user.
+ */
+ public int showDialog()
+ {
+ returnValue = CANCEL_OPTION;
+
+ // Open the dialog in the right place, then wait for it to be closed,
+ // one way or another.
+ pack();
+ setLocationRelativeTo(getOwner());
+ show();
+
+ return returnValue;
+ }
+
+
+ /**
+ * Attaches the tool tip from the GUI resources that corresponds to the
+ * given key, to the given component.
+ */
+ private static JComponent tip(JComponent component, String messageKey)
+ {
+ component.setToolTipText(msg(messageKey));
+
+ return component;
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private static String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ProGuardGUI.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ProGuardGUI.java
new file mode 100644
index 0000000000..04f58e005e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ProGuardGUI.java
@@ -0,0 +1,1778 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import proguard.*;
+import proguard.classfile.util.ClassUtil;
+import proguard.gui.splash.*;
+import proguard.util.ListUtil;
+
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.URL;
+import java.util.*;
+import java.util.List;
+
+
+/**
+ * GUI for configuring and executing ProGuard and ReTrace.
+ *
+ * @author Eric Lafortune
+ */
+public class ProGuardGUI extends JFrame
+{
+ private static final String NO_SPLASH_OPTION = "-nosplash";
+
+ private static final String TITLE_IMAGE_FILE = "vtitle.png";
+ private static final String BOILERPLATE_CONFIGURATION = "boilerplate.pro";
+ private static final String DEFAULT_CONFIGURATION = "default.pro";
+
+ private static final String OPTIMIZATIONS_DEFAULT = "*";
+ private static final String KEEP_ATTRIBUTE_DEFAULT = "Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod";
+ private static final String SOURCE_FILE_ATTRIBUTE_DEFAULT = "SourceFile";
+ private static final String ADAPT_RESOURCE_FILE_NAMES_DEFAULT = "**.properties";
+ private static final String ADAPT_RESOURCE_FILE_CONTENTS_DEFAULT = "**.properties,META-INF/MANIFEST.MF";
+
+ private static final Border BORDER = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
+
+ static boolean systemOutRedirected;
+
+ private final JFileChooser configurationChooser = new JFileChooser("");
+ private final JFileChooser fileChooser = new JFileChooser("");
+
+ private final SplashPanel splashPanel;
+
+ private final ClassPathPanel programPanel = new ClassPathPanel(this, true);
+ private final ClassPathPanel libraryPanel = new ClassPathPanel(this, false);
+
+ private KeepClassSpecification[] boilerplateKeep;
+ private final JCheckBox[] boilerplateKeepCheckBoxes;
+ private final JTextField[] boilerplateKeepTextFields;
+
+ private final KeepSpecificationsPanel additionalKeepPanel = new KeepSpecificationsPanel(this, true, false, false, false, false, false);
+
+ private KeepClassSpecification[] boilerplateKeepNames;
+ private final JCheckBox[] boilerplateKeepNamesCheckBoxes;
+ private final JTextField[] boilerplateKeepNamesTextFields;
+
+ private final KeepSpecificationsPanel additionalKeepNamesPanel = new KeepSpecificationsPanel(this, true, false, false, true, false, false);
+
+ private ClassSpecification[] boilerplateNoSideEffectMethods;
+ private final JCheckBox[] boilerplateNoSideEffectMethodCheckBoxes;
+
+ private final ClassSpecificationsPanel additionalNoSideEffectsPanel = new ClassSpecificationsPanel(this, false);
+
+ private final ClassSpecificationsPanel whyAreYouKeepingPanel = new ClassSpecificationsPanel(this, false);
+
+ private final JCheckBox shrinkCheckBox = new JCheckBox(msg("shrink"));
+ private final JCheckBox printUsageCheckBox = new JCheckBox(msg("printUsage"));
+
+ private final JCheckBox optimizeCheckBox = new JCheckBox(msg("optimize"));
+ private final JCheckBox allowAccessModificationCheckBox = new JCheckBox(msg("allowAccessModification"));
+ private final JCheckBox mergeInterfacesAggressivelyCheckBox = new JCheckBox(msg("mergeInterfacesAggressively"));
+ private final JLabel optimizationsLabel = new JLabel(msg("optimizations"));
+ private final JLabel optimizationPassesLabel = new JLabel(msg("optimizationPasses"));
+
+ private final JSpinner optimizationPassesSpinner = new JSpinner(new SpinnerNumberModel(1, 1, 9, 1));
+
+ private final JCheckBox obfuscateCheckBox = new JCheckBox(msg("obfuscate"));
+ private final JCheckBox printMappingCheckBox = new JCheckBox(msg("printMapping"));
+ private final JCheckBox applyMappingCheckBox = new JCheckBox(msg("applyMapping"));
+ private final JCheckBox obfuscationDictionaryCheckBox = new JCheckBox(msg("obfuscationDictionary"));
+ private final JCheckBox classObfuscationDictionaryCheckBox = new JCheckBox(msg("classObfuscationDictionary"));
+ private final JCheckBox packageObfuscationDictionaryCheckBox = new JCheckBox(msg("packageObfuscationDictionary"));
+ private final JCheckBox overloadAggressivelyCheckBox = new JCheckBox(msg("overloadAggressively"));
+ private final JCheckBox useUniqueClassMemberNamesCheckBox = new JCheckBox(msg("useUniqueClassMemberNames"));
+ private final JCheckBox useMixedCaseClassNamesCheckBox = new JCheckBox(msg("useMixedCaseClassNames"));
+ private final JCheckBox keepPackageNamesCheckBox = new JCheckBox(msg("keepPackageNames"));
+ private final JCheckBox flattenPackageHierarchyCheckBox = new JCheckBox(msg("flattenPackageHierarchy"));
+ private final JCheckBox repackageClassesCheckBox = new JCheckBox(msg("repackageClasses"));
+ private final JCheckBox keepAttributesCheckBox = new JCheckBox(msg("keepAttributes"));
+ private final JCheckBox keepParameterNamesCheckBox = new JCheckBox(msg("keepParameterNames"));
+ private final JCheckBox newSourceFileAttributeCheckBox = new JCheckBox(msg("renameSourceFileAttribute"));
+ private final JCheckBox adaptClassStringsCheckBox = new JCheckBox(msg("adaptClassStrings"));
+ private final JCheckBox adaptResourceFileNamesCheckBox = new JCheckBox(msg("adaptResourceFileNames"));
+ private final JCheckBox adaptResourceFileContentsCheckBox = new JCheckBox(msg("adaptResourceFileContents"));
+
+ private final JCheckBox preverifyCheckBox = new JCheckBox(msg("preverify"));
+ private final JCheckBox microEditionCheckBox = new JCheckBox(msg("microEdition"));
+ private final JCheckBox targetCheckBox = new JCheckBox(msg("target"));
+
+ private final JComboBox targetComboBox = new JComboBox(ListUtil.commaSeparatedList(msg("targets")).toArray());
+
+ private final JCheckBox verboseCheckBox = new JCheckBox(msg("verbose"));
+ private final JCheckBox noteCheckBox = new JCheckBox(msg("note"));
+ private final JCheckBox warnCheckBox = new JCheckBox(msg("warn"));
+ private final JCheckBox ignoreWarningsCheckBox = new JCheckBox(msg("ignoreWarnings"));
+ private final JCheckBox skipNonPublicLibraryClassesCheckBox = new JCheckBox(msg("skipNonPublicLibraryClasses"));
+ private final JCheckBox skipNonPublicLibraryClassMembersCheckBox = new JCheckBox(msg("skipNonPublicLibraryClassMembers"));
+ private final JCheckBox keepDirectoriesCheckBox = new JCheckBox(msg("keepDirectories"));
+ private final JCheckBox forceProcessingCheckBox = new JCheckBox(msg("forceProcessing"));
+ private final JCheckBox printSeedsCheckBox = new JCheckBox(msg("printSeeds"));
+ private final JCheckBox printConfigurationCheckBox = new JCheckBox(msg("printConfiguration"));
+ private final JCheckBox dumpCheckBox = new JCheckBox(msg("dump"));
+
+ private final JTextField printUsageTextField = new JTextField(40);
+ private final JTextField optimizationsTextField = new JTextField(40);
+ private final JTextField printMappingTextField = new JTextField(40);
+ private final JTextField applyMappingTextField = new JTextField(40);
+ private final JTextField obfuscationDictionaryTextField = new JTextField(40);
+ private final JTextField classObfuscationDictionaryTextField = new JTextField(40);
+ private final JTextField packageObfuscationDictionaryTextField = new JTextField(40);
+ private final JTextField keepPackageNamesTextField = new JTextField(40);
+ private final JTextField flattenPackageHierarchyTextField = new JTextField(40);
+ private final JTextField repackageClassesTextField = new JTextField(40);
+ private final JTextField keepAttributesTextField = new JTextField(40);
+ private final JTextField newSourceFileAttributeTextField = new JTextField(40);
+ private final JTextField adaptClassStringsTextField = new JTextField(40);
+ private final JTextField adaptResourceFileNamesTextField = new JTextField(40);
+ private final JTextField adaptResourceFileContentsTextField = new JTextField(40);
+ private final JTextField noteTextField = new JTextField(40);
+ private final JTextField warnTextField = new JTextField(40);
+ private final JTextField keepDirectoriesTextField = new JTextField(40);
+ private final JTextField printSeedsTextField = new JTextField(40);
+ private final JTextField printConfigurationTextField = new JTextField(40);
+ private final JTextField dumpTextField = new JTextField(40);
+
+ private final JTextArea consoleTextArea = new JTextArea(msg("processingInfo"), 3, 40);
+
+ private final JCheckBox reTraceVerboseCheckBox = new JCheckBox(msg("verbose"));
+ private final JTextField reTraceMappingTextField = new JTextField(40);
+ private final JTextArea stackTraceTextArea = new JTextArea(3, 40);
+ private final JTextArea reTraceTextArea = new JTextArea(msg("reTraceInfo"), 3, 40);
+
+
+ /**
+ * Creates a new ProGuardGUI.
+ */
+ public ProGuardGUI()
+ {
+ setTitle("ProGuard");
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
+
+ // Create some constraints that can be reused.
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.anchor = GridBagConstraints.WEST;
+ constraints.insets = new Insets(0, 4, 0, 4);
+
+ GridBagConstraints constraintsStretch = new GridBagConstraints();
+ constraintsStretch.fill = GridBagConstraints.HORIZONTAL;
+ constraintsStretch.weightx = 1.0;
+ constraintsStretch.anchor = GridBagConstraints.WEST;
+ constraintsStretch.insets = constraints.insets;
+
+ GridBagConstraints constraintsLast = new GridBagConstraints();
+ constraintsLast.gridwidth = GridBagConstraints.REMAINDER;
+ constraintsLast.anchor = GridBagConstraints.WEST;
+ constraintsLast.insets = constraints.insets;
+
+ GridBagConstraints constraintsLastStretch = new GridBagConstraints();
+ constraintsLastStretch.gridwidth = GridBagConstraints.REMAINDER;
+ constraintsLastStretch.fill = GridBagConstraints.HORIZONTAL;
+ constraintsLastStretch.weightx = 1.0;
+ constraintsLastStretch.anchor = GridBagConstraints.WEST;
+ constraintsLastStretch.insets = constraints.insets;
+
+ GridBagConstraints splashPanelConstraints = new GridBagConstraints();
+ splashPanelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ splashPanelConstraints.fill = GridBagConstraints.BOTH;
+ splashPanelConstraints.weightx = 1.0;
+ splashPanelConstraints.weighty = 0.02;
+ splashPanelConstraints.anchor = GridBagConstraints.NORTHWEST;
+ //splashPanelConstraints.insets = constraints.insets;
+
+ GridBagConstraints welcomePaneConstraints = new GridBagConstraints();
+ welcomePaneConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ welcomePaneConstraints.fill = GridBagConstraints.NONE;
+ welcomePaneConstraints.weightx = 1.0;
+ welcomePaneConstraints.weighty = 0.01;
+ welcomePaneConstraints.anchor = GridBagConstraints.CENTER;//NORTHWEST;
+ welcomePaneConstraints.insets = new Insets(20, 40, 20, 40);
+
+ GridBagConstraints panelConstraints = new GridBagConstraints();
+ panelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ panelConstraints.fill = GridBagConstraints.HORIZONTAL;
+ panelConstraints.weightx = 1.0;
+ panelConstraints.anchor = GridBagConstraints.NORTHWEST;
+ panelConstraints.insets = constraints.insets;
+
+ GridBagConstraints stretchPanelConstraints = new GridBagConstraints();
+ stretchPanelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ stretchPanelConstraints.fill = GridBagConstraints.BOTH;
+ stretchPanelConstraints.weightx = 1.0;
+ stretchPanelConstraints.weighty = 1.0;
+ stretchPanelConstraints.anchor = GridBagConstraints.NORTHWEST;
+ stretchPanelConstraints.insets = constraints.insets;
+
+ GridBagConstraints glueConstraints = new GridBagConstraints();
+ glueConstraints.fill = GridBagConstraints.BOTH;
+ glueConstraints.weightx = 0.01;
+ glueConstraints.weighty = 0.01;
+ glueConstraints.anchor = GridBagConstraints.NORTHWEST;
+ glueConstraints.insets = constraints.insets;
+
+ GridBagConstraints bottomButtonConstraints = new GridBagConstraints();
+ bottomButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ bottomButtonConstraints.insets = new Insets(2, 2, 4, 6);
+ bottomButtonConstraints.ipadx = 10;
+ bottomButtonConstraints.ipady = 2;
+
+ GridBagConstraints lastBottomButtonConstraints = new GridBagConstraints();
+ lastBottomButtonConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ lastBottomButtonConstraints.anchor = GridBagConstraints.SOUTHEAST;
+ lastBottomButtonConstraints.insets = bottomButtonConstraints.insets;
+ lastBottomButtonConstraints.ipadx = bottomButtonConstraints.ipadx;
+ lastBottomButtonConstraints.ipady = bottomButtonConstraints.ipady;
+
+ // Leave room for a growBox on Mac OS X.
+ if (System.getProperty("os.name").toLowerCase().startsWith("mac os x"))
+ {
+ lastBottomButtonConstraints.insets = new Insets(2, 2, 4, 6 + 16);
+ }
+
+ GridBagLayout layout = new GridBagLayout();
+
+ configurationChooser.addChoosableFileFilter(
+ new ExtensionFileFilter(msg("proExtension"), new String[] { ".pro" }));
+
+ // Create the opening panel.
+ Sprite splash =
+ new CompositeSprite(new Sprite[]
+ {
+ new ColorSprite(new ConstantColor(Color.gray),
+ new FontSprite(new ConstantFont(new Font("sansserif", Font.BOLD, 90)),
+ new TextSprite(new ConstantString("ProGuard"),
+ new ConstantInt(160),
+ new LinearInt(-10, 120, new SmoothTiming(500, 1000))))),
+
+ new ColorSprite(new ConstantColor(Color.white),
+ new FontSprite(new ConstantFont(new Font("sansserif", Font.BOLD, 45)),
+ new ShadowedSprite(new ConstantInt(3),
+ new ConstantInt(3),
+ new ConstantDouble(0.4),
+ new ConstantInt(1),
+ new CompositeSprite(new Sprite[]
+ {
+ new TextSprite(new ConstantString(msg("shrinking")),
+ new LinearInt(1000, 60, new SmoothTiming(1000, 2000)),
+ new ConstantInt(70)),
+ new TextSprite(new ConstantString(msg("optimization")),
+ new LinearInt(1000, 400, new SmoothTiming(1500, 2500)),
+ new ConstantInt(60)),
+ new TextSprite(new ConstantString(msg("obfuscation")),
+ new LinearInt(1000, 10, new SmoothTiming(2000, 3000)),
+ new ConstantInt(145)),
+ new TextSprite(new ConstantString(msg("preverification")),
+ new LinearInt(1000, 350, new SmoothTiming(2500, 3500)),
+ new ConstantInt(140)),
+ new FontSprite(new ConstantFont(new Font("sansserif", Font.BOLD, 30)),
+ new TextSprite(new TypeWriterString(msg("developed"), new LinearTiming(3500, 5500)),
+ new ConstantInt(250),
+ new ConstantInt(200))),
+ })))),
+ });
+ splashPanel = new SplashPanel(splash, 0.5, 5500L);
+ splashPanel.setPreferredSize(new Dimension(0, 200));
+
+ JEditorPane welcomePane = new JEditorPane("text/html", msg("proGuardInfo"));
+ welcomePane.setPreferredSize(new Dimension(640, 350));
+ // The constant HONOR_DISPLAY_PROPERTIES isn't present yet in JDK 1.4.
+ //welcomePane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
+ welcomePane.putClientProperty("JEditorPane.honorDisplayProperties", Boolean.TRUE);
+ welcomePane.setOpaque(false);
+ welcomePane.setEditable(false);
+ welcomePane.setBorder(new EmptyBorder(20, 20, 20, 20));
+ addBorder(welcomePane, "welcome");
+
+ JPanel proGuardPanel = new JPanel(layout);
+ proGuardPanel.add(splashPanel, splashPanelConstraints);
+ proGuardPanel.add(welcomePane, welcomePaneConstraints);
+
+ // Create the input panel.
+ // TODO: properly clone the ClassPath objects.
+ // This is awkward to implement in the generic ListPanel.addElements(...)
+ // method, since the Object.clone() method is not public.
+ programPanel.addCopyToPanelButton("moveToLibraries", "moveToLibrariesTip", libraryPanel);
+ libraryPanel.addCopyToPanelButton("moveToProgram", "moveToProgramTip", programPanel);
+
+ // Collect all buttons of these panels and make sure they are equally
+ // sized.
+ List panelButtons = new ArrayList();
+ panelButtons.addAll(programPanel.getButtons());
+ panelButtons.addAll(libraryPanel.getButtons());
+ setCommonPreferredSize(panelButtons);
+
+ addBorder(programPanel, "programJars" );
+ addBorder(libraryPanel, "libraryJars" );
+
+ JPanel inputOutputPanel = new JPanel(layout);
+ inputOutputPanel.add(tip(programPanel, "programJarsTip"), stretchPanelConstraints);
+ inputOutputPanel.add(tip(libraryPanel, "libraryJarsTip"), stretchPanelConstraints);
+
+ // Load the boiler plate options.
+ loadBoilerplateConfiguration();
+
+ // Create the boiler plate keep panels.
+ boilerplateKeepCheckBoxes = new JCheckBox[boilerplateKeep.length];
+ boilerplateKeepTextFields = new JTextField[boilerplateKeep.length];
+
+ JButton printUsageBrowseButton = createBrowseButton(printUsageTextField,
+ msg("selectUsageFile"));
+
+ JPanel shrinkingOptionsPanel = new JPanel(layout);
+ addBorder(shrinkingOptionsPanel, "options");
+
+ shrinkingOptionsPanel.add(tip(shrinkCheckBox, "shrinkTip"), constraintsLastStretch);
+ shrinkingOptionsPanel.add(tip(printUsageCheckBox, "printUsageTip"), constraints);
+ shrinkingOptionsPanel.add(tip(printUsageTextField, "outputFileTip"), constraintsStretch);
+ shrinkingOptionsPanel.add(tip(printUsageBrowseButton, "selectUsageFile"), constraintsLast);
+
+ JPanel shrinkingPanel = new JPanel(layout);
+
+ shrinkingPanel.add(shrinkingOptionsPanel, panelConstraints);
+ addClassSpecifications(extractClassSpecifications(boilerplateKeep),
+ shrinkingPanel,
+ boilerplateKeepCheckBoxes,
+ boilerplateKeepTextFields);
+
+ addBorder(additionalKeepPanel, "keepAdditional");
+ shrinkingPanel.add(tip(additionalKeepPanel, "keepAdditionalTip"), stretchPanelConstraints);
+
+ // Create the boiler plate keep names panels.
+ boilerplateKeepNamesCheckBoxes = new JCheckBox[boilerplateKeepNames.length];
+ boilerplateKeepNamesTextFields = new JTextField[boilerplateKeepNames.length];
+
+ JButton printMappingBrowseButton = createBrowseButton(printMappingTextField,
+ msg("selectPrintMappingFile"));
+ JButton applyMappingBrowseButton = createBrowseButton(applyMappingTextField,
+ msg("selectApplyMappingFile"));
+ JButton obfucationDictionaryBrowseButton = createBrowseButton(obfuscationDictionaryTextField,
+ msg("selectObfuscationDictionaryFile"));
+ JButton classObfucationDictionaryBrowseButton = createBrowseButton(classObfuscationDictionaryTextField,
+ msg("selectObfuscationDictionaryFile"));
+ JButton packageObfucationDictionaryBrowseButton = createBrowseButton(packageObfuscationDictionaryTextField,
+ msg("selectObfuscationDictionaryFile"));
+
+ JPanel obfuscationOptionsPanel = new JPanel(layout);
+ addBorder(obfuscationOptionsPanel, "options");
+
+ obfuscationOptionsPanel.add(tip(obfuscateCheckBox, "obfuscateTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(printMappingCheckBox, "printMappingTip"), constraints);
+ obfuscationOptionsPanel.add(tip(printMappingTextField, "outputFileTip"), constraintsStretch);
+ obfuscationOptionsPanel.add(tip(printMappingBrowseButton, "selectPrintMappingFile"), constraintsLast);
+ obfuscationOptionsPanel.add(tip(applyMappingCheckBox, "applyMappingTip"), constraints);
+ obfuscationOptionsPanel.add(tip(applyMappingTextField, "inputFileTip"), constraintsStretch);
+ obfuscationOptionsPanel.add(tip(applyMappingBrowseButton, "selectApplyMappingFile"), constraintsLast);
+ obfuscationOptionsPanel.add(tip(obfuscationDictionaryCheckBox, "obfuscationDictionaryTip"), constraints);
+ obfuscationOptionsPanel.add(tip(obfuscationDictionaryTextField, "inputFileTip"), constraintsStretch);
+ obfuscationOptionsPanel.add(tip(obfucationDictionaryBrowseButton, "selectObfuscationDictionaryFile"), constraintsLast);
+ obfuscationOptionsPanel.add(tip(classObfuscationDictionaryCheckBox, "classObfuscationDictionaryTip"), constraints);
+ obfuscationOptionsPanel.add(tip(classObfuscationDictionaryTextField, "inputFileTip"), constraintsStretch);
+ obfuscationOptionsPanel.add(tip(classObfucationDictionaryBrowseButton, "selectObfuscationDictionaryFile"), constraintsLast);
+ obfuscationOptionsPanel.add(tip(packageObfuscationDictionaryCheckBox, "packageObfuscationDictionaryTip"), constraints);
+ obfuscationOptionsPanel.add(tip(packageObfuscationDictionaryTextField, "inputFileTip"), constraintsStretch);
+ obfuscationOptionsPanel.add(tip(packageObfucationDictionaryBrowseButton, "selectObfuscationDictionaryFile"), constraintsLast);
+ obfuscationOptionsPanel.add(tip(overloadAggressivelyCheckBox, "overloadAggressivelyTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(useUniqueClassMemberNamesCheckBox, "useUniqueClassMemberNamesTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(useMixedCaseClassNamesCheckBox, "useMixedCaseClassNamesTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(keepPackageNamesCheckBox, "keepPackageNamesTip"), constraints);
+ obfuscationOptionsPanel.add(tip(keepPackageNamesTextField, "packageNamesTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(flattenPackageHierarchyCheckBox, "flattenPackageHierarchyTip"), constraints);
+ obfuscationOptionsPanel.add(tip(flattenPackageHierarchyTextField, "packageTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(repackageClassesCheckBox, "repackageClassesTip"), constraints);
+ obfuscationOptionsPanel.add(tip(repackageClassesTextField, "packageTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(keepAttributesCheckBox, "keepAttributesTip"), constraints);
+ obfuscationOptionsPanel.add(tip(keepAttributesTextField, "attributesTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(keepParameterNamesCheckBox, "keepParameterNamesTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(newSourceFileAttributeCheckBox, "renameSourceFileAttributeTip"), constraints);
+ obfuscationOptionsPanel.add(tip(newSourceFileAttributeTextField, "sourceFileAttributeTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(adaptClassStringsCheckBox, "adaptClassStringsTip"), constraints);
+ obfuscationOptionsPanel.add(tip(adaptClassStringsTextField, "classNamesTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(adaptResourceFileNamesCheckBox, "adaptResourceFileNamesTip"), constraints);
+ obfuscationOptionsPanel.add(tip(adaptResourceFileNamesTextField, "fileNameFilterTip"), constraintsLastStretch);
+ obfuscationOptionsPanel.add(tip(adaptResourceFileContentsCheckBox, "adaptResourceFileContentsTip"), constraints);
+ obfuscationOptionsPanel.add(tip(adaptResourceFileContentsTextField, "fileNameFilterTip"), constraintsLastStretch);
+
+ JPanel obfuscationPanel = new JPanel(layout);
+
+ obfuscationPanel.add(obfuscationOptionsPanel, panelConstraints);
+ addClassSpecifications(extractClassSpecifications(boilerplateKeepNames),
+ obfuscationPanel,
+ boilerplateKeepNamesCheckBoxes,
+ boilerplateKeepNamesTextFields);
+
+ addBorder(additionalKeepNamesPanel, "keepNamesAdditional");
+ obfuscationPanel.add(tip(additionalKeepNamesPanel, "keepNamesAdditionalTip"), stretchPanelConstraints);
+
+ // Create the boiler plate "no side effect methods" panels.
+ boilerplateNoSideEffectMethodCheckBoxes = new JCheckBox[boilerplateNoSideEffectMethods.length];
+
+ JPanel optimizationOptionsPanel = new JPanel(layout);
+ addBorder(optimizationOptionsPanel, "options");
+
+ JButton optimizationsButton =
+ createOptimizationsButton(optimizationsTextField);
+
+ optimizationOptionsPanel.add(tip(optimizeCheckBox, "optimizeTip"), constraintsLastStretch);
+ optimizationOptionsPanel.add(tip(allowAccessModificationCheckBox, "allowAccessModificationTip"), constraintsLastStretch);
+ optimizationOptionsPanel.add(tip(mergeInterfacesAggressivelyCheckBox, "mergeInterfacesAggressivelyTip"), constraintsLastStretch);
+ optimizationOptionsPanel.add(tip(optimizationsLabel, "optimizationsTip"), constraints);
+ optimizationOptionsPanel.add(tip(optimizationsTextField, "optimizationsFilterTip"), constraintsStretch);
+ optimizationOptionsPanel.add(tip(optimizationsButton, "optimizationsSelectTip"), constraintsLast);
+ optimizationOptionsPanel.add(tip(optimizationPassesLabel, "optimizationPassesTip"), constraints);
+ optimizationOptionsPanel.add(tip(optimizationPassesSpinner, "optimizationPassesTip"), constraintsLast);
+
+ JPanel optimizationPanel = new JPanel(layout);
+
+ optimizationPanel.add(optimizationOptionsPanel, panelConstraints);
+ addClassSpecifications(boilerplateNoSideEffectMethods,
+ optimizationPanel,
+ boilerplateNoSideEffectMethodCheckBoxes,
+ null);
+
+ addBorder(additionalNoSideEffectsPanel, "assumeNoSideEffectsAdditional");
+ optimizationPanel.add(tip(additionalNoSideEffectsPanel, "assumeNoSideEffectsAdditionalTip"), stretchPanelConstraints);
+
+ // Create the options panel.
+ JPanel preverificationOptionsPanel = new JPanel(layout);
+ addBorder(preverificationOptionsPanel, "preverificationAndTargeting");
+
+ preverificationOptionsPanel.add(tip(preverifyCheckBox, "preverifyTip"), constraintsLastStretch);
+ preverificationOptionsPanel.add(tip(microEditionCheckBox, "microEditionTip"), constraintsLastStretch);
+ preverificationOptionsPanel.add(tip(targetCheckBox, "targetTip"), constraints);
+ preverificationOptionsPanel.add(tip(targetComboBox, "targetTip"), constraintsLast);
+
+ JButton printSeedsBrowseButton =
+ createBrowseButton(printSeedsTextField, msg("selectSeedsFile"));
+
+ JButton printConfigurationBrowseButton =
+ createBrowseButton(printConfigurationTextField, msg( "selectConfigurationFile"));
+
+ JButton dumpBrowseButton =
+ createBrowseButton(dumpTextField, msg("selectDumpFile"));
+
+ // Select the most recent target by default.
+ targetComboBox.setSelectedIndex(targetComboBox.getItemCount() - 1);
+
+ JPanel consistencyPanel = new JPanel(layout);
+ addBorder(consistencyPanel, "consistencyAndCorrectness");
+
+ consistencyPanel.add(tip(verboseCheckBox, "verboseTip"), constraintsLastStretch);
+ consistencyPanel.add(tip(noteCheckBox, "noteTip"), constraints);
+ consistencyPanel.add(tip(noteTextField, "noteFilterTip"), constraintsLastStretch);
+ consistencyPanel.add(tip(warnCheckBox, "warnTip"), constraints);
+ consistencyPanel.add(tip(warnTextField, "warnFilterTip"), constraintsLastStretch);
+ consistencyPanel.add(tip(ignoreWarningsCheckBox, "ignoreWarningsTip"), constraintsLastStretch);
+ consistencyPanel.add(tip(skipNonPublicLibraryClassesCheckBox, "skipNonPublicLibraryClassesTip"), constraintsLastStretch);
+ consistencyPanel.add(tip(skipNonPublicLibraryClassMembersCheckBox, "skipNonPublicLibraryClassMembersTip"), constraintsLastStretch);
+ consistencyPanel.add(tip(keepDirectoriesCheckBox, "keepDirectoriesTip"), constraints);
+ consistencyPanel.add(tip(keepDirectoriesTextField, "directoriesTip"), constraintsLastStretch);
+ consistencyPanel.add(tip(forceProcessingCheckBox, "forceProcessingTip"), constraintsLastStretch);
+ consistencyPanel.add(tip(printSeedsCheckBox, "printSeedsTip"), constraints);
+ consistencyPanel.add(tip(printSeedsTextField, "outputFileTip"), constraintsStretch);
+ consistencyPanel.add(tip(printSeedsBrowseButton, "selectSeedsFile"), constraintsLast);
+ consistencyPanel.add(tip(printConfigurationCheckBox, "printConfigurationTip"), constraints);
+ consistencyPanel.add(tip(printConfigurationTextField, "outputFileTip"), constraintsStretch);
+ consistencyPanel.add(tip(printConfigurationBrowseButton, "selectConfigurationFile"), constraintsLast);
+ consistencyPanel.add(tip(dumpCheckBox, "dumpTip"), constraints);
+ consistencyPanel.add(tip(dumpTextField, "outputFileTip"), constraintsStretch);
+ consistencyPanel.add(tip(dumpBrowseButton, "selectDumpFile"), constraintsLast);
+
+ // Collect all components that are followed by text fields and make
+ // sure they are equally sized. That way the text fields start at the
+ // same horizontal position.
+ setCommonPreferredSize(Arrays.asList(new JComponent[] {
+ printMappingCheckBox,
+ applyMappingCheckBox,
+ flattenPackageHierarchyCheckBox,
+ repackageClassesCheckBox,
+ newSourceFileAttributeCheckBox,
+ }));
+
+ JPanel optionsPanel = new JPanel(layout);
+
+ optionsPanel.add(preverificationOptionsPanel, panelConstraints);
+ optionsPanel.add(consistencyPanel, panelConstraints);
+
+ addBorder(whyAreYouKeepingPanel, "whyAreYouKeeping");
+ optionsPanel.add(tip(whyAreYouKeepingPanel, "whyAreYouKeepingTip"), stretchPanelConstraints);
+
+ // Create the process panel.
+ consoleTextArea.setOpaque(false);
+ consoleTextArea.setEditable(false);
+ consoleTextArea.setLineWrap(false);
+ consoleTextArea.setWrapStyleWord(false);
+ JScrollPane consoleScrollPane = new JScrollPane(consoleTextArea);
+ consoleScrollPane.setBorder(new EmptyBorder(1, 1, 1, 1));
+ addBorder(consoleScrollPane, "processingConsole");
+
+ JPanel processPanel = new JPanel(layout);
+ processPanel.add(consoleScrollPane, stretchPanelConstraints);
+
+ // Create the load, save, and process buttons.
+ JButton loadButton = new JButton(msg("loadConfiguration"));
+ loadButton.addActionListener(new MyLoadConfigurationActionListener());
+
+ JButton viewButton = new JButton(msg("viewConfiguration"));
+ viewButton.addActionListener(new MyViewConfigurationActionListener());
+
+ JButton saveButton = new JButton(msg("saveConfiguration"));
+ saveButton.addActionListener(new MySaveConfigurationActionListener());
+
+ JButton processButton = new JButton(msg("process"));
+ processButton.addActionListener(new MyProcessActionListener());
+
+ // Create the ReTrace panel.
+ JPanel reTraceSettingsPanel = new JPanel(layout);
+ addBorder(reTraceSettingsPanel, "reTraceSettings");
+
+ JButton reTraceMappingBrowseButton = createBrowseButton(reTraceMappingTextField,
+ msg("selectApplyMappingFile"));
+
+ JLabel reTraceMappingLabel = new JLabel(msg("mappingFile"));
+ reTraceMappingLabel.setForeground(reTraceVerboseCheckBox.getForeground());
+
+ reTraceSettingsPanel.add(tip(reTraceVerboseCheckBox, "verboseTip"), constraintsLastStretch);
+ reTraceSettingsPanel.add(tip(reTraceMappingLabel, "mappingFileTip"), constraints);
+ reTraceSettingsPanel.add(tip(reTraceMappingTextField, "inputFileTip"), constraintsStretch);
+ reTraceSettingsPanel.add(tip(reTraceMappingBrowseButton, "selectApplyMappingFile"), constraintsLast);
+
+ stackTraceTextArea.setOpaque(true);
+ stackTraceTextArea.setEditable(true);
+ stackTraceTextArea.setLineWrap(false);
+ stackTraceTextArea.setWrapStyleWord(true);
+ JScrollPane stackTraceScrollPane = new JScrollPane(stackTraceTextArea);
+ addBorder(stackTraceScrollPane, "obfuscatedStackTrace");
+
+ reTraceTextArea.setOpaque(false);
+ reTraceTextArea.setEditable(false);
+ reTraceTextArea.setLineWrap(true);
+ reTraceTextArea.setWrapStyleWord(true);
+ JScrollPane reTraceScrollPane = new JScrollPane(reTraceTextArea);
+ reTraceScrollPane.setBorder(new EmptyBorder(1, 1, 1, 1));
+ addBorder(reTraceScrollPane, "deobfuscatedStackTrace");
+
+ JPanel reTracePanel = new JPanel(layout);
+ reTracePanel.add(reTraceSettingsPanel, panelConstraints);
+ reTracePanel.add(tip(stackTraceScrollPane, "obfuscatedStackTraceTip"), panelConstraints);
+ reTracePanel.add(reTraceScrollPane, stretchPanelConstraints);
+
+ // Create the load button.
+ JButton loadStackTraceButton = new JButton(msg("loadStackTrace"));
+ loadStackTraceButton.addActionListener(new MyLoadStackTraceActionListener());
+
+ JButton reTraceButton = new JButton(msg("reTrace"));
+ reTraceButton.addActionListener(new MyReTraceActionListener());
+
+ // Create the main tabbed pane.
+ TabbedPane tabs = new TabbedPane();
+ tabs.add(msg("proGuardTab"), proGuardPanel);
+ tabs.add(msg("inputOutputTab"), inputOutputPanel);
+ tabs.add(msg("shrinkingTab"), shrinkingPanel);
+ tabs.add(msg("obfuscationTab"), obfuscationPanel);
+ tabs.add(msg("optimizationTab"), optimizationPanel);
+ tabs.add(msg("informationTab"), optionsPanel);
+ tabs.add(msg("processTab"), processPanel);
+ tabs.add(msg("reTraceTab"), reTracePanel);
+ tabs.addImage(Toolkit.getDefaultToolkit().getImage(
+ this.getClass().getResource(TITLE_IMAGE_FILE)));
+
+ // Add the bottom buttons to each panel.
+ proGuardPanel .add(Box.createGlue(), glueConstraints);
+ proGuardPanel .add(tip(loadButton, "loadConfigurationTip"), bottomButtonConstraints);
+ proGuardPanel .add(createNextButton(tabs), lastBottomButtonConstraints);
+
+ inputOutputPanel .add(Box.createGlue(), glueConstraints);
+ inputOutputPanel .add(createPreviousButton(tabs), bottomButtonConstraints);
+ inputOutputPanel .add(createNextButton(tabs), lastBottomButtonConstraints);
+
+ shrinkingPanel .add(Box.createGlue(), glueConstraints);
+ shrinkingPanel .add(createPreviousButton(tabs), bottomButtonConstraints);
+ shrinkingPanel .add(createNextButton(tabs), lastBottomButtonConstraints);
+
+ obfuscationPanel .add(Box.createGlue(), glueConstraints);
+ obfuscationPanel .add(createPreviousButton(tabs), bottomButtonConstraints);
+ obfuscationPanel .add(createNextButton(tabs), lastBottomButtonConstraints);
+
+ optimizationPanel .add(Box.createGlue(), glueConstraints);
+ optimizationPanel .add(createPreviousButton(tabs), bottomButtonConstraints);
+ optimizationPanel .add(createNextButton(tabs), lastBottomButtonConstraints);
+
+ optionsPanel .add(Box.createGlue(), glueConstraints);
+ optionsPanel .add(createPreviousButton(tabs), bottomButtonConstraints);
+ optionsPanel .add(createNextButton(tabs), lastBottomButtonConstraints);
+
+ processPanel .add(Box.createGlue(), glueConstraints);
+ processPanel .add(createPreviousButton(tabs), bottomButtonConstraints);
+ processPanel .add(tip(viewButton, "viewConfigurationTip"), bottomButtonConstraints);
+ processPanel .add(tip(saveButton, "saveConfigurationTip"), bottomButtonConstraints);
+ processPanel .add(tip(processButton, "processTip"), lastBottomButtonConstraints);
+
+ reTracePanel .add(Box.createGlue(), glueConstraints);
+ reTracePanel .add(tip(loadStackTraceButton, "loadStackTraceTip"), bottomButtonConstraints);
+ reTracePanel .add(tip(reTraceButton, "reTraceTip"), lastBottomButtonConstraints);
+
+ // Add the main tabs to the frame.
+ getContentPane().add(tabs);
+
+ // Pack the entire GUI before setting some default values.
+ pack();
+
+ // Initialize the GUI settings to reasonable defaults.
+ loadConfiguration(this.getClass().getResource(DEFAULT_CONFIGURATION));
+ }
+
+
+ public void startSplash()
+ {
+ splashPanel.start();
+ }
+
+
+ public void skipSplash()
+ {
+ splashPanel.stop();
+ }
+
+
+ /**
+ * Loads the boilerplate keep class options from the boilerplate file
+ * into the boilerplate array.
+ */
+ private void loadBoilerplateConfiguration()
+ {
+ try
+ {
+ // Parse the boilerplate configuration file.
+ ConfigurationParser parser = new ConfigurationParser(
+ this.getClass().getResource(BOILERPLATE_CONFIGURATION),
+ System.getProperties());
+
+ Configuration configuration = new Configuration();
+
+ try
+ {
+ parser.parse(configuration);
+
+ // We're interested in the keep options.
+ boilerplateKeep =
+ extractKeepSpecifications(configuration.keep, false, false);
+
+ // We're interested in the keep options.
+ boilerplateKeepNames =
+ extractKeepSpecifications(configuration.keep, true, false);
+
+ // We're interested in the side effects options.
+ boilerplateNoSideEffectMethods = new ClassSpecification[configuration.assumeNoSideEffects.size()];
+ configuration.assumeNoSideEffects.toArray(boilerplateNoSideEffectMethods);
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Returns an array containing the ClassSpecifications instances with
+ * matching flags.
+ */
+ private KeepClassSpecification[] extractKeepSpecifications(List keepSpecifications,
+ boolean allowShrinking,
+ boolean allowObfuscation)
+ {
+ List matches = new ArrayList();
+
+ for (int index = 0; index < keepSpecifications.size(); index++)
+ {
+ KeepClassSpecification keepClassSpecification = (KeepClassSpecification)keepSpecifications.get(index);
+ if (keepClassSpecification.allowShrinking == allowShrinking &&
+ keepClassSpecification.allowObfuscation == allowObfuscation)
+ {
+ matches.add(keepClassSpecification);
+ }
+ }
+
+ KeepClassSpecification[] matchingKeepClassSpecifications = new KeepClassSpecification[matches.size()];
+ matches.toArray(matchingKeepClassSpecifications);
+
+ return matchingKeepClassSpecifications;
+ }
+
+
+ /**
+ * Returns an array containing the ClassSpecification instances of the
+ * given array of KeepClassSpecification instances.
+ */
+ private ClassSpecification[] extractClassSpecifications(KeepClassSpecification[] keepClassSpecifications)
+ {
+ ClassSpecification[] classSpecifications = new ClassSpecification[keepClassSpecifications.length];
+
+ for (int index = 0; index < classSpecifications.length; index++)
+ {
+ classSpecifications[index] = keepClassSpecifications[index];
+ }
+
+ return classSpecifications;
+ }
+
+
+ /**
+ * Creates a panel with the given boiler plate class specifications.
+ */
+ private void addClassSpecifications(ClassSpecification[] boilerplateClassSpecifications,
+ JPanel classSpecificationsPanel,
+ JCheckBox[] boilerplateCheckBoxes,
+ JTextField[] boilerplateTextFields)
+ {
+ // Create some constraints that can be reused.
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.anchor = GridBagConstraints.WEST;
+ constraints.insets = new Insets(0, 4, 0, 4);
+
+ GridBagConstraints constraintsLastStretch = new GridBagConstraints();
+ constraintsLastStretch.gridwidth = GridBagConstraints.REMAINDER;
+ constraintsLastStretch.fill = GridBagConstraints.HORIZONTAL;
+ constraintsLastStretch.weightx = 1.0;
+ constraintsLastStretch.anchor = GridBagConstraints.WEST;
+ constraintsLastStretch.insets = constraints.insets;
+
+ GridBagConstraints panelConstraints = new GridBagConstraints();
+ panelConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ panelConstraints.fill = GridBagConstraints.HORIZONTAL;
+ panelConstraints.weightx = 1.0;
+ panelConstraints.anchor = GridBagConstraints.NORTHWEST;
+ panelConstraints.insets = constraints.insets;
+
+ GridBagLayout layout = new GridBagLayout();
+
+ String lastPanelName = null;
+ JPanel keepSubpanel = null;
+ for (int index = 0; index < boilerplateClassSpecifications.length; index++)
+ {
+ // The panel structure is derived from the comments.
+ String comments = boilerplateClassSpecifications[index].comments;
+ int dashIndex = comments.indexOf('-');
+ int periodIndex = comments.indexOf('.', dashIndex);
+ String panelName = comments.substring(0, dashIndex).trim();
+ String optionName = comments.substring(dashIndex + 1, periodIndex).replace('_', '.').trim();
+ String toolTip = comments.substring(periodIndex + 1);
+ if (keepSubpanel == null || !panelName.equals(lastPanelName))
+ {
+ // Create a new keep subpanel and add it.
+ keepSubpanel = new JPanel(layout);
+ keepSubpanel.setBorder(BorderFactory.createTitledBorder(BORDER, panelName));
+ classSpecificationsPanel.add(keepSubpanel, panelConstraints);
+
+ lastPanelName = panelName;
+ }
+
+ // Add the check box to the subpanel.
+ JCheckBox boilerplateCheckBox = new JCheckBox(optionName);
+ boilerplateCheckBox.setToolTipText(toolTip);
+ boilerplateCheckBoxes[index] = boilerplateCheckBox;
+ keepSubpanel.add(boilerplateCheckBox,
+ boilerplateTextFields != null ?
+ constraints :
+ constraintsLastStretch);
+
+ if (boilerplateTextFields != null)
+ {
+ // Add the text field to the subpanel.
+ boilerplateTextFields[index] = new JTextField(40);
+ keepSubpanel.add(tip(boilerplateTextFields[index], "classNamesTip"), constraintsLastStretch);
+ }
+ }
+ }
+
+
+ /**
+ * Adds a standard border with the title that corresponds to the given key
+ * in the GUI resources.
+ */
+ private void addBorder(JComponent component, String titleKey)
+ {
+ Border oldBorder = component.getBorder();
+ Border newBorder = BorderFactory.createTitledBorder(BORDER, msg(titleKey));
+
+ component.setBorder(oldBorder == null ?
+ newBorder :
+ new CompoundBorder(newBorder, oldBorder));
+ }
+
+
+ /**
+ * Creates a Previous button for the given tabbed pane.
+ */
+ private JButton createPreviousButton(final TabbedPane tabbedPane)
+ {
+ JButton browseButton = new JButton(msg("previous"));
+ browseButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ tabbedPane.previous();
+ }
+ });
+
+ return browseButton;
+ }
+
+
+ /**
+ * Creates a Next button for the given tabbed pane.
+ */
+ private JButton createNextButton(final TabbedPane tabbedPane)
+ {
+ JButton browseButton = new JButton(msg("next"));
+ browseButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ tabbedPane.next();
+ }
+ });
+
+ return browseButton;
+ }
+
+
+ /**
+ * Creates a browse button that opens a file browser for the given text field.
+ */
+ private JButton createBrowseButton(final JTextField textField,
+ final String title)
+ {
+ JButton browseButton = new JButton(msg("browse"));
+ browseButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ // Update the file chooser.
+ fileChooser.setDialogTitle(title);
+ fileChooser.setSelectedFile(new File(textField.getText()));
+
+ int returnVal = fileChooser.showDialog(ProGuardGUI.this, msg("ok"));
+ if (returnVal == JFileChooser.APPROVE_OPTION)
+ {
+ // Update the text field.
+ textField.setText(fileChooser.getSelectedFile().getPath());
+ }
+ }
+ });
+
+ return browseButton;
+ }
+
+
+ protected JButton createOptimizationsButton(final JTextField textField)
+ {
+ final OptimizationsDialog optimizationsDialog = new OptimizationsDialog(ProGuardGUI.this);
+
+ JButton optimizationsButton = new JButton(msg("select"));
+ optimizationsButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ // Update the dialog.
+ optimizationsDialog.setFilter(textField.getText());
+
+ int returnValue = optimizationsDialog.showDialog();
+ if (returnValue == OptimizationsDialog.APPROVE_OPTION)
+ {
+ // Update the text field.
+ textField.setText(optimizationsDialog.getFilter());
+ }
+ }
+ });
+
+ return optimizationsButton;
+ }
+
+
+ /**
+ * Sets the preferred sizes of the given components to the maximum of their
+ * current preferred sizes.
+ */
+ private void setCommonPreferredSize(List components)
+ {
+ // Find the maximum preferred size.
+ Dimension maximumSize = null;
+ for (int index = 0; index < components.size(); index++)
+ {
+ JComponent component = (JComponent)components.get(index);
+ Dimension size = component.getPreferredSize();
+ if (maximumSize == null ||
+ size.getWidth() > maximumSize.getWidth())
+ {
+ maximumSize = size;
+ }
+ }
+
+ // Set the size that we found as the preferred size for all components.
+ for (int index = 0; index < components.size(); index++)
+ {
+ JComponent component = (JComponent)components.get(index);
+ component.setPreferredSize(maximumSize);
+ }
+ }
+
+
+ /**
+ * Updates to GUI settings to reflect the given ProGuard configuration.
+ */
+ private void setProGuardConfiguration(Configuration configuration)
+ {
+ // Set up the input and output jars and directories.
+ programPanel.setClassPath(configuration.programJars);
+ libraryPanel.setClassPath(configuration.libraryJars);
+
+ // Set up the boilerplate keep options.
+ for (int index = 0; index < boilerplateKeep.length; index++)
+ {
+ String classNames =
+ findMatchingKeepSpecifications(boilerplateKeep[index],
+ configuration.keep);
+
+ boilerplateKeepCheckBoxes[index].setSelected(classNames != null);
+ boilerplateKeepTextFields[index].setText(classNames == null ? "*" : classNames);
+ }
+
+
+ // Set up the boilerplate keep names options.
+ for (int index = 0; index < boilerplateKeepNames.length; index++)
+ {
+ String classNames =
+ findMatchingKeepSpecifications(boilerplateKeepNames[index],
+ configuration.keep);
+
+ boilerplateKeepNamesCheckBoxes[index].setSelected(classNames != null);
+ boilerplateKeepNamesTextFields[index].setText(classNames == null ? "*" : classNames);
+ }
+
+ // Set up the additional keep options. Note that the matched boilerplate
+ // options have been removed from the list.
+ additionalKeepPanel.setClassSpecifications(filteredKeepSpecifications(configuration.keep,
+ false));
+
+ // Set up the additional keep options. Note that the matched boilerplate
+ // options have been removed from the list.
+ additionalKeepNamesPanel.setClassSpecifications(filteredKeepSpecifications(configuration.keep,
+ true));
+
+
+ // Set up the boilerplate "no side effect methods" options.
+ for (int index = 0; index < boilerplateNoSideEffectMethods.length; index++)
+ {
+ boolean found =
+ findClassSpecification(boilerplateNoSideEffectMethods[index],
+ configuration.assumeNoSideEffects);
+
+ boilerplateNoSideEffectMethodCheckBoxes[index].setSelected(found);
+ }
+
+ // Set up the additional keep options. Note that the matched boilerplate
+ // options have been removed from the list.
+ additionalNoSideEffectsPanel.setClassSpecifications(configuration.assumeNoSideEffects);
+
+ // Set up the "why are you keeping" options.
+ whyAreYouKeepingPanel.setClassSpecifications(configuration.whyAreYouKeeping);
+
+ // Set up the other options.
+ shrinkCheckBox .setSelected(configuration.shrink);
+ printUsageCheckBox .setSelected(configuration.printUsage != null);
+
+ optimizeCheckBox .setSelected(configuration.optimize);
+ allowAccessModificationCheckBox .setSelected(configuration.allowAccessModification);
+ mergeInterfacesAggressivelyCheckBox .setSelected(configuration.mergeInterfacesAggressively);
+ optimizationPassesSpinner.getModel() .setValue(new Integer(configuration.optimizationPasses));
+
+ obfuscateCheckBox .setSelected(configuration.obfuscate);
+ printMappingCheckBox .setSelected(configuration.printMapping != null);
+ applyMappingCheckBox .setSelected(configuration.applyMapping != null);
+ obfuscationDictionaryCheckBox .setSelected(configuration.obfuscationDictionary != null);
+ classObfuscationDictionaryCheckBox .setSelected(configuration.classObfuscationDictionary != null);
+ packageObfuscationDictionaryCheckBox .setSelected(configuration.packageObfuscationDictionary != null);
+ overloadAggressivelyCheckBox .setSelected(configuration.overloadAggressively);
+ useUniqueClassMemberNamesCheckBox .setSelected(configuration.useUniqueClassMemberNames);
+ useMixedCaseClassNamesCheckBox .setSelected(configuration.useMixedCaseClassNames);
+ keepPackageNamesCheckBox .setSelected(configuration.keepPackageNames != null);
+ flattenPackageHierarchyCheckBox .setSelected(configuration.flattenPackageHierarchy != null);
+ repackageClassesCheckBox .setSelected(configuration.repackageClasses != null);
+ keepAttributesCheckBox .setSelected(configuration.keepAttributes != null);
+ keepParameterNamesCheckBox .setSelected(configuration.keepParameterNames);
+ newSourceFileAttributeCheckBox .setSelected(configuration.newSourceFileAttribute != null);
+ adaptClassStringsCheckBox .setSelected(configuration.adaptClassStrings != null);
+ adaptResourceFileNamesCheckBox .setSelected(configuration.adaptResourceFileNames != null);
+ adaptResourceFileContentsCheckBox .setSelected(configuration.adaptResourceFileContents != null);
+
+ preverifyCheckBox .setSelected(configuration.preverify);
+ microEditionCheckBox .setSelected(configuration.microEdition);
+ targetCheckBox .setSelected(configuration.targetClassVersion != 0);
+
+ verboseCheckBox .setSelected(configuration.verbose);
+ noteCheckBox .setSelected(configuration.note == null || !configuration.note.isEmpty());
+ warnCheckBox .setSelected(configuration.warn == null || !configuration.warn.isEmpty());
+ ignoreWarningsCheckBox .setSelected(configuration.ignoreWarnings);
+ skipNonPublicLibraryClassesCheckBox .setSelected(configuration.skipNonPublicLibraryClasses);
+ skipNonPublicLibraryClassMembersCheckBox.setSelected(configuration.skipNonPublicLibraryClassMembers);
+ keepDirectoriesCheckBox .setSelected(configuration.keepDirectories != null);
+ forceProcessingCheckBox .setSelected(configuration.lastModified == Long.MAX_VALUE);
+ printSeedsCheckBox .setSelected(configuration.printSeeds != null);
+ printConfigurationCheckBox .setSelected(configuration.printConfiguration != null);
+ dumpCheckBox .setSelected(configuration.dump != null);
+
+ printUsageTextField .setText(fileName(configuration.printUsage));
+ optimizationsTextField .setText(configuration.optimizations == null ? OPTIMIZATIONS_DEFAULT : ListUtil.commaSeparatedString(configuration.optimizations, true));
+ printMappingTextField .setText(fileName(configuration.printMapping));
+ applyMappingTextField .setText(fileName(configuration.applyMapping));
+ obfuscationDictionaryTextField .setText(fileName(configuration.obfuscationDictionary));
+ classObfuscationDictionaryTextField .setText(fileName(configuration.classObfuscationDictionary));
+ packageObfuscationDictionaryTextField .setText(fileName(configuration.packageObfuscationDictionary));
+ keepPackageNamesTextField .setText(configuration.keepPackageNames == null ? "" : ClassUtil.externalClassName(ListUtil.commaSeparatedString(configuration.keepPackageNames, true)));
+ flattenPackageHierarchyTextField .setText(configuration.flattenPackageHierarchy);
+ repackageClassesTextField .setText(configuration.repackageClasses);
+ keepAttributesTextField .setText(configuration.keepAttributes == null ? KEEP_ATTRIBUTE_DEFAULT : ListUtil.commaSeparatedString(configuration.keepAttributes, true));
+ newSourceFileAttributeTextField .setText(configuration.newSourceFileAttribute == null ? SOURCE_FILE_ATTRIBUTE_DEFAULT : configuration.newSourceFileAttribute);
+ adaptClassStringsTextField .setText(configuration.adaptClassStrings == null ? "" : ClassUtil.externalClassName(ListUtil.commaSeparatedString(configuration.adaptClassStrings, true)));
+ adaptResourceFileNamesTextField .setText(configuration.adaptResourceFileNames == null ? ADAPT_RESOURCE_FILE_NAMES_DEFAULT : ListUtil.commaSeparatedString(configuration.adaptResourceFileNames, true));
+ adaptResourceFileContentsTextField .setText(configuration.adaptResourceFileContents == null ? ADAPT_RESOURCE_FILE_CONTENTS_DEFAULT : ListUtil.commaSeparatedString(configuration.adaptResourceFileContents, true));
+ noteTextField .setText(ListUtil.commaSeparatedString(configuration.note, true));
+ warnTextField .setText(ListUtil.commaSeparatedString(configuration.warn, true));
+ keepDirectoriesTextField .setText(ListUtil.commaSeparatedString(configuration.keepDirectories, true));
+ printSeedsTextField .setText(fileName(configuration.printSeeds));
+ printConfigurationTextField .setText(fileName(configuration.printConfiguration));
+ dumpTextField .setText(fileName(configuration.dump));
+
+ if (configuration.targetClassVersion != 0)
+ {
+ targetComboBox.setSelectedItem(ClassUtil.externalClassVersion(configuration.targetClassVersion));
+ }
+ else
+ {
+ targetComboBox.setSelectedIndex(targetComboBox.getItemCount() - 1);
+ }
+
+ if (configuration.printMapping != null)
+ {
+ reTraceMappingTextField.setText(fileName(configuration.printMapping));
+ }
+ }
+
+
+ /**
+ * Returns the ProGuard configuration that reflects the current GUI settings.
+ */
+ private Configuration getProGuardConfiguration()
+ {
+ Configuration configuration = new Configuration();
+
+ // Get the input and output jars and directories.
+ configuration.programJars = programPanel.getClassPath();
+ configuration.libraryJars = libraryPanel.getClassPath();
+
+ List keep = new ArrayList();
+
+ // Collect the additional keep options.
+ List additionalKeep = additionalKeepPanel.getClassSpecifications();
+ if (additionalKeep != null)
+ {
+ keep.addAll(additionalKeep);
+ }
+
+ // Collect the additional keep names options.
+ List additionalKeepNames = additionalKeepNamesPanel.getClassSpecifications();
+ if (additionalKeepNames != null)
+ {
+ keep.addAll(additionalKeepNames);
+ }
+
+ // Collect the boilerplate keep options.
+ for (int index = 0; index < boilerplateKeep.length; index++)
+ {
+ if (boilerplateKeepCheckBoxes[index].isSelected())
+ {
+ keep.add(classSpecification(boilerplateKeep[index],
+ boilerplateKeepTextFields[index].getText()));
+ }
+ }
+
+ // Collect the boilerplate keep names options.
+ for (int index = 0; index < boilerplateKeepNames.length; index++)
+ {
+ if (boilerplateKeepNamesCheckBoxes[index].isSelected())
+ {
+ keep.add(classSpecification(boilerplateKeepNames[index],
+ boilerplateKeepNamesTextFields[index].getText()));
+ }
+ }
+
+ // Put the list of keep specifications in the configuration.
+ if (keep.size() > 0)
+ {
+ configuration.keep = keep;
+ }
+
+
+ // Collect the boilerplate "no side effect methods" options.
+ List noSideEffectMethods = new ArrayList();
+
+ for (int index = 0; index < boilerplateNoSideEffectMethods.length; index++)
+ {
+ if (boilerplateNoSideEffectMethodCheckBoxes[index].isSelected())
+ {
+ noSideEffectMethods.add(boilerplateNoSideEffectMethods[index]);
+ }
+ }
+
+ // Collect the additional "no side effect methods" options.
+ List additionalNoSideEffectOptions = additionalNoSideEffectsPanel.getClassSpecifications();
+ if (additionalNoSideEffectOptions != null)
+ {
+ noSideEffectMethods.addAll(additionalNoSideEffectOptions);
+ }
+
+ // Put the list of "no side effect methods" options in the configuration.
+ if (noSideEffectMethods.size() > 0)
+ {
+ configuration.assumeNoSideEffects = noSideEffectMethods;
+ }
+
+
+ // Collect the "why are you keeping" options.
+ configuration.whyAreYouKeeping = whyAreYouKeepingPanel.getClassSpecifications();
+
+
+ // Get the other options.
+ configuration.shrink = shrinkCheckBox .isSelected();
+ configuration.printUsage = printUsageCheckBox .isSelected() ? new File(printUsageTextField .getText()) : null;
+
+ configuration.optimize = optimizeCheckBox .isSelected();
+ configuration.allowAccessModification = allowAccessModificationCheckBox .isSelected();
+ configuration.mergeInterfacesAggressively = mergeInterfacesAggressivelyCheckBox .isSelected();
+ configuration.optimizations = optimizationsTextField.getText().length() > 1 ? ListUtil.commaSeparatedList(optimizationsTextField .getText()) : null;
+ configuration.optimizationPasses = ((SpinnerNumberModel)optimizationPassesSpinner.getModel()).getNumber().intValue();
+
+ configuration.obfuscate = obfuscateCheckBox .isSelected();
+ configuration.printMapping = printMappingCheckBox .isSelected() ? new File(printMappingTextField .getText()) : null;
+ configuration.applyMapping = applyMappingCheckBox .isSelected() ? new File(applyMappingTextField .getText()) : null;
+ configuration.obfuscationDictionary = obfuscationDictionaryCheckBox .isSelected() ? new File(obfuscationDictionaryTextField .getText()) : null;
+ configuration.classObfuscationDictionary = classObfuscationDictionaryCheckBox .isSelected() ? new File(classObfuscationDictionaryTextField .getText()) : null;
+ configuration.packageObfuscationDictionary = packageObfuscationDictionaryCheckBox .isSelected() ? new File(packageObfuscationDictionaryTextField .getText()) : null;
+ configuration.overloadAggressively = overloadAggressivelyCheckBox .isSelected();
+ configuration.useUniqueClassMemberNames = useUniqueClassMemberNamesCheckBox .isSelected();
+ configuration.useMixedCaseClassNames = useMixedCaseClassNamesCheckBox .isSelected();
+ configuration.keepPackageNames = keepPackageNamesCheckBox .isSelected() ? keepPackageNamesTextField.getText().length() > 0 ? ListUtil.commaSeparatedList(ClassUtil.internalClassName(keepPackageNamesTextField.getText())) : new ArrayList() : null;
+ configuration.flattenPackageHierarchy = flattenPackageHierarchyCheckBox .isSelected() ? ClassUtil.internalClassName(flattenPackageHierarchyTextField .getText()) : null;
+ configuration.repackageClasses = repackageClassesCheckBox .isSelected() ? ClassUtil.internalClassName(repackageClassesTextField .getText()) : null;
+ configuration.keepAttributes = keepAttributesCheckBox .isSelected() ? ListUtil.commaSeparatedList(keepAttributesTextField .getText()) : null;
+ configuration.keepParameterNames = keepParameterNamesCheckBox .isSelected();
+ configuration.newSourceFileAttribute = newSourceFileAttributeCheckBox .isSelected() ? newSourceFileAttributeTextField .getText() : null;
+ configuration.adaptClassStrings = adaptClassStringsCheckBox .isSelected() ? adaptClassStringsTextField.getText().length() > 0 ? ListUtil.commaSeparatedList(ClassUtil.internalClassName(adaptClassStringsTextField.getText())) : new ArrayList() : null;
+ configuration.adaptResourceFileNames = adaptResourceFileNamesCheckBox .isSelected() ? ListUtil.commaSeparatedList(adaptResourceFileNamesTextField .getText()) : null;
+ configuration.adaptResourceFileContents = adaptResourceFileContentsCheckBox .isSelected() ? ListUtil.commaSeparatedList(adaptResourceFileContentsTextField .getText()) : null;
+
+ configuration.preverify = preverifyCheckBox .isSelected();
+ configuration.microEdition = microEditionCheckBox .isSelected();
+ configuration.targetClassVersion = targetCheckBox .isSelected() ? ClassUtil.internalClassVersion(targetComboBox.getSelectedItem().toString()) : 0;
+
+ configuration.verbose = verboseCheckBox .isSelected();
+ configuration.note = noteCheckBox .isSelected() ? noteTextField.getText().length() > 0 ? ListUtil.commaSeparatedList(ClassUtil.internalClassName(noteTextField.getText())) : null : new ArrayList();
+ configuration.warn = warnCheckBox .isSelected() ? warnTextField.getText().length() > 0 ? ListUtil.commaSeparatedList(ClassUtil.internalClassName(warnTextField.getText())) : null : new ArrayList();
+ configuration.ignoreWarnings = ignoreWarningsCheckBox .isSelected();
+ configuration.skipNonPublicLibraryClasses = skipNonPublicLibraryClassesCheckBox .isSelected();
+ configuration.skipNonPublicLibraryClassMembers = skipNonPublicLibraryClassMembersCheckBox.isSelected();
+ configuration.keepDirectories = keepDirectoriesCheckBox .isSelected() ? keepDirectoriesTextField.getText().length() > 0 ? ListUtil.commaSeparatedList(ClassUtil.internalClassName(keepDirectoriesTextField.getText())) : new ArrayList() : null;
+ configuration.lastModified = forceProcessingCheckBox .isSelected() ? Long.MAX_VALUE : System.currentTimeMillis();
+ configuration.printSeeds = printSeedsCheckBox .isSelected() ? new File(printSeedsTextField .getText()) : null;
+ configuration.printConfiguration = printConfigurationCheckBox .isSelected() ? new File(printConfigurationTextField .getText()) : null;
+ configuration.dump = dumpCheckBox .isSelected() ? new File(dumpTextField .getText()) : null;
+
+ return configuration;
+ }
+
+
+ /**
+ * Looks in the given list for a class specification that is identical to
+ * the given template. Returns true if it is found, and removes the matching
+ * class specification as a side effect.
+ */
+ private boolean findClassSpecification(ClassSpecification classSpecificationTemplate,
+ List classSpecifications)
+ {
+ if (classSpecifications == null)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < classSpecifications.size(); index++)
+ {
+ if (classSpecificationTemplate.equals(classSpecifications.get(index)))
+ {
+ // Remove the matching option as a side effect.
+ classSpecifications.remove(index);
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns the subset of the given list of keep specifications, with
+ * matching shrinking flag.
+ */
+ private List filteredKeepSpecifications(List keepSpecifications,
+ boolean allowShrinking)
+ {
+ List filteredKeepSpecifications = new ArrayList();
+
+ for (int index = 0; index < keepSpecifications.size(); index++)
+ {
+ KeepClassSpecification keepClassSpecification =
+ (KeepClassSpecification)keepSpecifications.get(index);
+
+ if (keepClassSpecification.allowShrinking == allowShrinking)
+ {
+ filteredKeepSpecifications.add(keepClassSpecification);
+ }
+ }
+
+ return filteredKeepSpecifications;
+ }
+
+
+ /**
+ * Looks in the given list for keep specifications that match the given
+ * template. Returns a comma-separated string of class names from
+ * matching keep specifications, and removes the matching keep
+ * specifications as a side effect.
+ */
+ private String findMatchingKeepSpecifications(KeepClassSpecification keepClassSpecificationTemplate,
+ List keepSpecifications)
+ {
+ if (keepSpecifications == null)
+ {
+ return null;
+ }
+
+ StringBuffer buffer = null;
+
+ for (int index = 0; index < keepSpecifications.size(); index++)
+ {
+ KeepClassSpecification listedKeepClassSpecification =
+ (KeepClassSpecification)keepSpecifications.get(index);
+ String className = listedKeepClassSpecification.className;
+ keepClassSpecificationTemplate.className = className;
+ if (keepClassSpecificationTemplate.equals(listedKeepClassSpecification))
+ {
+ if (buffer == null)
+ {
+ buffer = new StringBuffer();
+ }
+ else
+ {
+ buffer.append(',');
+ }
+ buffer.append(className == null ? "*" : ClassUtil.externalClassName(className));
+
+ // Remove the matching option as a side effect.
+ keepSpecifications.remove(index--);
+ }
+ }
+
+ return buffer == null ? null : buffer.toString();
+ }
+
+
+ /**
+ * Returns a class specification or keep specification, based on the given
+ * template and the class name to be filled in.
+ */
+ private ClassSpecification classSpecification(ClassSpecification classSpecificationTemplate,
+ String className)
+ {
+ // Create a copy of the template.
+ ClassSpecification classSpecification =
+ (ClassSpecification)classSpecificationTemplate.clone();
+
+ // Set the class name in the copy.
+ classSpecification.className =
+ className.equals("") ||
+ className.equals("*") ?
+ null :
+ ClassUtil.internalClassName(className);
+
+ // Return the modified copy.
+ return classSpecification;
+ }
+
+
+ // Methods and internal classes related to actions.
+
+ /**
+ * Loads the given ProGuard configuration into the GUI.
+ */
+ private void loadConfiguration(File file)
+ {
+ // Set the default directory and file in the file choosers.
+ configurationChooser.setSelectedFile(file.getAbsoluteFile());
+ fileChooser.setCurrentDirectory(file.getAbsoluteFile().getParentFile());
+
+ try
+ {
+ // Parse the configuration file.
+ ConfigurationParser parser = new ConfigurationParser(file,
+ System.getProperties());
+
+ Configuration configuration = new Configuration();
+
+ try
+ {
+ parser.parse(configuration);
+
+ // Let the GUI reflect the configuration.
+ setProGuardConfiguration(configuration);
+ }
+ catch (ParseException ex)
+ {
+ JOptionPane.showMessageDialog(getContentPane(),
+ msg("cantParseConfigurationFile", file.getPath()),
+ msg("warning"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ catch (IOException ex)
+ {
+ JOptionPane.showMessageDialog(getContentPane(),
+ msg("cantOpenConfigurationFile", file.getPath()),
+ msg("warning"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+
+ /**
+ * Loads the given ProGuard configuration into the GUI.
+ */
+ private void loadConfiguration(URL url)
+ {
+ try
+ {
+ // Parse the configuration file.
+ ConfigurationParser parser = new ConfigurationParser(url,
+ System.getProperties());
+
+ Configuration configuration = new Configuration();
+
+ try
+ {
+ parser.parse(configuration);
+
+ // Let the GUI reflect the configuration.
+ setProGuardConfiguration(configuration);
+ }
+ catch (ParseException ex)
+ {
+ JOptionPane.showMessageDialog(getContentPane(),
+ msg("cantParseConfigurationFile", url),
+ msg("warning"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ catch (IOException ex)
+ {
+ JOptionPane.showMessageDialog(getContentPane(),
+ msg("cantOpenConfigurationFile", url),
+ msg("warning"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+
+ /**
+ * Saves the current ProGuard configuration to the given file.
+ */
+ private void saveConfiguration(File file)
+ {
+ try
+ {
+ // Save the configuration file.
+ ConfigurationWriter writer = new ConfigurationWriter(file);
+
+ try
+ {
+ writer.write(getProGuardConfiguration());
+ }
+ finally
+ {
+ writer.close();
+ }
+ }
+ catch (Exception ex)
+ {
+ JOptionPane.showMessageDialog(getContentPane(),
+ msg("cantSaveConfigurationFile", file.getPath()),
+ msg("warning"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+
+ /**
+ * Loads the given stack trace into the GUI.
+ */
+ private void loadStackTrace(File file)
+ {
+ try
+ {
+ StringBuffer buffer = new StringBuffer(1024);
+
+ Reader reader = new BufferedReader(new FileReader(file));
+ try
+ {
+ while (true)
+ {
+ int c = reader.read();
+ if (c < 0)
+ {
+ break;
+ }
+
+ buffer.append(c);
+ }
+ }
+ finally
+ {
+ reader.close();
+ }
+
+ // Put the stack trace in the text area.
+ stackTraceTextArea.setText(buffer.toString());
+ }
+ catch (IOException ex)
+ {
+ JOptionPane.showMessageDialog(getContentPane(),
+ msg("cantOpenStackTraceFile", fileName(file)),
+ msg("warning"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+
+ /**
+ * This ActionListener loads a ProGuard configuration file and initializes
+ * the GUI accordingly.
+ */
+ private class MyLoadConfigurationActionListener implements ActionListener
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ configurationChooser.setDialogTitle(msg("selectConfigurationFile"));
+
+ int returnValue = configurationChooser.showOpenDialog(ProGuardGUI.this);
+ if (returnValue == JFileChooser.APPROVE_OPTION)
+ {
+ loadConfiguration(configurationChooser.getSelectedFile());
+ }
+ }
+ }
+
+
+ /**
+ * This ActionListener saves a ProGuard configuration file based on the
+ * current GUI settings.
+ */
+ private class MySaveConfigurationActionListener implements ActionListener
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ configurationChooser.setDialogTitle(msg("saveConfigurationFile"));
+
+ int returnVal = configurationChooser.showSaveDialog(ProGuardGUI.this);
+ if (returnVal == JFileChooser.APPROVE_OPTION)
+ {
+ saveConfiguration(configurationChooser.getSelectedFile());
+ }
+ }
+ }
+
+
+ /**
+ * This ActionListener displays the ProGuard configuration specified by the
+ * current GUI settings.
+ */
+ private class MyViewConfigurationActionListener implements ActionListener
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ // Make sure System.out has not been redirected yet.
+ if (!systemOutRedirected)
+ {
+ consoleTextArea.setText("");
+
+ TextAreaOutputStream outputStream =
+ new TextAreaOutputStream(consoleTextArea);
+
+ try
+ {
+ // TODO: write out relative path names and path names with system properties.
+
+ // Write the configuration.
+ ConfigurationWriter writer = new ConfigurationWriter(outputStream);
+ try
+ {
+ writer.write(getProGuardConfiguration());
+ }
+ finally
+ {
+ writer.close();
+ }
+ }
+ catch (IOException ex)
+ {
+ // This shouldn't happen.
+ }
+
+ // Scroll to the top of the configuration.
+ consoleTextArea.setCaretPosition(0);
+ }
+ }
+ }
+
+
+ /**
+ * This ActionListener executes ProGuard based on the current GUI settings.
+ */
+ private class MyProcessActionListener implements ActionListener
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ // Make sure System.out has not been redirected yet.
+ if (!systemOutRedirected)
+ {
+ systemOutRedirected = true;
+
+ // Get the informational configuration file name.
+ File configurationFile = configurationChooser.getSelectedFile();
+ String configurationFileName = configurationFile != null ?
+ configurationFile.getName() :
+ msg("sampleConfigurationFileName");
+
+ // Create the ProGuard thread.
+ Thread proGuardThread =
+ new Thread(new ProGuardRunnable(consoleTextArea,
+ getProGuardConfiguration(),
+ configurationFileName));
+
+ // Run it.
+ proGuardThread.start();
+ }
+ }
+ }
+
+
+ /**
+ * This ActionListener loads an obfuscated stack trace from a file and puts
+ * it in the proper text area.
+ */
+ private class MyLoadStackTraceActionListener implements ActionListener
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ fileChooser.setDialogTitle(msg("selectStackTraceFile"));
+ fileChooser.setSelectedFile(null);
+
+ int returnValue = fileChooser.showOpenDialog(ProGuardGUI.this);
+ if (returnValue == JFileChooser.APPROVE_OPTION)
+ {
+
+ loadStackTrace(fileChooser.getSelectedFile());
+ }
+ }
+ }
+
+
+ /**
+ * This ActionListener executes ReTrace based on the current GUI settings.
+ */
+ private class MyReTraceActionListener implements ActionListener
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ // Make sure System.out has not been redirected yet.
+ if (!systemOutRedirected)
+ {
+ systemOutRedirected = true;
+
+ boolean verbose = reTraceVerboseCheckBox.isSelected();
+ File retraceMappingFile = new File(reTraceMappingTextField.getText());
+ String stackTrace = stackTraceTextArea.getText();
+
+ // Create the ReTrace runnable.
+ Runnable reTraceRunnable = new ReTraceRunnable(reTraceTextArea,
+ verbose,
+ retraceMappingFile,
+ stackTrace);
+
+ // Run it in this thread, because it won't take long anyway.
+ reTraceRunnable.run();
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the canonical file name for the given file, or the empty string
+ * if the file name is empty.
+ */
+ private String fileName(File file)
+ {
+ if (file == null)
+ {
+ return "";
+ }
+ else
+ {
+ try
+ {
+ return file.getCanonicalPath();
+ }
+ catch (IOException ex)
+ {
+ return file.getPath();
+ }
+ }
+ }
+
+
+ /**
+ * Attaches the tool tip from the GUI resources that corresponds to the
+ * given key, to the given component.
+ */
+ private static JComponent tip(JComponent component, String messageKey)
+ {
+ component.setToolTipText(msg(messageKey));
+
+ return component;
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private static String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key and argument.
+ */
+ private String msg(String messageKey,
+ Object messageArgument)
+ {
+ return GUIResources.getMessage(messageKey, new Object[] {messageArgument});
+ }
+
+
+ /**
+ * The main method for the ProGuard GUI.
+ */
+ public static void main(final String[] args)
+ {
+ try
+ {
+ SwingUtil.invokeAndWait(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ ProGuardGUI gui = new ProGuardGUI();
+
+ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension guiSize = gui.getSize();
+ gui.setLocation((screenSize.width - guiSize.width) / 2,
+ (screenSize.height - guiSize.height) / 2);
+ gui.show();
+
+ // Start the splash animation, unless specified otherwise.
+ int argIndex = 0;
+ if (argIndex < args.length &&
+ NO_SPLASH_OPTION.startsWith(args[argIndex]))
+ {
+ gui.skipSplash();
+ argIndex++;
+ }
+ else
+ {
+ gui.startSplash();
+ }
+
+ // Load an initial configuration, if specified.
+ if (argIndex < args.length)
+ {
+ gui.loadConfiguration(new File(args[argIndex]));
+ argIndex++;
+ }
+
+ if (argIndex < args.length)
+ {
+ System.out.println(gui.getClass().getName() + ": ignoring extra arguments [" + args[argIndex] + "...]");
+ }
+ }
+ catch (Exception e)
+ {
+ System.out.println("Internal problem starting the ProGuard GUI (" + e.getMessage() + ")");
+ }
+ }
+ });
+ }
+ catch (Exception e)
+ {
+ System.out.println("Internal problem starting the ProGuard GUI (" + e.getMessage() + ")");
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ProGuardRunnable.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ProGuardRunnable.java
new file mode 100644
index 0000000000..2f2a1d643f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ProGuardRunnable.java
@@ -0,0 +1,154 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import proguard.*;
+
+import javax.swing.*;
+import java.awt.*;
+import java.io.PrintStream;
+
+
+/**
+ * This <code>Runnable</code> runs ProGuard, sending console output to a text
+ * area and any exceptions to message dialogs.
+ *
+ * @see ProGuard
+ * @author Eric Lafortune
+ */
+final class ProGuardRunnable implements Runnable
+{
+ private final JTextArea consoleTextArea;
+ private final Configuration configuration;
+ private final String configurationFileName;
+
+
+ /**
+ * Creates a new ProGuardRunnable object.
+ * @param consoleTextArea the text area to send the console output to.
+ * @param configuration the ProGuard configuration.
+ * @param configurationFileName the optional file name of the configuration,
+ * for informational purposes.
+ */
+ public ProGuardRunnable(JTextArea consoleTextArea,
+ Configuration configuration,
+ String configurationFileName)
+ {
+ this.consoleTextArea = consoleTextArea;
+ this.configuration = configuration;
+ this.configurationFileName = configurationFileName;
+ }
+
+
+ // Implementation for Runnable.
+
+ public void run()
+ {
+ consoleTextArea.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+ consoleTextArea.setText("");
+
+ // Redirect the System's out and err streams to the console text area.
+ PrintStream oldOut = System.out;
+ PrintStream oldErr = System.err;
+
+ PrintStream printStream =
+ new PrintStream(new TextAreaOutputStream(consoleTextArea), true);
+
+ System.setOut(printStream);
+ System.setErr(printStream);
+
+ try
+ {
+ // Create a new ProGuard object with the GUI's configuration.
+ ProGuard proGuard = new ProGuard(configuration);
+
+ // Run it.
+ proGuard.execute();
+
+ // Print out the completion message.
+ System.out.println("Processing completed successfully");
+ }
+ catch (Exception ex)
+ {
+ //ex.printStackTrace();
+
+ // Print out the exception message.
+ System.out.println(ex.getMessage());
+
+ // Show a dialog as well.
+ MessageDialogRunnable.showMessageDialog(consoleTextArea,
+ ex.getMessage(),
+ msg("errorProcessing"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ catch (OutOfMemoryError er)
+ {
+ // Forget about the ProGuard object as quickly as possible.
+ System.gc();
+
+ // Print out a message suggesting what to do next.
+ System.out.println(msg("outOfMemoryInfo", configurationFileName));
+
+ // Show a dialog as well.
+ MessageDialogRunnable.showMessageDialog(consoleTextArea,
+ msg("outOfMemory"),
+ msg("errorProcessing"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ finally
+ {
+ // Make sure all output has been sent to the console text area.
+ printStream.close();
+
+ // Restore the old System's out and err streams.
+ System.setOut(oldOut);
+ System.setErr(oldErr);
+ }
+
+ consoleTextArea.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+
+ // Reset the global static redirection lock.
+ ProGuardGUI.systemOutRedirected = false;
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key and argument.
+ */
+ private String msg(String messageKey,
+ Object messageArgument)
+ {
+ return GUIResources.getMessage(messageKey, new Object[] {messageArgument});
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ReTraceRunnable.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ReTraceRunnable.java
new file mode 100644
index 0000000000..90a2a093bd
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/ReTraceRunnable.java
@@ -0,0 +1,125 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import proguard.retrace.ReTrace;
+
+import javax.swing.*;
+import java.awt.*;
+import java.io.*;
+
+
+/**
+ * This <code>Runnable</code> runs ReTrace, sending the output to a text
+ * area and any exceptions to message dialogs.
+ *
+ * @see ReTrace
+ * @author Eric Lafortune
+ */
+final class ReTraceRunnable implements Runnable
+{
+ private final JTextArea consoleTextArea;
+ private final boolean verbose;
+ private final File mappingFile;
+ private final String stackTrace;
+
+
+ /**
+ * Creates a new ReTraceRunnable.
+ * @param consoleTextArea the text area to send the console output to.
+ * @param verbose specifies whether the de-obfuscated stack trace
+ * should be verbose.
+ * @param mappingFile the mapping file that was written out by ProGuard.
+ */
+ public ReTraceRunnable(JTextArea consoleTextArea,
+ boolean verbose,
+ File mappingFile,
+ String stackTrace)
+ {
+ this.consoleTextArea = consoleTextArea;
+ this.verbose = verbose;
+ this.mappingFile = mappingFile;
+ this.stackTrace = stackTrace;
+ }
+
+
+ // Implementation for Runnable.
+
+ public void run()
+ {
+ consoleTextArea.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+ consoleTextArea.setText("");
+
+ LineNumberReader reader =
+ new LineNumberReader(
+ new CharArrayReader(stackTrace.toCharArray()));
+
+ PrintWriter writer =
+ new PrintWriter(new TextAreaWriter(consoleTextArea), true);
+
+ try
+ {
+ // Execute ReTrace with the collected settings.
+ new ReTrace(ReTrace.STACK_TRACE_EXPRESSION, verbose, mappingFile)
+ .retrace(reader, writer);
+ }
+ catch (Exception ex)
+ {
+ // Print out the exception message.
+ System.out.println(ex.getMessage());
+
+ // Show a dialog as well.
+ MessageDialogRunnable.showMessageDialog(consoleTextArea,
+ ex.getMessage(),
+ msg("errorReTracing"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ catch (OutOfMemoryError er)
+ {
+ // Forget about the ProGuard object as quickly as possible.
+ System.gc();
+
+ // Print out a message suggesting what to do next.
+ System.out.println(msg("outOfMemory"));
+
+ // Show a dialog as well.
+ MessageDialogRunnable.showMessageDialog(consoleTextArea,
+ msg("outOfMemory"),
+ msg("errorReTracing"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+
+ consoleTextArea.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ consoleTextArea.setCaretPosition(0);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the message from the GUI resources that corresponds to the given
+ * key.
+ */
+ private String msg(String messageKey)
+ {
+ return GUIResources.getMessage(messageKey);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/SwingUtil.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/SwingUtil.java
new file mode 100644
index 0000000000..ac74e31636
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/SwingUtil.java
@@ -0,0 +1,82 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import javax.swing.*;
+import java.lang.reflect.InvocationTargetException;
+
+
+/**
+ * This utility class provides variants of the invocation method from the
+ * <code>SwingUtilities</code> class.
+ *
+ * @see SwingUtilities
+ * @author Eric Lafortune
+ */
+public class SwingUtil
+{
+ /**
+ * Invokes the given Runnable in the AWT event dispatching thread,
+ * and waits for it to finish. This method may be called from any thread,
+ * including the event dispatching thread itself.
+ * @see SwingUtilities#invokeAndWait(Runnable)
+ * @param runnable the Runnable to be executed.
+ */
+ public static void invokeAndWait(Runnable runnable)
+ throws InterruptedException, InvocationTargetException
+ {
+ try
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ runnable.run();
+ }
+ else
+ {
+ SwingUtilities.invokeAndWait(runnable);
+ }
+ }
+ catch (Exception ex)
+ {
+ // Ignore any exceptions.
+ }
+ }
+
+
+ /**
+ * Invokes the given Runnable in the AWT event dispatching thread, not
+ * necessarily right away. This method may be called from any thread,
+ * including the event dispatching thread itself.
+ * @see SwingUtilities#invokeLater(Runnable)
+ * @param runnable the Runnable to be executed.
+ */
+ public static void invokeLater(Runnable runnable)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ runnable.run();
+ }
+ else
+ {
+ SwingUtilities.invokeLater(runnable);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/TabbedPane.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/TabbedPane.java
new file mode 100644
index 0000000000..4ef8703466
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/TabbedPane.java
@@ -0,0 +1,229 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+
+
+/**
+ * This <code>Jpanel</code> is similar to a <code>JTabbedPane</code>.
+ * It uses buttons on the left-hand side to switch between panels.
+ * An image can be added below these buttons.
+ * Some methods are provided to switch between tabs.
+ *
+ * @author Eric Lafortune
+ */
+public class TabbedPane
+ extends JPanel
+{
+ private final CardLayout cardLayout = new CardLayout();
+ private final JPanel cardPanel = new JPanel(cardLayout);
+ private final ButtonGroup buttonGroup = new ButtonGroup();
+
+
+ /**
+ * Creates a new TabbedPane.
+ */
+ public TabbedPane()
+ {
+ GridBagLayout layout = new GridBagLayout();
+ setLayout(layout);
+
+ GridBagConstraints cardConstraints = new GridBagConstraints();
+ cardConstraints.gridx = 1;
+ cardConstraints.gridy = 0;
+ cardConstraints.gridheight = GridBagConstraints.REMAINDER;
+ cardConstraints.fill = GridBagConstraints.BOTH;
+ cardConstraints.weightx = 1.0;
+ cardConstraints.weighty = 1.0;
+ cardConstraints.anchor = GridBagConstraints.NORTHWEST;
+
+ add(cardPanel, cardConstraints);
+ }
+
+
+ /**
+ * Adds a component with a given title to the tabbed pane.
+ *
+ * @param title the title that will be used in the tab button.
+ * @param component the component that will be added as a tab.
+ */
+ public Component add(final String title, Component component)
+ {
+ GridBagConstraints buttonConstraints = new GridBagConstraints();
+ buttonConstraints.gridx = 0;
+ buttonConstraints.fill = GridBagConstraints.HORIZONTAL;
+ buttonConstraints.anchor = GridBagConstraints.NORTHWEST;
+ buttonConstraints.ipadx = 10;
+ buttonConstraints.ipady = 4;
+
+ JToggleButton button = new JToggleButton(title);
+
+ // Let the button react on the mouse press, instead of waiting for the
+ // mouse release.
+ button.setModel(new JToggleButton.ToggleButtonModel()
+ {
+ public void setPressed(boolean b)
+ {
+ if ((isPressed() == b) || !isEnabled())
+ {
+ return;
+ }
+
+ if (!b && isArmed())
+ {
+ setSelected(!this.isSelected());
+ }
+
+ if (b)
+ {
+ stateMask |= PRESSED;
+ }
+ else
+ {
+ stateMask &= ~PRESSED;
+ }
+
+ fireStateChanged();
+
+ if (isPressed())
+ {
+ fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, getActionCommand()));
+ }
+ }
+
+ });
+
+ // Switch to the tab on a button press.
+ button.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ cardLayout.show(cardPanel, title);
+ }
+ });
+
+ // Only one button can be selected at the same time.
+ buttonGroup.add(button);
+
+ // If this is the first tab, make sure its button is selected.
+ if (cardPanel.getComponentCount() == 0)
+ {
+ button.setSelected(true);
+ }
+
+ // Add the button and its panel.
+ add(button, buttonConstraints);
+ cardPanel.add(title, component);
+
+ return component;
+ }
+
+
+ /**
+ * Adds an image below the tab buttons, after all tabs have been added.
+ * The image will only be as visible as permitted by the available space.
+ *
+ * @param image the image.
+ * @return the component containing the image.
+ */
+ public Component addImage(final Image image)
+ {
+ GridBagConstraints imageConstraints = new GridBagConstraints();
+ imageConstraints.gridx = 0;
+ imageConstraints.weighty = 1.0;
+ imageConstraints.fill = GridBagConstraints.BOTH;
+ imageConstraints.anchor = GridBagConstraints.SOUTHWEST;
+
+ JButton component = new JButton(new ImageIcon(image));
+ component.setFocusPainted(false);
+ component.setFocusable(false);
+ component.setRequestFocusEnabled(false);
+ component.setRolloverEnabled(false);
+ component.setMargin(new Insets(0, 0, 0, 0));
+ component.setHorizontalAlignment(JButton.LEFT);
+ component.setVerticalAlignment(JButton.BOTTOM);
+ component.setPreferredSize(new Dimension(0, 0));
+
+ add(component, imageConstraints);
+
+ return component;
+ }
+
+
+ /**
+ * Selects the first tab.
+ */
+ public void first()
+ {
+ cardLayout.first(cardPanel);
+ updateButtonSelection();
+ }
+
+
+ /**
+ * Selects the last tab.
+ */
+ public void last()
+ {
+ cardLayout.last(cardPanel);
+ updateButtonSelection();
+ }
+
+
+ /**
+ * Selects the previous tab.
+ */
+ public void previous()
+ {
+ cardLayout.previous(cardPanel);
+ updateButtonSelection();
+ }
+
+
+ /**
+ * Selects the next tab.
+ */
+ public void next()
+ {
+ cardLayout.next(cardPanel);
+ updateButtonSelection();
+ }
+
+
+ /**
+ * Lets the button selection reflect the currently visible panel.
+ */
+ private void updateButtonSelection()
+ {
+ int count = cardPanel.getComponentCount();
+ for (int index = 0 ; index < count ; index++) {
+ Component card = cardPanel.getComponent(index);
+ if (card.isShowing())
+ {
+ JToggleButton button = (JToggleButton)getComponent(index+1);
+ button.setSelected(true);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/TextAreaOutputStream.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/TextAreaOutputStream.java
new file mode 100644
index 0000000000..18cac563ec
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/TextAreaOutputStream.java
@@ -0,0 +1,80 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import javax.swing.*;
+import java.io.*;
+
+
+/**
+ * This <code>PrintStream</code> appends its output to a given text area.
+ *
+ * @author Eric Lafortune
+ */
+final class TextAreaOutputStream extends FilterOutputStream implements Runnable
+{
+ private final JTextArea textArea;
+
+
+ public TextAreaOutputStream(JTextArea textArea)
+ {
+ super(new ByteArrayOutputStream());
+
+ this.textArea = textArea;
+ }
+
+
+ // Implementation for FilterOutputStream.
+
+ public void flush() throws IOException
+ {
+ super.flush();
+
+ try
+ {
+ // Append the accumulated buffer contents to the text area.
+ SwingUtil.invokeAndWait(this);
+ }
+ catch (Exception e)
+ {
+ // Nothing.
+ }
+ }
+
+
+ // Implementation for Runnable.
+
+ public void run()
+ {
+ ByteArrayOutputStream out = (ByteArrayOutputStream)super.out;
+
+ // Has any new text been written?
+ String text = out.toString();
+ if (text.length() > 0)
+ {
+ // Append the accumulated text to the text area.
+ textArea.append(text);
+
+ // Clear the buffer.
+ out.reset();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/TextAreaWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/TextAreaWriter.java
new file mode 100644
index 0000000000..9915e27450
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/TextAreaWriter.java
@@ -0,0 +1,80 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui;
+
+import javax.swing.*;
+import java.io.*;
+
+
+/**
+ * This writer appends its output to a given text area.
+ *
+ * @author Eric Lafortune
+ */
+final class TextAreaWriter extends FilterWriter implements Runnable
+{
+ private final JTextArea textArea;
+
+
+ public TextAreaWriter(JTextArea textArea)
+ {
+ super(new CharArrayWriter());
+
+ this.textArea = textArea;
+ }
+
+
+ // Implementation for FilterWriter.
+
+ public void flush() throws IOException
+ {
+ super.flush();
+
+ try
+ {
+ // Append the accumulated buffer contents to the text area.
+ SwingUtil.invokeAndWait(this);
+ }
+ catch (Exception e)
+ {
+ // Nothing.
+ }
+ }
+
+
+ // Implementation for Runnable.
+
+ public void run()
+ {
+ CharArrayWriter writer = (CharArrayWriter)super.out;
+
+ // Has any new text been written?
+ String text = writer.toString();
+ if (text.length() > 0)
+ {
+ // Append the accumulated text to the text area.
+ textArea.append(text);
+
+ // Clear the buffer.
+ writer.reset();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/arrow.gif b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/arrow.gif
new file mode 100644
index 0000000000..c58e34ea47
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/arrow.gif
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/boilerplate.pro b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/boilerplate.pro
new file mode 100644
index 0000000000..4b35ac1dd7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/boilerplate.pro
@@ -0,0 +1,384 @@
+# Keep - Applications. Keep all application classes, along with their 'main'
+# methods.
+-keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+}
+
+# Keep - Applets. Keep all extensions of java.applet.Applet.
+-keep public class * extends java.applet.Applet
+
+# Keep - Servlets. Keep all extensions of javax.servlet.Servlet.
+-keep public class * extends javax.servlet.Servlet
+
+# Keep - Midlets. Keep all extensions of javax.microedition.midlet.MIDlet.
+-keep public class * extends javax.microedition.midlet.MIDlet
+
+# Keep - Xlets. Keep all extensions of javax.tv.xlet.Xlet.
+-keep public class * extends javax.tv.xlet.Xlet
+
+# Keep - Library. Keep all public and protected classes, fields, and methods.
+-keep public class * {
+ public protected <fields>;
+ public protected <methods>;
+}
+
+# Also keep - Enumerations. Keep the special static methods that are required in
+# enumeration classes.
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# Also keep - Serialization code. Keep all fields and methods that are used for
+# serialization.
+-keepclassmembers class * extends java.io.Serializable {
+ static final long serialVersionUID;
+ static final java.io.ObjectStreamField[] serialPersistentFields;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+
+# Also keep - BeanInfo classes. Keep all implementations of java.beans.BeanInfo.
+-keep class * implements java.beans.BeanInfo
+
+# Also keep - Bean classes. Keep all specified classes, along with their getters
+# and setters.
+-keep class * {
+ void set*(***);
+ void set*(int,***);
+
+ boolean is*();
+ boolean is*(int);
+
+ *** get*();
+ *** get*(int);
+}
+
+# Also keep - Database drivers. Keep all implementations of java.sql.Driver.
+-keep class * implements java.sql.Driver
+
+# Also keep - Swing UI L&F. Keep all extensions of javax.swing.plaf.ComponentUI,
+# along with the special 'createUI' method.
+-keep class * extends javax.swing.plaf.ComponentUI {
+ public static javax.swing.plaf.ComponentUI createUI(javax.swing.JComponent);
+}
+
+# Also keep - RMI interfaces. Keep all interfaces that extend the
+# java.rmi.Remote interface, and their methods.
+-keep interface * extends java.rmi.Remote {
+ <methods>;
+}
+
+# Also keep - RMI implementations. Keep all implementations of java.rmi.Remote,
+# including any explicit or implicit implementations of Activatable, with their
+# two-argument constructors.
+-keep class * implements java.rmi.Remote {
+ <init>(java.rmi.activation.ActivationID,java.rmi.MarshalledObject);
+}
+
+# Keep names - Native method names. Keep all native class/method names.
+-keepclasseswithmembernames,includedescriptorclasses class * {
+ native <methods>;
+}
+
+# Keep names - _class method names. Keep all .class method names. This may be
+# useful for libraries that will be obfuscated again with different obfuscators.
+-keepclassmembernames class * {
+ java.lang.Class class$(java.lang.String);
+ java.lang.Class class$(java.lang.String,boolean);
+}
+
+# Remove - System method calls. Remove all invocations of System
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.System {
+ public static long currentTimeMillis();
+ static java.lang.Class getCallerClass();
+ public static int identityHashCode(java.lang.Object);
+ public static java.lang.SecurityManager getSecurityManager();
+ public static java.util.Properties getProperties();
+ public static java.lang.String getProperty(java.lang.String);
+ public static java.lang.String getenv(java.lang.String);
+ public static java.lang.String mapLibraryName(java.lang.String);
+ public static java.lang.String getProperty(java.lang.String,java.lang.String);
+}
+
+# Remove - Math method calls. Remove all invocations of Math
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.Math {
+ public static double sin(double);
+ public static double cos(double);
+ public static double tan(double);
+ public static double asin(double);
+ public static double acos(double);
+ public static double atan(double);
+ public static double toRadians(double);
+ public static double toDegrees(double);
+ public static double exp(double);
+ public static double log(double);
+ public static double log10(double);
+ public static double sqrt(double);
+ public static double cbrt(double);
+ public static double IEEEremainder(double,double);
+ public static double ceil(double);
+ public static double floor(double);
+ public static double rint(double);
+ public static double atan2(double,double);
+ public static double pow(double,double);
+ public static int round(float);
+ public static long round(double);
+ public static double random();
+ public static int abs(int);
+ public static long abs(long);
+ public static float abs(float);
+ public static double abs(double);
+ public static int max(int,int);
+ public static long max(long,long);
+ public static float max(float,float);
+ public static double max(double,double);
+ public static int min(int,int);
+ public static long min(long,long);
+ public static float min(float,float);
+ public static double min(double,double);
+ public static double ulp(double);
+ public static float ulp(float);
+ public static double signum(double);
+ public static float signum(float);
+ public static double sinh(double);
+ public static double cosh(double);
+ public static double tanh(double);
+ public static double hypot(double,double);
+ public static double expm1(double);
+ public static double log1p(double);
+}
+
+# Remove - Number method calls. Remove all invocations of Number
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.* extends java.lang.Number {
+ public static java.lang.String toString(byte);
+ public static java.lang.Byte valueOf(byte);
+ public static byte parseByte(java.lang.String);
+ public static byte parseByte(java.lang.String,int);
+ public static java.lang.Byte valueOf(java.lang.String,int);
+ public static java.lang.Byte valueOf(java.lang.String);
+ public static java.lang.Byte decode(java.lang.String);
+ public int compareTo(java.lang.Byte);
+
+ public static java.lang.String toString(short);
+ public static short parseShort(java.lang.String);
+ public static short parseShort(java.lang.String,int);
+ public static java.lang.Short valueOf(java.lang.String,int);
+ public static java.lang.Short valueOf(java.lang.String);
+ public static java.lang.Short valueOf(short);
+ public static java.lang.Short decode(java.lang.String);
+ public static short reverseBytes(short);
+ public int compareTo(java.lang.Short);
+
+ public static java.lang.String toString(int,int);
+ public static java.lang.String toHexString(int);
+ public static java.lang.String toOctalString(int);
+ public static java.lang.String toBinaryString(int);
+ public static java.lang.String toString(int);
+ public static int parseInt(java.lang.String,int);
+ public static int parseInt(java.lang.String);
+ public static java.lang.Integer valueOf(java.lang.String,int);
+ public static java.lang.Integer valueOf(java.lang.String);
+ public static java.lang.Integer valueOf(int);
+ public static java.lang.Integer getInteger(java.lang.String);
+ public static java.lang.Integer getInteger(java.lang.String,int);
+ public static java.lang.Integer getInteger(java.lang.String,java.lang.Integer);
+ public static java.lang.Integer decode(java.lang.String);
+ public static int highestOneBit(int);
+ public static int lowestOneBit(int);
+ public static int numberOfLeadingZeros(int);
+ public static int numberOfTrailingZeros(int);
+ public static int bitCount(int);
+ public static int rotateLeft(int,int);
+ public static int rotateRight(int,int);
+ public static int reverse(int);
+ public static int signum(int);
+ public static int reverseBytes(int);
+ public int compareTo(java.lang.Integer);
+
+ public static java.lang.String toString(long,int);
+ public static java.lang.String toHexString(long);
+ public static java.lang.String toOctalString(long);
+ public static java.lang.String toBinaryString(long);
+ public static java.lang.String toString(long);
+ public static long parseLong(java.lang.String,int);
+ public static long parseLong(java.lang.String);
+ public static java.lang.Long valueOf(java.lang.String,int);
+ public static java.lang.Long valueOf(java.lang.String);
+ public static java.lang.Long valueOf(long);
+ public static java.lang.Long decode(java.lang.String);
+ public static java.lang.Long getLong(java.lang.String);
+ public static java.lang.Long getLong(java.lang.String,long);
+ public static java.lang.Long getLong(java.lang.String,java.lang.Long);
+ public static long highestOneBit(long);
+ public static long lowestOneBit(long);
+ public static int numberOfLeadingZeros(long);
+ public static int numberOfTrailingZeros(long);
+ public static int bitCount(long);
+ public static long rotateLeft(long,int);
+ public static long rotateRight(long,int);
+ public static long reverse(long);
+ public static int signum(long);
+ public static long reverseBytes(long);
+ public int compareTo(java.lang.Long);
+
+ public static java.lang.String toString(float);
+ public static java.lang.String toHexString(float);
+ public static java.lang.Float valueOf(java.lang.String);
+ public static java.lang.Float valueOf(float);
+ public static float parseFloat(java.lang.String);
+ public static boolean isNaN(float);
+ public static boolean isInfinite(float);
+ public static int floatToIntBits(float);
+ public static int floatToRawIntBits(float);
+ public static float intBitsToFloat(int);
+ public static int compare(float,float);
+ public boolean isNaN();
+ public boolean isInfinite();
+ public int compareTo(java.lang.Float);
+
+ public static java.lang.String toString(double);
+ public static java.lang.String toHexString(double);
+ public static java.lang.Double valueOf(java.lang.String);
+ public static java.lang.Double valueOf(double);
+ public static double parseDouble(java.lang.String);
+ public static boolean isNaN(double);
+ public static boolean isInfinite(double);
+ public static long doubleToLongBits(double);
+ public static long doubleToRawLongBits(double);
+ public static double longBitsToDouble(long);
+ public static int compare(double,double);
+ public boolean isNaN();
+ public boolean isInfinite();
+ public int compareTo(java.lang.Double);
+
+ public byte byteValue();
+ public short shortValue();
+ public int intValue();
+ public long longValue();
+ public float floatValue();
+ public double doubleValue();
+
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public java.lang.String toString();
+}
+
+# Remove - String method calls. Remove all invocations of String
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.String {
+ public static java.lang.String copyValueOf(char[]);
+ public static java.lang.String copyValueOf(char[],int,int);
+ public static java.lang.String valueOf(boolean);
+ public static java.lang.String valueOf(char);
+ public static java.lang.String valueOf(char[]);
+ public static java.lang.String valueOf(char[],int,int);
+ public static java.lang.String valueOf(double);
+ public static java.lang.String valueOf(float);
+ public static java.lang.String valueOf(int);
+ public static java.lang.String valueOf(java.lang.Object);
+ public static java.lang.String valueOf(long);
+ public boolean contentEquals(java.lang.StringBuffer);
+ public boolean endsWith(java.lang.String);
+ public boolean equalsIgnoreCase(java.lang.String);
+ public boolean equals(java.lang.Object);
+ public boolean matches(java.lang.String);
+ public boolean regionMatches(boolean,int,java.lang.String,int,int);
+ public boolean regionMatches(int,java.lang.String,int,int);
+ public boolean startsWith(java.lang.String);
+ public boolean startsWith(java.lang.String,int);
+ public byte[] getBytes();
+ public byte[] getBytes(java.lang.String);
+ public char charAt(int);
+ public char[] toCharArray();
+ public int compareToIgnoreCase(java.lang.String);
+ public int compareTo(java.lang.Object);
+ public int compareTo(java.lang.String);
+ public int hashCode();
+ public int indexOf(int);
+ public int indexOf(int,int);
+ public int indexOf(java.lang.String);
+ public int indexOf(java.lang.String,int);
+ public int lastIndexOf(int);
+ public int lastIndexOf(int,int);
+ public int lastIndexOf(java.lang.String);
+ public int lastIndexOf(java.lang.String,int);
+ public int length();
+ public java.lang.CharSequence subSequence(int,int);
+ public java.lang.String concat(java.lang.String);
+ public java.lang.String replaceAll(java.lang.String,java.lang.String);
+ public java.lang.String replace(char,char);
+ public java.lang.String replaceFirst(java.lang.String,java.lang.String);
+ public java.lang.String[] split(java.lang.String);
+ public java.lang.String[] split(java.lang.String,int);
+ public java.lang.String substring(int);
+ public java.lang.String substring(int,int);
+ public java.lang.String toLowerCase();
+ public java.lang.String toLowerCase(java.util.Locale);
+ public java.lang.String toString();
+ public java.lang.String toUpperCase();
+ public java.lang.String toUpperCase(java.util.Locale);
+ public java.lang.String trim();
+}
+
+# Remove - StringBuffer method calls. Remove all invocations of StringBuffer
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.StringBuffer {
+ public java.lang.String toString();
+ public char charAt(int);
+ public int capacity();
+ public int codePointAt(int);
+ public int codePointBefore(int);
+ public int indexOf(java.lang.String,int);
+ public int lastIndexOf(java.lang.String);
+ public int lastIndexOf(java.lang.String,int);
+ public int length();
+ public java.lang.String substring(int);
+ public java.lang.String substring(int,int);
+}
+
+# Remove - StringBuilder method calls. Remove all invocations of StringBuilder
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.StringBuilder {
+ public java.lang.String toString();
+ public char charAt(int);
+ public int capacity();
+ public int codePointAt(int);
+ public int codePointBefore(int);
+ public int indexOf(java.lang.String,int);
+ public int lastIndexOf(java.lang.String);
+ public int lastIndexOf(java.lang.String,int);
+ public int length();
+ public java.lang.String substring(int);
+ public java.lang.String substring(int,int);
+}
+
+# Remove debugging - Throwable_printStackTrace calls. Remove all invocations of
+# Throwable.printStackTrace().
+-assumenosideeffects public class java.lang.Throwable {
+ public void printStackTrace();
+}
+
+# Remove debugging - Thread_dumpStack calls. Remove all invocations of
+# Thread.dumpStack().
+-assumenosideeffects public class java.lang.Thread {
+ public static void dumpStack();
+}
+
+# Remove debugging - All logging API calls. Remove all invocations of the
+# logging API whose return values are not used.
+-assumenosideeffects public class java.util.logging.* {
+ <methods>;
+}
+
+# Remove debugging - All Log4j API calls. Remove all invocations of the
+# Log4j API whose return values are not used.
+-assumenosideeffects public class org.apache.log4j.** {
+ <methods>;
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/default.pro b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/default.pro
new file mode 100644
index 0000000000..8cd6b38ed5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/default.pro
@@ -0,0 +1,292 @@
+# The default configuration when starting up the GUI.
+
+-libraryjars <java.home>/lib/rt.jar
+
+# Keep - Applications. Keep all application classes, along with their 'main'
+# methods.
+-keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+}
+
+# Also keep - Enumerations. Keep the special static methods that are required in
+# enumeration classes.
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# Also keep - Database drivers. Keep all implementations of java.sql.Driver.
+-keep class * extends java.sql.Driver
+
+# Also keep - Swing UI L&F. Keep all extensions of javax.swing.plaf.ComponentUI,
+# along with the special 'createUI' method.
+-keep class * extends javax.swing.plaf.ComponentUI {
+ public static javax.swing.plaf.ComponentUI createUI(javax.swing.JComponent);
+}
+
+# Keep names - Native method names. Keep all native class/method names.
+-keepclasseswithmembers,includedescriptorclasses,allowshrinking class * {
+ native <methods>;
+}
+
+# Remove - System method calls. Remove all invocations of System
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.System {
+ public static long currentTimeMillis();
+ static java.lang.Class getCallerClass();
+ public static int identityHashCode(java.lang.Object);
+ public static java.lang.SecurityManager getSecurityManager();
+ public static java.util.Properties getProperties();
+ public static java.lang.String getProperty(java.lang.String);
+ public static java.lang.String getenv(java.lang.String);
+ public static java.lang.String mapLibraryName(java.lang.String);
+ public static java.lang.String getProperty(java.lang.String,java.lang.String);
+}
+
+# Remove - Math method calls. Remove all invocations of Math
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.Math {
+ public static double sin(double);
+ public static double cos(double);
+ public static double tan(double);
+ public static double asin(double);
+ public static double acos(double);
+ public static double atan(double);
+ public static double toRadians(double);
+ public static double toDegrees(double);
+ public static double exp(double);
+ public static double log(double);
+ public static double log10(double);
+ public static double sqrt(double);
+ public static double cbrt(double);
+ public static double IEEEremainder(double,double);
+ public static double ceil(double);
+ public static double floor(double);
+ public static double rint(double);
+ public static double atan2(double,double);
+ public static double pow(double,double);
+ public static int round(float);
+ public static long round(double);
+ public static double random();
+ public static int abs(int);
+ public static long abs(long);
+ public static float abs(float);
+ public static double abs(double);
+ public static int max(int,int);
+ public static long max(long,long);
+ public static float max(float,float);
+ public static double max(double,double);
+ public static int min(int,int);
+ public static long min(long,long);
+ public static float min(float,float);
+ public static double min(double,double);
+ public static double ulp(double);
+ public static float ulp(float);
+ public static double signum(double);
+ public static float signum(float);
+ public static double sinh(double);
+ public static double cosh(double);
+ public static double tanh(double);
+ public static double hypot(double,double);
+ public static double expm1(double);
+ public static double log1p(double);
+}
+
+# Remove - Number method calls. Remove all invocations of Number
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.* extends java.lang.Number {
+ public static java.lang.String toString(byte);
+ public static java.lang.Byte valueOf(byte);
+ public static byte parseByte(java.lang.String);
+ public static byte parseByte(java.lang.String,int);
+ public static java.lang.Byte valueOf(java.lang.String,int);
+ public static java.lang.Byte valueOf(java.lang.String);
+ public static java.lang.Byte decode(java.lang.String);
+ public int compareTo(java.lang.Byte);
+ public static java.lang.String toString(short);
+ public static short parseShort(java.lang.String);
+ public static short parseShort(java.lang.String,int);
+ public static java.lang.Short valueOf(java.lang.String,int);
+ public static java.lang.Short valueOf(java.lang.String);
+ public static java.lang.Short valueOf(short);
+ public static java.lang.Short decode(java.lang.String);
+ public static short reverseBytes(short);
+ public int compareTo(java.lang.Short);
+ public static java.lang.String toString(int,int);
+ public static java.lang.String toHexString(int);
+ public static java.lang.String toOctalString(int);
+ public static java.lang.String toBinaryString(int);
+ public static java.lang.String toString(int);
+ public static int parseInt(java.lang.String,int);
+ public static int parseInt(java.lang.String);
+ public static java.lang.Integer valueOf(java.lang.String,int);
+ public static java.lang.Integer valueOf(java.lang.String);
+ public static java.lang.Integer valueOf(int);
+ public static java.lang.Integer getInteger(java.lang.String);
+ public static java.lang.Integer getInteger(java.lang.String,int);
+ public static java.lang.Integer getInteger(java.lang.String,java.lang.Integer);
+ public static java.lang.Integer decode(java.lang.String);
+ public static int highestOneBit(int);
+ public static int lowestOneBit(int);
+ public static int numberOfLeadingZeros(int);
+ public static int numberOfTrailingZeros(int);
+ public static int bitCount(int);
+ public static int rotateLeft(int,int);
+ public static int rotateRight(int,int);
+ public static int reverse(int);
+ public static int signum(int);
+ public static int reverseBytes(int);
+ public int compareTo(java.lang.Integer);
+ public static java.lang.String toString(long,int);
+ public static java.lang.String toHexString(long);
+ public static java.lang.String toOctalString(long);
+ public static java.lang.String toBinaryString(long);
+ public static java.lang.String toString(long);
+ public static long parseLong(java.lang.String,int);
+ public static long parseLong(java.lang.String);
+ public static java.lang.Long valueOf(java.lang.String,int);
+ public static java.lang.Long valueOf(java.lang.String);
+ public static java.lang.Long valueOf(long);
+ public static java.lang.Long decode(java.lang.String);
+ public static java.lang.Long getLong(java.lang.String);
+ public static java.lang.Long getLong(java.lang.String,long);
+ public static java.lang.Long getLong(java.lang.String,java.lang.Long);
+ public static long highestOneBit(long);
+ public static long lowestOneBit(long);
+ public static int numberOfLeadingZeros(long);
+ public static int numberOfTrailingZeros(long);
+ public static int bitCount(long);
+ public static long rotateLeft(long,int);
+ public static long rotateRight(long,int);
+ public static long reverse(long);
+ public static int signum(long);
+ public static long reverseBytes(long);
+ public int compareTo(java.lang.Long);
+ public static java.lang.String toString(float);
+ public static java.lang.String toHexString(float);
+ public static java.lang.Float valueOf(java.lang.String);
+ public static java.lang.Float valueOf(float);
+ public static float parseFloat(java.lang.String);
+ public static boolean isNaN(float);
+ public static boolean isInfinite(float);
+ public static int floatToIntBits(float);
+ public static int floatToRawIntBits(float);
+ public static float intBitsToFloat(int);
+ public static int compare(float,float);
+ public boolean isNaN();
+ public boolean isInfinite();
+ public int compareTo(java.lang.Float);
+ public static java.lang.String toString(double);
+ public static java.lang.String toHexString(double);
+ public static java.lang.Double valueOf(java.lang.String);
+ public static java.lang.Double valueOf(double);
+ public static double parseDouble(java.lang.String);
+ public static boolean isNaN(double);
+ public static boolean isInfinite(double);
+ public static long doubleToLongBits(double);
+ public static long doubleToRawLongBits(double);
+ public static double longBitsToDouble(long);
+ public static int compare(double,double);
+ public boolean isNaN();
+ public boolean isInfinite();
+ public int compareTo(java.lang.Double);
+ public byte byteValue();
+ public short shortValue();
+ public int intValue();
+ public long longValue();
+ public float floatValue();
+ public double doubleValue();
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public java.lang.String toString();
+}
+
+# Remove - String method calls. Remove all invocations of String
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.String {
+ public static java.lang.String copyValueOf(char[]);
+ public static java.lang.String copyValueOf(char[],int,int);
+ public static java.lang.String valueOf(boolean);
+ public static java.lang.String valueOf(char);
+ public static java.lang.String valueOf(char[]);
+ public static java.lang.String valueOf(char[],int,int);
+ public static java.lang.String valueOf(double);
+ public static java.lang.String valueOf(float);
+ public static java.lang.String valueOf(int);
+ public static java.lang.String valueOf(java.lang.Object);
+ public static java.lang.String valueOf(long);
+ public boolean contentEquals(java.lang.StringBuffer);
+ public boolean endsWith(java.lang.String);
+ public boolean equalsIgnoreCase(java.lang.String);
+ public boolean equals(java.lang.Object);
+ public boolean matches(java.lang.String);
+ public boolean regionMatches(boolean,int,java.lang.String,int,int);
+ public boolean regionMatches(int,java.lang.String,int,int);
+ public boolean startsWith(java.lang.String);
+ public boolean startsWith(java.lang.String,int);
+ public byte[] getBytes();
+ public byte[] getBytes(java.lang.String);
+ public char charAt(int);
+ public char[] toCharArray();
+ public int compareToIgnoreCase(java.lang.String);
+ public int compareTo(java.lang.Object);
+ public int compareTo(java.lang.String);
+ public int hashCode();
+ public int indexOf(int);
+ public int indexOf(int,int);
+ public int indexOf(java.lang.String);
+ public int indexOf(java.lang.String,int);
+ public int lastIndexOf(int);
+ public int lastIndexOf(int,int);
+ public int lastIndexOf(java.lang.String);
+ public int lastIndexOf(java.lang.String,int);
+ public int length();
+ public java.lang.CharSequence subSequence(int,int);
+ public java.lang.String concat(java.lang.String);
+ public java.lang.String replaceAll(java.lang.String,java.lang.String);
+ public java.lang.String replace(char,char);
+ public java.lang.String replaceFirst(java.lang.String,java.lang.String);
+ public java.lang.String[] split(java.lang.String);
+ public java.lang.String[] split(java.lang.String,int);
+ public java.lang.String substring(int);
+ public java.lang.String substring(int,int);
+ public java.lang.String toLowerCase();
+ public java.lang.String toLowerCase(java.util.Locale);
+ public java.lang.String toString();
+ public java.lang.String toUpperCase();
+ public java.lang.String toUpperCase(java.util.Locale);
+ public java.lang.String trim();
+}
+
+# Remove - StringBuffer method calls. Remove all invocations of StringBuffer
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.StringBuffer {
+ public java.lang.String toString();
+ public char charAt(int);
+ public int capacity();
+ public int codePointAt(int);
+ public int codePointBefore(int);
+ public int indexOf(java.lang.String,int);
+ public int lastIndexOf(java.lang.String);
+ public int lastIndexOf(java.lang.String,int);
+ public int length();
+ public java.lang.String substring(int);
+ public java.lang.String substring(int,int);
+}
+
+# Remove - StringBuilder method calls. Remove all invocations of StringBuilder
+# methods without side effects whose return values are not used.
+-assumenosideeffects public class java.lang.StringBuilder {
+ public java.lang.String toString();
+ public char charAt(int);
+ public int capacity();
+ public int codePointAt(int);
+ public int codePointBefore(int);
+ public int indexOf(java.lang.String,int);
+ public int lastIndexOf(java.lang.String);
+ public int lastIndexOf(java.lang.String,int);
+ public int length();
+ public java.lang.String substring(int);
+ public java.lang.String substring(int,int);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/package.html
new file mode 100644
index 0000000000..4eedcc2717
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains a GUI for ProGuard and ReTrace.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/BufferedSprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/BufferedSprite.java
new file mode 100644
index 0000000000..8c69d51459
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/BufferedSprite.java
@@ -0,0 +1,145 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+
+/**
+ * This Sprite encapsulates another Sprite, which is then buffered in an Image.
+ *
+ * @author Eric Lafortune
+ */
+public class BufferedSprite implements Sprite
+{
+ private final int bufferX;
+ private final int bufferY;
+ private final Image bufferImage;
+ private final Color backgroundColor;
+ private final Sprite sprite;
+ private final VariableInt x;
+ private final VariableInt y;
+
+ private long cachedTime = -1;
+
+
+ /**
+ * Creates a new BufferedSprite with an ABGR image.
+ * @param bufferX the x offset of the buffer image.
+ * @param bufferY the y offset of the buffer image.
+ * @param width the width of the buffer image.
+ * @param height the height of the buffer image.
+ * @param sprite the Sprite that is painted in the buffer.
+ * @param x the variable x ordinate of the image buffer for painting.
+ * @param y the variable y ordinate of the image buffer for painting.
+ *
+ */
+ public BufferedSprite(int bufferX,
+ int bufferY,
+ int width,
+ int height,
+ Sprite sprite,
+ VariableInt x,
+ VariableInt y)
+ {
+
+ this(bufferX,
+ bufferY,
+ new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR),
+ null,
+ sprite,
+ x,
+ y);
+ }
+
+
+ /**
+ * Creates a new BufferedSprite with the given image.
+ * @param bufferX the x offset of the buffer image.
+ * @param bufferY the y offset of the buffer image.
+ * @param bufferImage the Image that is used for the buffering.
+ * @param backgroundColor the background color that is used for the buffer.
+ * @param sprite the Sprite that is painted in the buffer.
+ * @param x the variable x ordinate of the image buffer for
+ * painting.
+ * @param y the variable y ordinate of the image buffer for
+ * painting.
+ */
+ public BufferedSprite(int bufferX,
+ int bufferY,
+ Image bufferImage,
+ Color backgroundColor,
+ Sprite sprite,
+ VariableInt x,
+ VariableInt y)
+ {
+ this.bufferX = bufferX;
+ this.bufferY = bufferY;
+ this.bufferImage = bufferImage;
+ this.backgroundColor = backgroundColor;
+ this.sprite = sprite;
+ this.x = x;
+ this.y = y;
+ }
+
+
+ // Implementation for Sprite.
+
+ public void paint(Graphics graphics, long time)
+ {
+ if (time != cachedTime)
+ {
+ Graphics bufferGraphics = bufferImage.getGraphics();
+
+ // Clear the background.
+ if (backgroundColor != null)
+ {
+ Graphics2D bufferGraphics2D = (Graphics2D)bufferGraphics;
+ bufferGraphics2D.setComposite(AlphaComposite.Clear);
+ bufferGraphics.fillRect(0, 0, bufferImage.getWidth(null), bufferImage.getHeight(null));
+ bufferGraphics2D.setComposite(AlphaComposite.Src);
+ }
+ else
+ {
+ bufferGraphics.setColor(backgroundColor);
+ bufferGraphics.fillRect(0, 0, bufferImage.getWidth(null), bufferImage.getHeight(null));
+ }
+
+ // Set up the buffer graphics.
+ bufferGraphics.translate(-bufferX, -bufferY);
+ bufferGraphics.setColor(graphics.getColor());
+ bufferGraphics.setFont(graphics.getFont());
+
+ // Draw the sprite.
+ sprite.paint(bufferGraphics, time);
+
+ bufferGraphics.dispose();
+
+ cachedTime = time;
+ }
+
+ // Draw the buffer image.
+ graphics.drawImage(bufferImage,
+ bufferX + x.getInt(time),
+ bufferY + y.getInt(time),
+ null);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/CircleSprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/CircleSprite.java
new file mode 100644
index 0000000000..ccce9b9d2a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/CircleSprite.java
@@ -0,0 +1,74 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This Sprite represents an animated circle. It can optionally be filled.
+ *
+ * @author Eric Lafortune
+ */
+public class CircleSprite implements Sprite
+{
+ private final boolean filled;
+ private final VariableInt x;
+ private final VariableInt y;
+ private final VariableInt radius;
+
+
+ /**
+ * Creates a new CircleSprite.
+ * @param filled specifies whether the rectangle should be filled.
+ * @param x the variable x-coordinate of the center of the circle.
+ * @param y the variable y-coordinate of the center of the circle.
+ * @param radius the variable radius of the circle.
+ */
+ public CircleSprite(boolean filled,
+ VariableInt x,
+ VariableInt y,
+ VariableInt radius)
+ {
+ this.filled = filled;
+ this.x = x;
+ this.y = y;
+ this.radius = radius;
+ }
+
+
+ // Implementation for Sprite.
+
+ public void paint(Graphics graphics, long time)
+ {
+ int xt = x.getInt(time);
+ int yt = y.getInt(time);
+ int r = radius.getInt(time);
+
+ if (filled)
+ {
+ graphics.fillOval(xt - r, yt - r, 2 * r, 2 * r);
+ }
+ else
+ {
+ graphics.drawOval(xt - r, yt - r, 2 * r, 2 * r);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ClipSprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ClipSprite.java
new file mode 100644
index 0000000000..47de7134dc
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ClipSprite.java
@@ -0,0 +1,85 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This Sprite encapsulates another Sprite, which is clipped by a clip Sprite.
+ *
+ * @author Eric Lafortune
+ */
+public class ClipSprite implements Sprite
+{
+ private final VariableColor insideClipColor;
+ private final VariableColor outsideClipColor;
+ private final Sprite clipSprite;
+ private final Sprite sprite;
+
+
+ /**
+ * Creates a new ClipSprite.
+ * @param insideClipColor the background color inside the clip sprite.
+ * @param outsideClipColor the background color outside the clip sprite.
+ * @param clipSprite the clip Sprite.
+ * @param sprite the clipped Sprite.
+ */
+ public ClipSprite(VariableColor insideClipColor,
+ VariableColor outsideClipColor,
+ Sprite clipSprite,
+ Sprite sprite)
+ {
+ this.insideClipColor = insideClipColor;
+ this.outsideClipColor = outsideClipColor;
+ this.clipSprite = clipSprite;
+ this.sprite = sprite;
+ }
+
+
+ // Implementation for Sprite.
+
+ public void paint(Graphics graphics, long time)
+ {
+ // Clear the background.
+ Color outsideColor = outsideClipColor.getColor(time);
+ Rectangle clip = graphics.getClipBounds();
+ graphics.setPaintMode();
+ graphics.setColor(outsideColor);
+ graphics.fillRect(0, 0, clip.width, clip.height);
+
+ // Draw the sprite in XOR mode.
+ OverrideGraphics2D g = new OverrideGraphics2D((Graphics2D)graphics);
+ Color insideColor = insideClipColor.getColor(time);
+ g.setOverrideXORMode(insideColor);
+ sprite.paint(g, time);
+ g.setOverrideXORMode(null);
+
+ // Clear the clip area.
+ g.setOverrideColor(insideColor);
+ clipSprite.paint(g, time);
+ g.setOverrideColor(null);
+
+ // Draw the sprite in XOR mode.
+ g.setOverrideXORMode(insideColor);
+ sprite.paint(g, time);
+ g.setOverrideXORMode(null);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ColorSprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ColorSprite.java
new file mode 100644
index 0000000000..1e223be091
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ColorSprite.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This Sprite colors another given sprite.
+ *
+ * @author Eric Lafortune
+ */
+public class ColorSprite implements Sprite
+{
+ private final VariableColor color;
+ private final Sprite sprite;
+
+
+ /**
+ * Creates a new ColorSprite.
+ * @param color the variable color of the given sprite.
+ * @param sprite the sprite that will be colored and painted.
+ */
+ public ColorSprite(VariableColor color,
+ Sprite sprite)
+ {
+ this.color = color;
+ this.sprite = sprite;
+ }
+
+
+ // Implementation for Sprite.
+
+ public void paint(Graphics graphics, long time)
+ {
+ // Save the old color.
+ Color oldColor = graphics.getColor();
+
+ // Set the new color.
+ graphics.setColor(color.getColor(time));
+
+ // Paint the actual sprite.
+ sprite.paint(graphics, time);
+
+ // Restore the old color.
+ graphics.setColor(oldColor);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/CompositeSprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/CompositeSprite.java
new file mode 100644
index 0000000000..6050fa1e97
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/CompositeSprite.java
@@ -0,0 +1,56 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This Sprite is the composition of a list of Sprite objects.
+ *
+ * @author Eric Lafortune
+ */
+public class CompositeSprite implements Sprite
+{
+ private final Sprite[] sprites;
+
+
+ /**
+ * Creates a new CompositeSprite.
+ * @param sprites the array of Sprite objects to which the painting will
+ * be delegated, starting with the first element.
+ */
+ public CompositeSprite(Sprite[] sprites)
+ {
+ this.sprites = sprites;
+ }
+
+
+ // Implementation for Sprite.
+
+ public void paint(Graphics graphics, long time)
+ {
+ // Draw the sprites.
+ for (int index = 0; index < sprites.length; index++)
+ {
+ sprites[index].paint(graphics, time);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantColor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantColor.java
new file mode 100644
index 0000000000..ea9089c71f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantColor.java
@@ -0,0 +1,51 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This VariableColor is constant over time.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantColor implements VariableColor
+{
+ private final Color value;
+
+
+ /**
+ * Creates a new ConstantColor.
+ * @param value the constant value.
+ */
+ public ConstantColor(Color value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementation for VariableColor.
+
+ public Color getColor(long time)
+ {
+ return value;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantDouble.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantDouble.java
new file mode 100644
index 0000000000..ae6888d845
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantDouble.java
@@ -0,0 +1,49 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This VariableDouble is constant over time.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantDouble implements VariableDouble
+{
+ private final double value;
+
+
+ /**
+ * Creates a new ConstantDouble.
+ * @param value the constant value.
+ */
+ public ConstantDouble(double value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementation for VariableDouble.
+
+ public double getDouble(long time)
+ {
+ return value;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantFont.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantFont.java
new file mode 100644
index 0000000000..d6cba7803a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantFont.java
@@ -0,0 +1,46 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This VariableFont is constant over time.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantFont implements VariableFont
+{
+ private final Font value;
+
+ public ConstantFont(Font value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementation for VariableFont.
+
+ public Font getFont(long time)
+ {
+ return value;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantInt.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantInt.java
new file mode 100644
index 0000000000..0f1971b068
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantInt.java
@@ -0,0 +1,49 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This VariableInt is constant over time.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantInt implements VariableInt
+{
+ private final int value;
+
+
+ /**
+ * Creates a new ConstantInt.
+ * @param value the constant value.
+ */
+ public ConstantInt(int value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementation for VariableInt.
+
+ public int getInt(long time)
+ {
+ return value;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantString.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantString.java
new file mode 100644
index 0000000000..ec0a4d765c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantString.java
@@ -0,0 +1,49 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This VariableString is constant over time.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantString implements VariableString
+{
+ private final String value;
+
+
+ /**
+ * Creates a new ConstantString.
+ * @param value the constant value.
+ */
+ public ConstantString(String value)
+ {
+ this.value = value;
+ }
+
+
+ // Implementation for VariableString.
+
+ public String getString(long time)
+ {
+ return value;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantTiming.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantTiming.java
new file mode 100644
index 0000000000..c3d398a50f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ConstantTiming.java
@@ -0,0 +1,57 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This Timing is constant over time.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantTiming implements Timing
+{
+ private final double timing;
+
+
+ /**
+ * Creates a new ConstantTiming with a value of 0.
+ */
+ public ConstantTiming()
+ {
+ this(0.0);
+ }
+
+ /**
+ * Creates a new ConstantTiming with a given value.
+ * @param timing the constant value of the timing.
+ */
+ public ConstantTiming(double timing)
+ {
+ this.timing = timing;
+ }
+
+
+ // Implementation for Timing.
+
+ public double getTiming(long time)
+ {
+ return timing;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/FontSprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/FontSprite.java
new file mode 100644
index 0000000000..72a1747f59
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/FontSprite.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This Sprite sets the font for another given sprite.
+ *
+ * @author Eric Lafortune
+ */
+public class FontSprite implements Sprite
+{
+ private final VariableFont font;
+ private final Sprite sprite;
+
+
+ /**
+ * Creates a new FontSprite.
+ * @param font the variable Font of the given sprite.
+ * @param sprite the sprite that will be provided of a font and painted.
+ */
+ public FontSprite(VariableFont font,
+ Sprite sprite)
+ {
+ this.font = font;
+ this.sprite = sprite;
+ }
+
+
+ // Implementation for Sprite.
+
+ public void paint(Graphics graphics, long time)
+ {
+ // Save the old font.
+ Font oldFont = graphics.getFont();
+
+ // Set the new font.
+ graphics.setFont(font.getFont(time));
+
+ // Paint the actual sprite.
+ sprite.paint(graphics, time);
+
+ // Restore the old font.
+ graphics.setFont(oldFont);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ImageSprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ImageSprite.java
new file mode 100644
index 0000000000..48f2fcae92
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ImageSprite.java
@@ -0,0 +1,76 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This Sprite represents an animated image.
+ *
+ * @author Eric Lafortune
+ */
+public class ImageSprite implements Sprite
+{
+ private final Image image;
+ private final VariableInt x;
+ private final VariableInt y;
+ private final VariableDouble scaleX;
+ private final VariableDouble scaleY;
+
+
+ /**
+ * Creates a new ImageSprite.
+ * @param image the Image to be painted.
+ * @param x the variable x-coordinate of the upper-left corner of the image.
+ * @param y the variable y-coordinate of the upper-left corner of the image.
+ * @param scaleX the variable x-scale of the image.
+ * @param scaleY the variable y-scale of the image.
+ */
+ public ImageSprite(Image image,
+ VariableInt x,
+ VariableInt y,
+ VariableDouble scaleX,
+ VariableDouble scaleY)
+ {
+ this.image = image;
+ this.x = x;
+ this.y = y;
+ this.scaleX = scaleX;
+ this.scaleY = scaleY;
+ }
+
+
+ // Implementation for Sprite.
+
+ public void paint(Graphics graphics, long time)
+ {
+ int xt = x.getInt(time);
+ int yt = y.getInt(time);
+
+ double scale_x = scaleX.getDouble(time);
+ double scale_y = scaleY.getDouble(time);
+
+ int width = (int)(image.getWidth(null) * scale_x);
+ int height = (int)(image.getHeight(null) * scale_y);
+
+ graphics.drawImage(image, xt, yt, width, height, null);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearColor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearColor.java
new file mode 100644
index 0000000000..3cb1a36858
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearColor.java
@@ -0,0 +1,72 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This VariableColor varies linearly with respect to its Timing.
+ *
+ * @author Eric Lafortune
+ */
+public class LinearColor implements VariableColor
+{
+ private final Color fromValue;
+ private final Color toValue;
+ private final Timing timing;
+
+ private double cachedTiming = -1.0;
+ private Color cachedColor;
+
+
+ /**
+ * Creates a new LinearColor.
+ * @param fromValue the value that corresponds to a timing of 0.
+ * @param toValue the value that corresponds to a timing of 1.
+ * @param timing the applied timing.
+ */
+ public LinearColor(Color fromValue, Color toValue, Timing timing)
+ {
+ this.fromValue = fromValue;
+ this.toValue = toValue;
+ this.timing = timing;
+ }
+
+
+ // Implementation for VariableColor.
+
+ public Color getColor(long time)
+ {
+ double t = timing.getTiming(time);
+ if (t != cachedTiming)
+ {
+ cachedTiming = t;
+ cachedColor =
+ t == 0.0 ? fromValue :
+ t == 1.0 ? toValue :
+ new Color((int)(fromValue.getRed() + t * (toValue.getRed() - fromValue.getRed())),
+ (int)(fromValue.getGreen() + t * (toValue.getGreen() - fromValue.getGreen())),
+ (int)(fromValue.getBlue() + t * (toValue.getBlue() - fromValue.getBlue())));
+ }
+
+ return cachedColor;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearDouble.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearDouble.java
new file mode 100644
index 0000000000..dba1f56a68
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearDouble.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This VariableDouble varies linearly with respect to its Timing.
+ *
+ * @author Eric Lafortune
+ */
+public class LinearDouble implements VariableDouble
+{
+ private final double fromValue;
+ private final double toValue;
+ private final Timing timing;
+
+
+ /**
+ * Creates a new LinearDouble.
+ * @param fromValue the value that corresponds to a timing of 0.
+ * @param toValue the value that corresponds to a timing of 1.
+ * @param timing the applied timing.
+ */
+ public LinearDouble(double fromValue, double toValue, Timing timing)
+ {
+ this.fromValue = fromValue;
+ this.toValue = toValue;
+ this.timing = timing;
+ }
+
+
+ // Implementation for VariableDouble.
+
+ public double getDouble(long time)
+ {
+ return fromValue + timing.getTiming(time) * (toValue - fromValue);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearInt.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearInt.java
new file mode 100644
index 0000000000..52db46c09d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearInt.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This VariableColor varies linearly with respect to its Timing.
+ *
+ * @author Eric Lafortune
+ */
+public class LinearInt implements VariableInt
+{
+ private final int fromValue;
+ private final int toValue;
+ private final Timing timing;
+
+
+ /**
+ * Creates a new LinearInt.
+ * @param fromValue the value that corresponds to a timing of 0.
+ * @param toValue the value that corresponds to a timing of 1.
+ * @param timing the applied timing.
+ */
+ public LinearInt(int fromValue, int toValue, Timing timing)
+ {
+ this.fromValue = fromValue;
+ this.toValue = toValue;
+ this.timing = timing;
+ }
+
+
+ // Implementation for VariableInt.
+
+ public int getInt(long time)
+ {
+ return (int) (fromValue + timing.getTiming(time) * (toValue - fromValue));
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearTiming.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearTiming.java
new file mode 100644
index 0000000000..6b537d0c0b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/LinearTiming.java
@@ -0,0 +1,55 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This Timing ramps up linearly from 0 to 1 in a given time interval.
+ *
+ * @author Eric Lafortune
+ */
+public class LinearTiming implements Timing
+{
+ private final long fromTime;
+ private final long toTime;
+
+
+ /**
+ * Creates a new LinearTiming.
+ * @param fromTime the time at which the timing starts ramping up from 0.
+ * @param toTime the time at which the timing stops ramping up at 1.
+ */
+ public LinearTiming(long fromTime, long toTime)
+ {
+ this.fromTime = fromTime;
+ this.toTime = toTime;
+ }
+
+
+ // Implementation for Timing.
+
+ public double getTiming(long time)
+ {
+ // Compute the clamped linear interpolation.
+ return time <= fromTime ? 0.0 :
+ time >= toTime ? 1.0 :
+ (double)(time - fromTime) / (double)(toTime - fromTime);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/OverrideGraphics2D.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/OverrideGraphics2D.java
new file mode 100644
index 0000000000..45921c86e8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/OverrideGraphics2D.java
@@ -0,0 +1,598 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+import java.awt.RenderingHints.Key;
+import java.awt.font.*;
+import java.awt.geom.AffineTransform;
+import java.awt.image.*;
+import java.awt.image.renderable.RenderableImage;
+import java.text.AttributedCharacterIterator;
+import java.util.Map;
+
+/**
+ * This Graphics2D allows to fix some basic settings (Color, Font, Paint, Stroke,
+ * XORMode) of a delegate Graphics2D, overriding any subsequent attempts to
+ * change those settings.
+ *
+ * @author Eric Lafortune
+ * @noinspection deprecation
+ */
+final class OverrideGraphics2D extends Graphics2D
+{
+ private final Graphics2D graphics;
+
+ private Color overrideColor;
+ private Font overrideFont;
+ private Paint overridePaint;
+ private Stroke overrideStroke;
+ private Color overrideXORMode;
+
+ private Color color;
+ private Font font;
+ private Paint paint;
+ private Stroke stroke;
+
+
+ /**
+ * Creates a new OverrideGraphics2D.
+ * @param graphics the delegate Graphics2D.
+ */
+ public OverrideGraphics2D(Graphics2D graphics)
+ {
+ this.graphics = graphics;
+ this.color = graphics.getColor();
+ this.font = graphics.getFont();
+ this.paint = graphics.getPaint();
+ this.stroke = graphics.getStroke();
+ }
+
+
+ /**
+ * Fixes the Color of the Graphics2D.
+ *
+ * @param color the fixed Color, or <code>null</code> to undo the fixing.
+ */
+ public void setOverrideColor(Color color)
+ {
+ this.overrideColor = color;
+ graphics.setColor(color != null ? color : this.color);
+ }
+
+ /**
+ * Fixes the Font of the Graphics2D.
+ *
+ * @param font the fixed Font, or <code>null</code> to undo the fixing.
+ */
+ public void setOverrideFont(Font font)
+ {
+ this.overrideFont = font;
+ graphics.setFont(font != null ? font : this.font);
+ }
+
+ /**
+ * Fixes the Paint of the Graphics2D.
+ *
+ * @param paint the fixed Paint, or <code>null</code> to undo the fixing.
+ */
+ public void setOverridePaint(Paint paint)
+ {
+ this.overridePaint = paint;
+ graphics.setPaint(paint != null ? paint : this.paint);
+ }
+
+ /**
+ * Fixes the Stroke of the Graphics2D.
+ *
+ * @param stroke the fixed Stroke, or <code>null</code> to undo the fixing.
+ */
+ public void setOverrideStroke(Stroke stroke)
+ {
+ this.overrideStroke = stroke;
+ graphics.setStroke(stroke != null ? stroke : this.stroke);
+ }
+
+ /**
+ * Fixes the XORMode of the Graphics2D.
+ *
+ * @param color the fixed XORMode Color, or <code>null</code> to undo the fixing.
+ */
+ public void setOverrideXORMode(Color color)
+ {
+ this.overrideXORMode = color;
+ if (color != null)
+ {
+ graphics.setXORMode(color);
+ }
+ else
+ {
+ graphics.setPaintMode();
+ }
+ }
+
+
+ // Implementations for Graphics2D.
+
+ public void setColor(Color color)
+ {
+ this.color = color;
+ if (overrideColor == null)
+ {
+ graphics.setColor(color);
+ }
+ }
+
+ public void setFont(Font font)
+ {
+ this.font = font;
+ if (overrideFont == null)
+ {
+ graphics.setFont(font);
+ }
+ }
+
+ public void setPaint(Paint paint)
+ {
+ this.paint = paint;
+ if (overridePaint == null)
+ {
+ graphics.setPaint(paint);
+ }
+ }
+
+ public void setStroke(Stroke stroke)
+ {
+ this.stroke = stroke;
+ if (overrideStroke == null)
+ {
+ graphics.setStroke(stroke);
+ }
+ }
+
+ public void setXORMode(Color color)
+ {
+ if (overrideXORMode == null)
+ {
+ graphics.setXORMode(color);
+ }
+ }
+
+ public void setPaintMode()
+ {
+ if (overrideXORMode == null)
+ {
+ graphics.setPaintMode();
+ }
+ }
+
+
+ public Color getColor()
+ {
+ return overrideColor != null ? color : graphics.getColor();
+ }
+
+ public Font getFont()
+ {
+ return overrideFont != null ? font : graphics.getFont();
+ }
+
+ public Paint getPaint()
+ {
+ return overridePaint != null ? paint : graphics.getPaint();
+ }
+
+ public Stroke getStroke()
+ {
+ return overrideStroke != null ? stroke : graphics.getStroke();
+ }
+
+
+ public Graphics create()
+ {
+ OverrideGraphics2D g = new OverrideGraphics2D((Graphics2D)graphics.create());
+ g.setOverrideColor(overrideColor);
+ g.setOverrideFont(overrideFont);
+ g.setOverridePaint(overridePaint);
+ g.setOverrideStroke(overrideStroke);
+
+ return g;
+ }
+
+ public Graphics create(int x, int y, int width, int height)
+ {
+ OverrideGraphics2D g = new OverrideGraphics2D((Graphics2D)graphics.create(x, y, width, height));
+ g.setOverrideColor(overrideColor);
+ g.setOverrideFont(overrideFont);
+ g.setOverridePaint(overridePaint);
+ g.setOverrideStroke(overrideStroke);
+
+ return g;
+ }
+
+
+ // Delegation for Graphics2D
+
+ public void addRenderingHints(Map hints)
+ {
+ graphics.addRenderingHints(hints);
+ }
+
+ public void clearRect(int x, int y, int width, int height)
+ {
+ graphics.clearRect(x, y, width, height);
+ }
+
+ public void clip(Shape s)
+ {
+ graphics.clip(s);
+ }
+
+ public void clipRect(int x, int y, int width, int height)
+ {
+ graphics.clipRect(x, y, width, height);
+ }
+
+ public void copyArea(int x, int y, int width, int height, int dx, int dy)
+ {
+ graphics.copyArea(x, y, width, height, dx, dy);
+ }
+
+ public void dispose()
+ {
+ graphics.dispose();
+ }
+
+ public void draw(Shape s)
+ {
+ graphics.draw(s);
+ }
+
+ public void draw3DRect(int x, int y, int width, int height, boolean raised)
+ {
+ graphics.draw3DRect(x, y, width, height, raised);
+ }
+
+ public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
+ {
+ graphics.drawArc(x, y, width, height, startAngle, arcAngle);
+ }
+
+ public void drawBytes(byte[] data, int offset, int length, int x, int y)
+ {
+ graphics.drawBytes(data, offset, length, x, y);
+ }
+
+ public void drawChars(char[] data, int offset, int length, int x, int y)
+ {
+ graphics.drawChars(data, offset, length, x, y);
+ }
+
+ public void drawGlyphVector(GlyphVector g, float x, float y)
+ {
+ graphics.drawGlyphVector(g, x, y);
+ }
+
+ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer)
+ {
+ return graphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer);
+ }
+
+ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer)
+ {
+ return graphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
+ }
+
+ public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer)
+ {
+ return graphics.drawImage(img, x, y, width, height, bgcolor, observer);
+ }
+
+ public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer)
+ {
+ return graphics.drawImage(img, x, y, width, height, observer);
+ }
+
+ public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer)
+ {
+ return graphics.drawImage(img, x, y, bgcolor, observer);
+ }
+
+ public boolean drawImage(Image img, int x, int y, ImageObserver observer)
+ {
+ return graphics.drawImage(img, x, y, observer);
+ }
+
+ public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs)
+ {
+ return graphics.drawImage(img, xform, obs);
+ }
+
+ public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y)
+ {
+ graphics.drawImage(img, op, x, y);
+ }
+
+ public void drawLine(int x1, int y1, int x2, int y2)
+ {
+ graphics.drawLine(x1, y1, x2, y2);
+ }
+
+ public void drawOval(int x, int y, int width, int height)
+ {
+ graphics.drawOval(x, y, width, height);
+ }
+
+ public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
+ {
+ graphics.drawPolygon(xPoints, yPoints, nPoints);
+ }
+
+ public void drawPolygon(Polygon p)
+ {
+ graphics.drawPolygon(p);
+ }
+
+ public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
+ {
+ graphics.drawPolyline(xPoints, yPoints, nPoints);
+ }
+
+ public void drawRect(int x, int y, int width, int height)
+ {
+ graphics.drawRect(x, y, width, height);
+ }
+
+ public void drawRenderableImage(RenderableImage img, AffineTransform xform)
+ {
+ graphics.drawRenderableImage(img, xform);
+ }
+
+ public void drawRenderedImage(RenderedImage img, AffineTransform xform)
+ {
+ graphics.drawRenderedImage(img, xform);
+ }
+
+ public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)
+ {
+ graphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
+ }
+
+ public void drawString(String s, float x, float y)
+ {
+ graphics.drawString(s, x, y);
+ }
+
+ public void drawString(String str, int x, int y)
+ {
+ graphics.drawString(str, x, y);
+ }
+
+ public void drawString(AttributedCharacterIterator iterator, float x, float y)
+ {
+ graphics.drawString(iterator, x, y);
+ }
+
+ public void drawString(AttributedCharacterIterator iterator, int x, int y)
+ {
+ graphics.drawString(iterator, x, y);
+ }
+
+ public boolean equals(Object obj)
+ {
+ return graphics.equals(obj);
+ }
+
+ public void fill(Shape s)
+ {
+ graphics.fill(s);
+ }
+
+ public void fill3DRect(int x, int y, int width, int height, boolean raised)
+ {
+ graphics.fill3DRect(x, y, width, height, raised);
+ }
+
+ public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle)
+ {
+ graphics.fillArc(x, y, width, height, startAngle, arcAngle);
+ }
+
+ public void fillOval(int x, int y, int width, int height)
+ {
+ graphics.fillOval(x, y, width, height);
+ }
+
+ public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints)
+ {
+ graphics.fillPolygon(xPoints, yPoints, nPoints);
+ }
+
+ public void fillPolygon(Polygon p)
+ {
+ graphics.fillPolygon(p);
+ }
+
+ public void fillRect(int x, int y, int width, int height)
+ {
+ graphics.fillRect(x, y, width, height);
+ }
+
+ public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)
+ {
+ graphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
+ }
+
+ public Color getBackground()
+ {
+ return graphics.getBackground();
+ }
+
+ public Shape getClip()
+ {
+ return graphics.getClip();
+ }
+
+ public Rectangle getClipBounds()
+ {
+ return graphics.getClipBounds();
+ }
+
+ public Rectangle getClipBounds(Rectangle r)
+ {
+ return graphics.getClipBounds(r);
+ }
+
+ public Rectangle getClipRect()
+ {
+ return graphics.getClipRect();
+ }
+
+ public Composite getComposite()
+ {
+ return graphics.getComposite();
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ return graphics.getDeviceConfiguration();
+ }
+
+ public FontMetrics getFontMetrics()
+ {
+ return graphics.getFontMetrics();
+ }
+
+ public FontMetrics getFontMetrics(Font f)
+ {
+ return graphics.getFontMetrics(f);
+ }
+
+ public FontRenderContext getFontRenderContext()
+ {
+ return graphics.getFontRenderContext();
+ }
+
+ public Object getRenderingHint(Key hintKey)
+ {
+ return graphics.getRenderingHint(hintKey);
+ }
+
+ public RenderingHints getRenderingHints()
+ {
+ return graphics.getRenderingHints();
+ }
+
+ public AffineTransform getTransform()
+ {
+ return graphics.getTransform();
+ }
+
+ public int hashCode()
+ {
+ return graphics.hashCode();
+ }
+
+ public boolean hit(Rectangle rect, Shape s, boolean onStroke)
+ {
+ return graphics.hit(rect, s, onStroke);
+ }
+
+ public boolean hitClip(int x, int y, int width, int height)
+ {
+ return graphics.hitClip(x, y, width, height);
+ }
+
+ public void rotate(double theta)
+ {
+ graphics.rotate(theta);
+ }
+
+ public void rotate(double theta, double x, double y)
+ {
+ graphics.rotate(theta, x, y);
+ }
+
+ public void scale(double sx, double sy)
+ {
+ graphics.scale(sx, sy);
+ }
+
+ public void setBackground(Color color)
+ {
+ graphics.setBackground(color);
+ }
+
+ public void setClip(int x, int y, int width, int height)
+ {
+ graphics.setClip(x, y, width, height);
+ }
+
+ public void setClip(Shape clip)
+ {
+ graphics.setClip(clip);
+ }
+
+ public void setComposite(Composite comp)
+ {
+ graphics.setComposite(comp);
+ }
+
+ public void setRenderingHint(Key hintKey, Object hintValue)
+ {
+ graphics.setRenderingHint(hintKey, hintValue);
+ }
+
+ public void setRenderingHints(Map hints)
+ {
+ graphics.setRenderingHints(hints);
+ }
+
+ public void setTransform(AffineTransform Tx)
+ {
+ graphics.setTransform(Tx);
+ }
+
+ public void shear(double shx, double shy)
+ {
+ graphics.shear(shx, shy);
+ }
+
+ public String toString()
+ {
+ return graphics.toString();
+ }
+
+ public void transform(AffineTransform Tx)
+ {
+ graphics.transform(Tx);
+ }
+
+ public void translate(double tx, double ty)
+ {
+ graphics.translate(tx, ty);
+ }
+
+ public void translate(int x, int y)
+ {
+ graphics.translate(x, y);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/RectangleSprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/RectangleSprite.java
new file mode 100644
index 0000000000..f336697413
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/RectangleSprite.java
@@ -0,0 +1,114 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This Sprite represents an animated rounded rectangle. It can optionally be filled.
+ *
+ * @author Eric Lafortune
+ */
+public class RectangleSprite implements Sprite
+{
+ private final boolean filled;
+ private final VariableColor color;
+ private final VariableInt x;
+ private final VariableInt y;
+ private final VariableInt width;
+ private final VariableInt height;
+ private final VariableInt arcWidth;
+ private final VariableInt arcHeight;
+
+
+ /**
+ * Creates a new rectangular RectangleSprite.
+ * @param filled specifies whether the rectangle should be filled.
+ * @param color the variable color of the rectangle.
+ * @param x the variable x-ordinate of the upper-left corner of the rectangle.
+ * @param y the variable y-ordinate of the upper-left corner of the rectangle.
+ * @param width the variable width of the rectangle.
+ * @param height the variable height of the rectangle.
+ */
+ public RectangleSprite(boolean filled,
+ VariableColor color,
+ VariableInt x,
+ VariableInt y,
+ VariableInt width,
+ VariableInt height)
+ {
+ this(filled, color, x, y, width, height, new ConstantInt(0), new ConstantInt(0));
+ }
+
+
+ /**
+ * Creates a new RectangleSprite with rounded corners.
+ * @param filled specifies whether the rectangle should be filled.
+ * @param color the variable color of the rectangle.
+ * @param x the variable x-ordinate of the upper-left corner of the rectangle.
+ * @param y the variable y-ordinate of the upper-left corner of the rectangle.
+ * @param width the variable width of the rectangle.
+ * @param height the variable height of the rectangle.
+ * @param arcWidth the variable width of the corner arcs.
+ * @param arcHeight the variable height of the corner arcs.
+ */
+ public RectangleSprite(boolean filled,
+ VariableColor color,
+ VariableInt x,
+ VariableInt y,
+ VariableInt width,
+ VariableInt height,
+ VariableInt arcWidth,
+ VariableInt arcHeight)
+ {
+ this.filled = filled;
+ this.color = color;
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ this.arcWidth = arcWidth;
+ this.arcHeight = arcHeight;
+ }
+
+ // Implementation for Sprite.
+
+ public void paint(Graphics graphics, long time)
+ {
+ graphics.setColor(color.getColor(time));
+
+ int xt = x.getInt(time);
+ int yt = y.getInt(time);
+ int w = width.getInt(time);
+ int h = height.getInt(time);
+ int aw = arcWidth.getInt(time);
+ int ah = arcHeight.getInt(time);
+
+ if (filled)
+ {
+ graphics.fillRoundRect(xt, yt, w, h, aw, ah);
+ }
+ else
+ {
+ graphics.drawRoundRect(xt, yt, w, h, aw, ah);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SawToothTiming.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SawToothTiming.java
new file mode 100644
index 0000000000..53c9be231d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SawToothTiming.java
@@ -0,0 +1,53 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This Timing ramps up linearly from 0 to 1 in a given repeated time interval.
+ *
+ * @author Eric Lafortune
+ */
+public class SawToothTiming implements Timing
+{
+ private final long period;
+ private final long phase;
+
+
+ /**
+ * Creates a new SawToothTiming.
+ * @param period the time period for a full cycle.
+ * @param phase the phase of the cycle, which is added to the actual time.
+ */
+ public SawToothTiming(long period, long phase)
+ {
+ this.period = period;
+ this.phase = phase;
+ }
+
+
+ // Implementation for Timing.
+
+ public double getTiming(long time)
+ {
+ // Compute the translated and scaled saw-tooth function.
+ return (double)((time + phase) % period) / (double)period;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ShadowedSprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ShadowedSprite.java
new file mode 100644
index 0000000000..9ef63c7746
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/ShadowedSprite.java
@@ -0,0 +1,109 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This Sprite adds a drop shadow to another Sprite.
+ *
+ * @author Eric Lafortune
+ */
+public class ShadowedSprite implements Sprite
+{
+ private final VariableInt xOffset;
+ private final VariableInt yOffset;
+ private final VariableDouble alpha;
+ private final VariableInt blur;
+ private final Sprite sprite;
+
+ private float cachedAlpha = -1.0f;
+ private Color cachedColor;
+
+
+ /**
+ * Creates a new ShadowedSprite.
+ * @param xOffset the variable x-offset of the shadow, relative to the sprite itself.
+ * @param yOffset the variable y-offset of the shadow, relative to the sprite itself.
+ * @param alpha the variable darkness of the shadow (between 0 and 1).
+ * @param blur the variable blur of the shadow (0 for sharp shadows, 1 or
+ * more for increasingly blurry shadows).
+ * @param sprite the Sprite to be painted with its shadow.
+ */
+ public ShadowedSprite(VariableInt xOffset,
+ VariableInt yOffset,
+ VariableDouble alpha,
+ VariableInt blur,
+ Sprite sprite)
+ {
+ this.xOffset = xOffset;
+ this.yOffset = yOffset;
+ this.alpha = alpha;
+ this.blur = blur;
+ this.sprite = sprite;
+ }
+
+
+ // Implementation for Sprite.
+
+ public void paint(Graphics graphics, long time)
+ {
+ double l = alpha.getDouble(time);
+ int b = blur.getInt(time) + 1;
+
+ float a = 1.0f - (float)Math.pow(1.0 - l, 1.0/(b*b));
+ if (a != cachedAlpha)
+ {
+ cachedAlpha = a;
+ cachedColor = new Color(0f, 0f, 0f, a);
+ }
+
+ // Set up the shadow graphics.
+ //OverrideGraphics2D g = new OverrideGraphics2D((Graphics2D)graphics);
+ //g.setOverrideColor(cachedColor);
+
+ // Set the shadow color.
+ Color actualColor = graphics.getColor();
+ graphics.setColor(cachedColor);
+
+ int xo = xOffset.getInt(time) - b/2;
+ int yo = yOffset.getInt(time) - b/2;
+
+ // Draw the sprite's shadow.
+ for (int x = 0; x < b; x++)
+ {
+ for (int y = 0; y < b; y++)
+ {
+ int xt = xo + x;
+ int yt = yo + y;
+ graphics.translate(xt, yt);
+ sprite.paint(graphics, time);
+ graphics.translate(-xt, -yt);
+ }
+ }
+
+ // Restore the actual sprite color.
+ graphics.setColor(actualColor);
+
+ // Draw the sprite itself in the ordinary graphics.
+ sprite.paint(graphics, time);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SineTiming.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SineTiming.java
new file mode 100644
index 0000000000..3875b44117
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SineTiming.java
@@ -0,0 +1,53 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This Timing varies between 0 and 1, as a sine wave over time.
+ *
+ * @author Eric Lafortune
+ */
+public class SineTiming implements Timing
+{
+ private final long period;
+ private final long phase;
+
+
+ /**
+ * Creates a new SineTiming.
+ * @param period the time period for a full cycle.
+ * @param phase the phase of the cycle, which is added to the actual time.
+ */
+ public SineTiming(long period, long phase)
+ {
+ this.period = period;
+ this.phase = phase;
+ }
+
+
+ // Implementation for Timing.
+
+ public double getTiming(long time)
+ {
+ // Compute the translated and scaled sine function.
+ return 0.5 + 0.5 * Math.sin(2.0 * Math.PI * (time + phase) / period);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SmoothTiming.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SmoothTiming.java
new file mode 100644
index 0000000000..8e172996e0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SmoothTiming.java
@@ -0,0 +1,66 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This Timing ramps up smoothly from 0 to 1 in a given time interval.
+ *
+ * @author Eric Lafortune
+ */
+public class SmoothTiming implements Timing
+{
+ private final long fromTime;
+ private final long toTime;
+
+
+ /**
+ * Creates a new SmoothTiming.
+ * @param fromTime the time at which the timing starts ramping up from 0.
+ * @param toTime the time at which the timing stops ramping up at 1.
+ */
+ public SmoothTiming(long fromTime, long toTime)
+ {
+ this.fromTime = fromTime;
+ this.toTime = toTime;
+ }
+
+
+ // Implementation for Timing.
+
+ public double getTiming(long time)
+ {
+ if (time <= fromTime)
+ {
+ return 0.0;
+ }
+
+ if (time >= toTime)
+ {
+ return 1.0;
+ }
+
+ // Compute the linear interpolation.
+ double timing = (double) (time - fromTime) / (double) (toTime - fromTime);
+
+ // Smooth the interpolation at the ends.
+ return timing * timing * (3.0 - 2.0 * timing);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SplashPanel.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SplashPanel.java
new file mode 100644
index 0000000000..bcb124ea62
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/SplashPanel.java
@@ -0,0 +1,235 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import proguard.gui.SwingUtil;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * This JPanel renders an animated Sprite.
+ *
+ * @author Eric Lafortune
+ */
+public class SplashPanel extends JPanel
+{
+ private final MyAnimator animator = new MyAnimator();
+ private final MyRepainter repainter = new MyRepainter();
+
+ private final Sprite sprite;
+ private final double sleepFactor;
+
+ private long startTime = Long.MAX_VALUE;
+ private final long stopTime;
+
+ private volatile Thread animationThread;
+
+
+ /**
+ * Creates a new SplashPanel with the given Sprite, which will be animated
+ * indefinitely.
+ * @param sprite the Sprite that will be animated.
+ * @param processorLoad the fraction of processing time to be spend on
+ * animating the Sprite (between 0 and 1).
+ */
+ public SplashPanel(Sprite sprite, double processorLoad)
+ {
+ this(sprite, processorLoad, (long)Integer.MAX_VALUE);
+ }
+
+
+ /**
+ * Creates a new SplashPanel with the given Sprite, which will be animated
+ * for a limited period of time.
+ * @param sprite the Sprite that will be animated.
+ * @param processorLoad the fraction of processing time to be spend on
+ * animating the Sprite (between 0 and 1).
+ * @param stopTime the number of milliseconds after which the
+ * animation will be stopped automatically.
+ */
+ public SplashPanel(Sprite sprite, double processorLoad, long stopTime)
+ {
+ this.sprite = sprite;
+ this.sleepFactor = (1.0-processorLoad) / processorLoad;
+ this.stopTime = stopTime;
+
+ // Restart the animation on a mouse click.
+ addMouseListener(new MouseAdapter()
+ {
+ public void mouseClicked(MouseEvent e)
+ {
+ SplashPanel.this.start();
+ }
+ });
+ }
+
+
+ /**
+ * Starts the animation.
+ */
+ public void start()
+ {
+ // Go to the beginning of the animation.
+ startTime = System.currentTimeMillis();
+
+ // Make sure we have an animation thread running.
+ if (animationThread == null)
+ {
+ animationThread = new Thread(animator);
+ animationThread.start();
+ }
+ }
+
+
+ /**
+ * Stops the animation.
+ */
+ public void stop()
+ {
+ // Go to the end of the animation.
+ startTime = 0L;
+
+ // Let the animation thread stop itself.
+ animationThread = null;
+
+ // Repaint the SplashPanel one last time.
+ try
+ {
+ SwingUtil.invokeAndWait(repainter);
+ }
+ catch (InterruptedException ex)
+ {
+ // Nothing.
+ }
+ catch (InvocationTargetException ex)
+ {
+ // Nothing.
+ }
+ }
+
+
+ // Implementation for JPanel.
+
+ public void paintComponent(Graphics graphics)
+ {
+ super.paintComponent(graphics);
+
+ sprite.paint(graphics, System.currentTimeMillis() - startTime);
+ }
+
+
+ /**
+ * This Runnable makes sure its SplashPanel gets repainted regularly,
+ * depending on the targeted processor load.
+ */
+ private class MyAnimator implements Runnable
+ {
+ public void run()
+ {
+ try
+ {
+ while (animationThread != null)
+ {
+ // Check if we should stop the animation.
+ long time = System.currentTimeMillis();
+ if (time > startTime + stopTime)
+ {
+ animationThread = null;
+ }
+
+ // Do a repaint and time it.
+ SwingUtil.invokeAndWait(repainter);
+
+ // Sleep for a proportional while.
+ long repaintTime = System.currentTimeMillis() - time;
+ long sleepTime = (long)(sleepFactor * repaintTime);
+ if (sleepTime < 10L)
+ {
+ sleepTime = 10L;
+ }
+
+ Thread.sleep(sleepTime);
+ }
+ }
+ catch (InterruptedException ex)
+ {
+ // Nothing.
+ }
+ catch (InvocationTargetException ex)
+ {
+ // Nothing.
+ }
+ }
+ }
+
+
+ /**
+ * This Runnable repaints its SplashPanel.
+ */
+ private class MyRepainter implements Runnable
+ {
+ public void run()
+ {
+ SplashPanel.this.repaint();
+ }
+ }
+
+
+ /**
+ * A main method for testing the splash panel.
+ */
+ public static void main(String[] args)
+ {
+ JFrame frame = new JFrame();
+ frame.setTitle("Animation");
+ frame.setSize(800, 600);
+ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension frameSize = frame.getSize();
+ frame.setLocation((screenSize.width - frameSize.width) / 2,
+ (screenSize.height - frameSize.height) / 2);
+
+ Sprite sprite =
+ new ClipSprite(
+ new ConstantColor(Color.white),
+ new ConstantColor(Color.lightGray),
+ new CircleSprite(true,
+ new LinearInt(200, 600, new SineTiming(2345L, 0L)),
+ new LinearInt(200, 400, new SineTiming(3210L, 0L)),
+ new ConstantInt(150)),
+ new ColorSprite(new ConstantColor(Color.gray),
+ new FontSprite(new ConstantFont(new Font("sansserif", Font.BOLD, 90)),
+ new TextSprite(new ConstantString("ProGuard"),
+ new ConstantInt(200),
+ new ConstantInt(300)))));
+
+ SplashPanel panel = new SplashPanel(sprite, 0.5);
+ panel.setBackground(Color.white);
+
+ frame.getContentPane().add(panel);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setVisible(true);
+
+ panel.start();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/Sprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/Sprite.java
new file mode 100644
index 0000000000..c80b3d2325
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/Sprite.java
@@ -0,0 +1,41 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This interface describes objects that can paint themselves, possibly varying
+ * as a function of time.
+ *
+ * @author Eric Lafortune
+ */
+public interface Sprite
+{
+ /**
+ * Paints the object.
+ *
+ * @param graphics the Graphics to paint on.
+ * @param time the time since the start of the animation, expressed in
+ * milliseconds.
+ */
+ public void paint(Graphics graphics, long time);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TextSprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TextSprite.java
new file mode 100644
index 0000000000..fdfbc21c25
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TextSprite.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This Sprite represents a text.
+ *
+ * @author Eric Lafortune
+ */
+public class TextSprite implements Sprite
+{
+ private final VariableString[] text;
+ private final VariableInt spacing;
+ private final VariableInt x;
+ private final VariableInt y;
+
+
+ /**
+ * Creates a new TextSprite containing a single line of text.
+ * @param text the variable text string.
+ * @param x the variable x-coordinate of the lower-left corner of the text.
+ * @param y the variable y-coordinate of the lower-left corner of the text.
+ */
+ public TextSprite(VariableString text,
+ VariableInt x,
+ VariableInt y)
+ {
+ this(new VariableString[] { text }, new ConstantInt(0), x, y);
+ }
+
+
+ /**
+ * Creates a new TextSprite containing a multiple lines of text.
+ * @param text the variable text strings.
+ * @param spacing the variable spacing between the lines of text.
+ * @param x the variable x-coordinate of the lower-left corner of the
+ * first line of text.
+ * @param y the variable y-coordinate of the lower-left corner of the
+ * first line of text.
+ */
+ public TextSprite(VariableString[] text,
+ VariableInt spacing,
+ VariableInt x,
+ VariableInt y)
+ {
+
+ this.text = text;
+ this.spacing = spacing;
+ this.x = x;
+ this.y = y;
+ }
+
+
+ // Implementation for Sprite.
+
+ public void paint(Graphics graphics, long time)
+ {
+
+ int xt = x.getInt(time);
+ int yt = y.getInt(time);
+
+ int spacingt = spacing.getInt(time);
+
+ for (int index = 0; index < text.length; index++)
+ {
+ graphics.drawString(text[index].getString(time), xt, yt + index * spacingt);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TimeSwitchSprite.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TimeSwitchSprite.java
new file mode 100644
index 0000000000..9a92e66ff2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TimeSwitchSprite.java
@@ -0,0 +1,75 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This Sprite displays another Sprite in a given time interval.
+ * The time of the encapsulated Sprite is shifted by the start time.
+ *
+ * @author Eric Lafortune
+ */
+public class TimeSwitchSprite implements Sprite
+{
+ private final long onTime;
+ private final long offTime;
+ private final Sprite sprite;
+
+
+ /**
+ * Creates a new TimeSwitchSprite for displaying a given Sprite starting at
+ * a given time.
+ * @param onTime the start time.
+ * @param sprite the toggled Sprite.
+ */
+ public TimeSwitchSprite(long onTime, Sprite sprite)
+ {
+ this(onTime, 0L, sprite);
+ }
+
+
+ /**
+ * Creates a new TimeSwitchSprite for displaying a given Sprite in a given
+ * time interval.
+ * @param onTime the start time.
+ * @param offTime the stop time.
+ * @param sprite the toggled Sprite.
+ */
+ public TimeSwitchSprite(long onTime, long offTime, Sprite sprite)
+ {
+ this.onTime = onTime;
+ this.offTime = offTime;
+ this.sprite = sprite;
+ }
+
+
+ // Implementation for Sprite.
+
+ public void paint(Graphics graphics, long time)
+ {
+ if (time >= onTime && (offTime <= 0 || time <= offTime))
+ {
+ sprite.paint(graphics, time - onTime);
+ }
+
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/Timing.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/Timing.java
new file mode 100644
index 0000000000..b21e725a28
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/Timing.java
@@ -0,0 +1,34 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This interface maps a time to a normalized timing between 0 and 1.
+ *
+ * @author Eric Lafortune
+ */
+interface Timing
+{
+ /**
+ * Returns the timing for the given time.
+ */
+ public double getTiming(long time);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TypeWriterString.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TypeWriterString.java
new file mode 100644
index 0000000000..e1b1202624
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/TypeWriterString.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This VariableString produces a String that grows linearly with respect to its
+ * Timing, as if it is being written on a typewriter. A cursor at the end
+ * precedes the typed characters.
+ *
+ * @author Eric Lafortune
+ */
+public class TypeWriterString implements VariableString
+{
+ private final String string;
+ private final Timing timing;
+
+ private int cachedLength = -1;
+ private String cachedString;
+
+
+ /**
+ * Creates a new TypeWriterString.
+ * @param string the basic String.
+ * @param timing the applied timing.
+ */
+ public TypeWriterString(String string, Timing timing)
+ {
+ this.string = string;
+ this.timing = timing;
+ }
+
+
+ // Implementation for VariableString.
+
+ public String getString(long time)
+ {
+ double t = timing.getTiming(time);
+
+ int stringLength = string.length();
+ int length = (int)(stringLength * t + 0.5);
+ if (length != cachedLength)
+ {
+ cachedLength = length;
+ cachedString = string.substring(0, length);
+ if (t > 0.0 && length < stringLength)
+ {
+ cachedString += "_";
+ }
+ }
+
+ return cachedString;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableColor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableColor.java
new file mode 100644
index 0000000000..73dbd57161
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableColor.java
@@ -0,0 +1,36 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This interface represents a Color that varies with time.
+ *
+ * @author Eric Lafortune
+ */
+interface VariableColor
+{
+ /**
+ * Returns the Color for the given time.
+ */
+ public Color getColor(long time);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableDouble.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableDouble.java
new file mode 100644
index 0000000000..28d89732f5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableDouble.java
@@ -0,0 +1,34 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This interface represents a double that varies with time.
+ *
+ * @author Eric Lafortune
+ */
+interface VariableDouble
+{
+ /**
+ * Returns the double for the given time.
+ */
+ public double getDouble(long time);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableFont.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableFont.java
new file mode 100644
index 0000000000..92cde2f45f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableFont.java
@@ -0,0 +1,36 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This interface represents a Font that varies with time.
+ *
+ * @author Eric Lafortune
+ */
+interface VariableFont
+{
+ /**
+ * Returns the Font for the given time.
+ */
+ public Font getFont(long time);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableInt.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableInt.java
new file mode 100644
index 0000000000..d81f0a8529
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableInt.java
@@ -0,0 +1,34 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This interface represents an integer that varies with time.
+ *
+ * @author Eric Lafortune
+ */
+interface VariableInt
+{
+ /**
+ * Returns the integer for the given time.
+ */
+ public int getInt(long time);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableSizeFont.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableSizeFont.java
new file mode 100644
index 0000000000..5fc9cb28f2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableSizeFont.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+import java.awt.*;
+
+/**
+ * This VariableFont varies in size with respect to its Timing.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableSizeFont implements VariableFont
+{
+ private final Font font;
+ private final VariableDouble size;
+
+ private float cachedSize = -1.0f;
+ private Font cachedFont;
+
+
+ /**
+ * Creates a new VariableSizeFont
+ * @param font the base font.
+ * @param size the variable size of the font.
+ */
+ public VariableSizeFont(Font font, VariableDouble size)
+ {
+ this.font = font;
+ this.size = size;
+ }
+
+
+ // Implementation for VariableFont.
+
+ public Font getFont(long time)
+ {
+ float s = (float)size.getDouble(time);
+
+ if (s != cachedSize)
+ {
+ cachedSize = s;
+ cachedFont = font.deriveFont((float)s);
+ }
+
+ return cachedFont;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableString.java b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableString.java
new file mode 100644
index 0000000000..1e3cad7230
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/VariableString.java
@@ -0,0 +1,34 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.gui.splash;
+
+/**
+ * This interface represents a String that varies with time.
+ *
+ * @author Eric Lafortune
+ */
+interface VariableString
+{
+ /**
+ * Returns the String for the given time.
+ */
+ public String getString(long time);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/package.html
new file mode 100644
index 0000000000..209fad7c1a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/splash/package.html
@@ -0,0 +1,4 @@
+<body>
+This package contains a library for creating splash screens and animations
+with text, graphical elements, and some special effects.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/gui/vtitle.png b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/vtitle.png
new file mode 100644
index 0000000000..218f71620e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/gui/vtitle.png
Binary files differ
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/CascadingDataEntryWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/CascadingDataEntryWriter.java
new file mode 100644
index 0000000000..bb1c85188f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/CascadingDataEntryWriter.java
@@ -0,0 +1,94 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.*;
+
+/**
+ * This DataEntryWriter delegates to a given DataEntryWriter, or failing that,
+ * to another given DataEntryWriter.
+ *
+ * @author Eric Lafortune
+ */
+public class CascadingDataEntryWriter implements DataEntryWriter
+{
+ private DataEntryWriter dataEntryWriter1;
+ private DataEntryWriter dataEntryWriter2;
+
+
+ /**
+ * Creates a new CascadingDataEntryWriter.
+ * @param dataEntryWriter1 the DataEntryWriter to which the writing will be
+ * delegated first.
+ * @param dataEntryWriter2 the DataEntryWriter to which the writing will be
+ * delegated, if the first one can't provide an
+ * output stream.
+ */
+ public CascadingDataEntryWriter(DataEntryWriter dataEntryWriter1,
+ DataEntryWriter dataEntryWriter2)
+ {
+ this.dataEntryWriter1 = dataEntryWriter1;
+ this.dataEntryWriter2 = dataEntryWriter2;
+ }
+
+
+ // Implementations for DataEntryWriter.
+
+
+ public boolean createDirectory(DataEntry dataEntry) throws IOException
+ {
+ // Try to create a directory with the first data entry writer, or
+ // otherwise with the second data entry writer.
+ return dataEntryWriter1.createDirectory(dataEntry) ||
+ dataEntryWriter2.createDirectory(dataEntry);
+ }
+
+
+ public OutputStream getOutputStream(DataEntry dataEntry) throws IOException
+ {
+ return getOutputStream(dataEntry, null);
+ }
+
+
+ public OutputStream getOutputStream(DataEntry dataEntry,
+ Finisher finisher) throws IOException
+ {
+ // Try to get an output stream from the first data entry writer.
+ OutputStream outputStream =
+ dataEntryWriter1.getOutputStream(dataEntry, finisher);
+
+ // Return it, if it's not null. Otherwise try to get an output stream
+ // from the second data entry writer.
+ return outputStream != null ?
+ outputStream :
+ dataEntryWriter2.getOutputStream(dataEntry, finisher);
+ }
+
+
+ public void close() throws IOException
+ {
+ dataEntryWriter1.close();
+ dataEntryWriter2.close();
+
+ dataEntryWriter1 = null;
+ dataEntryWriter2 = null;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassFilter.java
new file mode 100644
index 0000000000..f5a78a37de
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassFilter.java
@@ -0,0 +1,57 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.ClassConstants;
+import proguard.util.ExtensionMatcher;
+
+
+/**
+ * This DataEntryReader delegates to one of two other DataEntryReader instances,
+ * depending on the extension of the data entry.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassFilter extends FilteredDataEntryReader
+{
+ /**
+ * Creates a new ClassFilter that delegates reading classes to the
+ * given reader.
+ */
+ public ClassFilter(DataEntryReader classReader)
+ {
+ this(classReader, null);
+ }
+
+
+ /**
+ * Creates a new ClassFilter that delegates to either of the two given
+ * readers.
+ */
+ public ClassFilter(DataEntryReader classReader,
+ DataEntryReader dataEntryReader)
+ {
+ super(new DataEntryNameFilter(
+ new ExtensionMatcher(ClassConstants.CLASS_FILE_EXTENSION)),
+ classReader,
+ dataEntryReader);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassReader.java
new file mode 100644
index 0000000000..fbb900ffd9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassReader.java
@@ -0,0 +1,115 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.*;
+import proguard.classfile.io.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.io.*;
+
+/**
+ * This DataEntryReader applies a given ClassVisitor to the class
+ * definitions that it reads.
+ * <p>
+ * Class files are read as ProgramClass objects or LibraryClass objects,
+ * depending on the <code>isLibrary</code> flag.
+ * <p>
+ * In case of libraries, only public classes are considered, if the
+ * <code>skipNonPublicLibraryClasses</code> flag is set.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassReader implements DataEntryReader
+{
+ private final boolean isLibrary;
+ private final boolean skipNonPublicLibraryClasses;
+ private final boolean skipNonPublicLibraryClassMembers;
+ private final WarningPrinter warningPrinter;
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new DataEntryClassFilter for reading the specified
+ * Clazz objects.
+ */
+ public ClassReader(boolean isLibrary,
+ boolean skipNonPublicLibraryClasses,
+ boolean skipNonPublicLibraryClassMembers,
+ WarningPrinter warningPrinter,
+ ClassVisitor classVisitor)
+ {
+ this.isLibrary = isLibrary;
+ this.skipNonPublicLibraryClasses = skipNonPublicLibraryClasses;
+ this.skipNonPublicLibraryClassMembers = skipNonPublicLibraryClassMembers;
+ this.warningPrinter = warningPrinter;
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for DataEntryReader.
+
+ public void read(DataEntry dataEntry) throws IOException
+ {
+ try
+ {
+ // Get the input stream.
+ InputStream inputStream = dataEntry.getInputStream();
+
+ // Wrap it into a data input stream.
+ DataInputStream dataInputStream = new DataInputStream(inputStream);
+
+ // Create a Clazz representation.
+ Clazz clazz;
+ if (isLibrary)
+ {
+ clazz = new LibraryClass();
+ clazz.accept(new LibraryClassReader(dataInputStream, skipNonPublicLibraryClasses, skipNonPublicLibraryClassMembers));
+ }
+ else
+ {
+ clazz = new ProgramClass();
+ clazz.accept(new ProgramClassReader(dataInputStream));
+ }
+
+ // Apply the visitor, if we have a real class.
+ String className = clazz.getName();
+ if (className != null)
+ {
+ if (!dataEntry.getName().replace(File.pathSeparatorChar, ClassConstants.PACKAGE_SEPARATOR).equals(className+ClassConstants.CLASS_FILE_EXTENSION) &&
+ warningPrinter != null)
+ {
+ warningPrinter.print(className,
+ "Warning: class [" + dataEntry.getName() + "] unexpectedly contains class [" + ClassUtil.externalClassName(className) + "]");
+ }
+
+ clazz.accept(classVisitor);
+ }
+
+ dataEntry.closeInputStream();
+ }
+ catch (Exception ex)
+ {
+ throw (IOException)new IOException("Can't process class ["+dataEntry.getName()+"] ("+ex.getMessage()+")").initCause(ex);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassRewriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassRewriter.java
new file mode 100644
index 0000000000..8f5b8cf3eb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ClassRewriter.java
@@ -0,0 +1,80 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.*;
+import proguard.classfile.io.ProgramClassWriter;
+
+import java.io.*;
+
+
+/**
+ * This DataEntryReader reads class entries and writes their corresponding
+ * versions from the ClassPool to a given DataEntryWriter.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassRewriter implements DataEntryReader
+{
+ private final ClassPool classPool;
+ private final DataEntryWriter dataEntryWriter;
+
+
+ public ClassRewriter(ClassPool classPool,
+ DataEntryWriter dataEntryWriter)
+ {
+ this.classPool = classPool;
+ this.dataEntryWriter = dataEntryWriter;
+ }
+
+
+ // Implementations for DataEntryReader.
+
+ public void read(DataEntry dataEntry) throws IOException
+ {
+ String inputName = dataEntry.getName();
+ String className = inputName.substring(0, inputName.length() - ClassConstants.CLASS_FILE_EXTENSION.length());
+
+ // Find the modified class corrsponding to the input entry.
+ ProgramClass programClass = (ProgramClass)classPool.getClass(className);
+ if (programClass != null)
+ {
+ // Rename the data entry if necessary.
+ String newClassName = programClass.getName();
+ if (!className.equals(newClassName))
+ {
+ dataEntry = new RenamedDataEntry(dataEntry, newClassName + ClassConstants.CLASS_FILE_EXTENSION);
+ }
+
+ // Get the output entry corresponding to this input entry.
+ OutputStream outputStream = dataEntryWriter.getOutputStream(dataEntry);
+ if (outputStream != null)
+ {
+ // Write the class to the output entry.
+ DataOutputStream classOutputStream = new DataOutputStream(outputStream);
+
+ new ProgramClassWriter(classOutputStream).visitProgramClass(programClass);
+
+ classOutputStream.flush();
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntry.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntry.java
new file mode 100644
index 0000000000..7ce278ab98
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntry.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.*;
+
+/**
+ * This interface describes a data entry, e.g. a ZIP entry, a file, or a
+ * directory.
+ *
+ * @author Eric Lafortune
+ */
+public interface DataEntry
+{
+ /**
+ * Returns the name of this data entry.
+ */
+ public String getName();
+
+ /**
+ * Returns whether the data entry represents a directory.
+ */
+ public boolean isDirectory();
+
+
+ /**
+ * Returns an input stream for reading the content of this data entry.
+ * The data entry may not represent a directory.
+ */
+ public InputStream getInputStream() throws IOException;
+
+
+ /**
+ * Closes the previously retrieved InputStream.
+ */
+ public void closeInputStream() throws IOException;
+
+
+ /**
+ * Returns the parent of this data entry, or <code>null</null> if it doesn't
+ * have one.
+ */
+ public DataEntry getParent();
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryClassWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryClassWriter.java
new file mode 100644
index 0000000000..2a078718d0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryClassWriter.java
@@ -0,0 +1,85 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.*;
+import proguard.classfile.io.ProgramClassWriter;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.io.*;
+
+/**
+ * This ClassVisitor writes out the ProgramClass objects that it visits to the
+ * given DataEntry, modified to have the correct name.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryClassWriter
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final DataEntryWriter dataEntryWriter;
+ private final DataEntry templateDataEntry;
+
+
+ /**
+ * Creates a new DataEntryClassWriter for writing to the given
+ * DataEntryWriter, based on the given template DataEntry.
+ */
+ public DataEntryClassWriter(DataEntryWriter dataEntryWriter,
+ DataEntry templateDataEntry)
+ {
+ this.dataEntryWriter = dataEntryWriter;
+ this.templateDataEntry = templateDataEntry;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Rename the data entry if necessary.
+ String actualClassName = programClass.getName();
+ DataEntry actualDataEntry =
+ new RenamedDataEntry(templateDataEntry,
+ actualClassName + ClassConstants.CLASS_FILE_EXTENSION);
+
+ try
+ {
+ // Get the output entry corresponding to this input entry.
+ OutputStream outputStream = dataEntryWriter.getOutputStream(actualDataEntry);
+ if (outputStream != null)
+ {
+ // Write the class to the output entry.
+ DataOutputStream classOutputStream = new DataOutputStream(outputStream);
+
+ new ProgramClassWriter(classOutputStream).visitProgramClass(programClass);
+
+ classOutputStream.flush();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Can't write program class ["+actualClassName+"] to ["+actualDataEntry+"] ("+e.getMessage()+")", e);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryCopier.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryCopier.java
new file mode 100644
index 0000000000..3915960561
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryCopier.java
@@ -0,0 +1,360 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.util.ExtensionMatcher;
+
+import java.io.*;
+
+
+/**
+ * This DataEntryReader writes the ZIP entries and files that it reads to a
+ * given DataEntryWriter.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryCopier implements DataEntryReader
+{
+ private static final int BUFFER_SIZE = 1024;
+
+ private final DataEntryWriter dataEntryWriter;
+ private final byte[] buffer = new byte[BUFFER_SIZE];
+
+
+
+ public DataEntryCopier(DataEntryWriter dataEntryWriter)
+ {
+ this.dataEntryWriter = dataEntryWriter;
+ }
+
+
+ // Implementations for DataEntryReader.
+
+ public void read(DataEntry dataEntry) throws IOException
+ {
+ try
+ {
+ if (dataEntry.isDirectory())
+ {
+ dataEntryWriter.createDirectory(dataEntry);
+ }
+ else
+ {
+ // Get the output entry corresponding to this input entry.
+ OutputStream outputStream = dataEntryWriter.getOutputStream(dataEntry);
+ if (outputStream != null)
+ {
+ InputStream inputStream = dataEntry.getInputStream();
+
+ try
+ {
+ // Copy the data from the input entry to the output entry.
+ copyData(inputStream, outputStream);
+ }
+ finally
+ {
+ // Close the data entries.
+ dataEntry.closeInputStream();
+ }
+ }
+ }
+ }
+ catch (IOException ex)
+ {
+ System.err.println("Warning: can't write resource [" + dataEntry.getName() + "] (" + ex.getMessage() + ")");
+ }
+ catch (Exception ex)
+ {
+ throw (IOException)new IOException("Can't write resource ["+dataEntry.getName()+"] ("+ex.getMessage()+")").initCause(ex);
+ }
+ }
+
+
+ /**
+ * Copies all data that it can read from the given input stream to the
+ * given output stream.
+ */
+ protected void copyData(InputStream inputStream,
+ OutputStream outputStream)
+ throws IOException
+ {
+ while (true)
+ {
+ int count = inputStream.read(buffer);
+ if (count < 0)
+ {
+ break;
+ }
+ outputStream.write(buffer, 0, count);
+ }
+
+ outputStream.flush();
+ }
+
+
+ /**
+ * A main method for testing file/jar/war/directory copying.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ String input = args[0];
+ String output = args[1];
+
+ boolean outputIsApk = output.endsWith(".apk") ||
+ output.endsWith(".ap_");
+ boolean outputIsJar = output.endsWith(".jar");
+ boolean outputIsAar = output.endsWith(".aar");
+ boolean outputIsWar = output.endsWith(".war");
+ boolean outputIsEar = output.endsWith(".ear");
+ boolean outputIsZip = output.endsWith(".zip");
+
+ DataEntryWriter writer = new DirectoryWriter(new File(output),
+ outputIsApk ||
+ outputIsJar ||
+ outputIsAar ||
+ outputIsWar ||
+ outputIsEar ||
+ outputIsZip);
+
+ // Zip up any zips, if necessary.
+ DataEntryWriter zipWriter = new JarWriter(writer);
+ if (outputIsZip)
+ {
+ // Always zip.
+ writer = zipWriter;
+ }
+ else
+ {
+ // Only zip up zips.
+ writer = new FilteredDataEntryWriter(new DataEntryParentFilter(
+ new DataEntryNameFilter(
+ new ExtensionMatcher(".zip"))),
+ zipWriter,
+ writer);
+ }
+
+ // Zip up any ears, if necessary.
+ DataEntryWriter earWriter = new JarWriter(writer);
+ if (outputIsEar)
+ {
+ // Always zip.
+ writer = earWriter;
+ }
+ else
+ {
+ // Only zip up ears.
+ writer = new FilteredDataEntryWriter(new DataEntryParentFilter(
+ new DataEntryNameFilter(
+ new ExtensionMatcher(".ear"))),
+ earWriter,
+ writer);
+ }
+
+ // Zip up any wars, if necessary.
+ DataEntryWriter warWriter = new JarWriter(writer);
+ if (outputIsWar)
+ {
+ // Always zip.
+ writer = warWriter;
+ }
+ else
+ {
+ // Only zip up wars.
+ writer = new FilteredDataEntryWriter(new DataEntryParentFilter(
+ new DataEntryNameFilter(
+ new ExtensionMatcher(".war"))),
+ warWriter,
+ writer);
+ }
+
+ // Zip up any aars, if necessary.
+ DataEntryWriter aarWriter = new JarWriter(writer);
+ if (outputIsAar)
+ {
+ // Always zip.
+ writer = aarWriter;
+ }
+ else
+ {
+ // Only zip up aars.
+ writer = new FilteredDataEntryWriter(new DataEntryParentFilter(
+ new DataEntryNameFilter(
+ new ExtensionMatcher(".aar"))),
+ aarWriter,
+ writer);
+ }
+
+ // Zip up any jars, if necessary.
+ DataEntryWriter jarWriter = new JarWriter(writer);
+ if (outputIsJar)
+ {
+ // Always zip.
+ writer = jarWriter;
+ }
+ else
+ {
+ // Only zip up jars.
+ writer = new FilteredDataEntryWriter(new DataEntryParentFilter(
+ new DataEntryNameFilter(
+ new ExtensionMatcher(".jar"))),
+ jarWriter,
+ writer);
+ }
+
+ // Zip up any apks, if necessary.
+ DataEntryWriter apkWriter = new JarWriter(writer);
+ if (outputIsApk)
+ {
+ // Always zip.
+ writer = apkWriter;
+ }
+ else
+ {
+ // Only zip up apks.
+ writer = new FilteredDataEntryWriter(new DataEntryParentFilter(
+ new DataEntryNameFilter(
+ new ExtensionMatcher(".apk"))),
+ apkWriter,
+ writer);
+ }
+
+
+ // Create the copying DataEntryReader.
+ DataEntryReader reader = new DataEntryCopier(writer);
+
+ boolean inputIsApk = input.endsWith(".apk") ||
+ input.endsWith(".ap_");
+ boolean inputIsJar = input.endsWith(".jar");
+ boolean inputIsAar = input.endsWith(".aar");
+ boolean inputIsWar = input.endsWith(".war");
+ boolean inputIsEar = input.endsWith(".ear");
+ boolean inputIsZip = input.endsWith(".zip");
+
+ // Unzip any apks, if necessary.
+ DataEntryReader apkReader = new JarReader(reader);
+ if (inputIsApk)
+ {
+ // Always unzip.
+ reader = apkReader;
+ }
+ else
+ {
+ // Only unzip apk entries.
+ reader = new FilteredDataEntryReader(new DataEntryNameFilter(
+ new ExtensionMatcher(".apk")),
+ apkReader,
+ reader);
+
+ // Unzip any jars, if necessary.
+ DataEntryReader jarReader = new JarReader(reader);
+ if (inputIsJar)
+ {
+ // Always unzip.
+ reader = jarReader;
+ }
+ else
+ {
+ // Only unzip jar entries.
+ reader = new FilteredDataEntryReader(new DataEntryNameFilter(
+ new ExtensionMatcher(".jar")),
+ jarReader,
+ reader);
+
+ // Unzip any aars, if necessary.
+ DataEntryReader aarReader = new JarReader(reader);
+ if (inputIsAar)
+ {
+ // Always unzip.
+ reader = aarReader;
+ }
+ else
+ {
+ // Only unzip aar entries.
+ reader = new FilteredDataEntryReader(new DataEntryNameFilter(
+ new ExtensionMatcher(".aar")),
+ aarReader,
+ reader);
+
+ // Unzip any wars, if necessary.
+ DataEntryReader warReader = new JarReader(reader);
+ if (inputIsWar)
+ {
+ // Always unzip.
+ reader = warReader;
+ }
+ else
+ {
+ // Only unzip war entries.
+ reader = new FilteredDataEntryReader(new DataEntryNameFilter(
+ new ExtensionMatcher(".war")),
+ warReader,
+ reader);
+
+ // Unzip any ears, if necessary.
+ DataEntryReader earReader = new JarReader(reader);
+ if (inputIsEar)
+ {
+ // Always unzip.
+ reader = earReader;
+ }
+ else
+ {
+ // Only unzip ear entries.
+ reader = new FilteredDataEntryReader(new DataEntryNameFilter(
+ new ExtensionMatcher(".ear")),
+ earReader,
+ reader);
+
+ // Unzip any zips, if necessary.
+ DataEntryReader zipReader = new JarReader(reader);
+ if (inputIsZip)
+ {
+ // Always unzip.
+ reader = zipReader;
+ }
+ else
+ {
+ // Only unzip zip entries.
+ reader = new FilteredDataEntryReader(new DataEntryNameFilter(
+ new ExtensionMatcher(".zip")),
+ zipReader,
+ reader);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ DirectoryPump directoryReader = new DirectoryPump(new File(input));
+
+ directoryReader.pumpDataEntries(reader);
+
+ writer.close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryDirectoryFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryDirectoryFilter.java
new file mode 100644
index 0000000000..beefc3b726
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryDirectoryFilter.java
@@ -0,0 +1,38 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+/**
+ * This DataEntryFilter filters data entries based on whether they represent
+ * directories.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryDirectoryFilter
+implements DataEntryFilter
+{
+ // Implementations for DataEntryFilter.
+
+ public boolean accepts(DataEntry dataEntry)
+ {
+ return dataEntry != null && dataEntry.isDirectory();
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryFilter.java
new file mode 100644
index 0000000000..fe9f647780
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryFilter.java
@@ -0,0 +1,38 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+
+/**
+ * This interface provides a method to filter data entries.
+ *
+ * @author Eric Lafortune
+ */
+public interface DataEntryFilter
+{
+ /**
+ * Checks whether the filter accepts the given data entry.
+ * @param dataEntry the data entry to filter.
+ * @return a boolean indicating whether the filter accepts the given data
+ * entry.
+ */
+ public boolean accepts(DataEntry dataEntry);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryNameFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryNameFilter.java
new file mode 100644
index 0000000000..e7f65c00f7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryNameFilter.java
@@ -0,0 +1,54 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.util.StringMatcher;
+
+/**
+ * This DataEntryFilter filters data entries based on whether their names match
+ * a given StringMatcher.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryNameFilter
+implements DataEntryFilter
+{
+ private final StringMatcher stringMatcher;
+
+
+ /**
+ * Creates a new DataEntryNameFilter.
+ * @param stringMatcher the string matcher that will be applied to the names
+ * of the filtered data entries.
+ */
+ public DataEntryNameFilter(StringMatcher stringMatcher)
+ {
+ this.stringMatcher = stringMatcher;
+ }
+
+
+ // Implementations for DataEntryFilter.
+
+ public boolean accepts(DataEntry dataEntry)
+ {
+ return dataEntry != null && stringMatcher.matches(dataEntry.getName());
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryObfuscator.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryObfuscator.java
new file mode 100644
index 0000000000..05a02156c9
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryObfuscator.java
@@ -0,0 +1,150 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * This DataEntryReader delegates to another DataEntryReader, renaming the
+ * data entries based on the renamed classes in the given ClassPool.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryObfuscator implements DataEntryReader
+{
+ private final ClassPool classPool;
+ private final Map packagePrefixMap;
+ private final DataEntryReader dataEntryReader;
+
+
+ /**
+ * Creates a new DataEntryObfuscator.
+ * @param classPool the class pool that maps from old names to new
+ * names.
+ * @param packagePrefixMap the map from old package prefixes to new package
+ * prefixes.
+ * @param dataEntryReader the DataEntryReader to which calls will be
+ * delegated.
+ */
+ public DataEntryObfuscator(ClassPool classPool,
+ Map packagePrefixMap,
+ DataEntryReader dataEntryReader)
+ {
+ this.classPool = classPool;
+ this.packagePrefixMap = packagePrefixMap;
+ this.dataEntryReader = dataEntryReader;
+ }
+
+
+ // Implementations for DataEntryReader.
+
+ public void read(DataEntry dataEntry) throws IOException
+ {
+ // Delegate to the actual data entry reader.
+ dataEntryReader.read(renamedDataEntry(dataEntry));
+ }
+
+
+ /**
+ * Create a renamed data entry, if possible.
+ */
+ private DataEntry renamedDataEntry(DataEntry dataEntry)
+ {
+ String dataEntryName = dataEntry.getName();
+
+ // Try to find a corresponding class name by removing increasingly
+ // long suffixes.
+ for (int suffixIndex = dataEntryName.length() - 1;
+ suffixIndex > 0;
+ suffixIndex--)
+ {
+ char c = dataEntryName.charAt(suffixIndex);
+ if (!Character.isLetterOrDigit(c))
+ {
+ // Chop off the suffix.
+ String className = dataEntryName.substring(0, suffixIndex);
+
+ // Did we get to the package separator?
+ if (c == ClassConstants.PACKAGE_SEPARATOR)
+ {
+ break;
+ }
+
+ // Is there a class corresponding to the data entry?
+ Clazz clazz = classPool.getClass(className);
+ if (clazz != null)
+ {
+ // Did the class get a new name?
+ String newClassName = clazz.getName();
+ if (!className.equals(newClassName))
+ {
+ // Return a renamed data entry.
+ String newDataEntryName =
+ newClassName + dataEntryName.substring(suffixIndex);
+
+ return new RenamedDataEntry(dataEntry, newDataEntryName);
+ }
+ else
+ {
+ // Otherwise stop looking.
+ return dataEntry;
+ }
+ }
+ }
+ }
+
+ // Try to find a corresponding package name by increasingly removing
+ // more subpackages.
+ String packagePrefix = dataEntryName;
+ do
+ {
+ // Chop off the class name or the last subpackage name.
+ packagePrefix = ClassUtil.internalPackagePrefix(packagePrefix);
+
+ // Is there a package corresponding to the package prefix?
+ String newPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
+ if (newPackagePrefix != null)
+ {
+ // Did the package get a new name?
+ if (!packagePrefix.equals(newPackagePrefix))
+ {
+ // Return a renamed data entry.
+ String newDataEntryName =
+ newPackagePrefix + dataEntryName.substring(packagePrefix.length());
+
+ return new RenamedDataEntry(dataEntry, newDataEntryName);
+ }
+ else
+ {
+ // Otherwise stop looking.
+ return dataEntry;
+ }
+ }
+ }
+ while (packagePrefix.length() > 0);
+
+ return dataEntry;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryParentFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryParentFilter.java
new file mode 100644
index 0000000000..b01bc718d6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryParentFilter.java
@@ -0,0 +1,51 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+/**
+ * This DataEntryFilter delegates filtering to a DataEntryFilter for its parent.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryParentFilter
+implements DataEntryFilter
+{
+ private final DataEntryFilter dataEntryFilter;
+
+
+ /**
+ * Creates a new ParentFilter.
+ * @param dataEntryFilter the filter that will be applied to the data
+ * entry's parent.
+ */
+ public DataEntryParentFilter(DataEntryFilter dataEntryFilter)
+ {
+ this.dataEntryFilter = dataEntryFilter;
+ }
+
+
+ // Implementations for DataEntryFilter.
+
+ public boolean accepts(DataEntry dataEntry)
+ {
+ return dataEntry != null && dataEntryFilter.accepts(dataEntry.getParent());
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryPump.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryPump.java
new file mode 100644
index 0000000000..b6cb53283f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryPump.java
@@ -0,0 +1,43 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.IOException;
+
+
+/**
+ * This interface provides a method to pump data entries. The implementation
+ * determines the source and the type of the data entries. Typical examples
+ * are zip entries coming from a zip file of file entries coming from a
+ * directory structure. The reader can for instance collect the classes,
+ * or copy the resource files that are presented.
+ *
+ * @author Eric Lafortune
+ */
+public interface DataEntryPump
+{
+ /**
+ * Applies the given DataEntryReader to all data entries that the
+ * implementation can provide.
+ */
+ public void pumpDataEntries(DataEntryReader dataEntryReader)
+ throws IOException;
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryReader.java
new file mode 100644
index 0000000000..e41b6eb2b4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryReader.java
@@ -0,0 +1,38 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.IOException;
+
+
+/**
+ * This interface provides methods for reading data entries. The implementation
+ * determines what to do with the read data, if anything.
+ *
+ * @author Eric Lafortune
+ */
+public interface DataEntryReader
+{
+ /**
+ * Reads the given data entry.
+ */
+ public void read(DataEntry dataEntry) throws IOException;
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryRenamer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryRenamer.java
new file mode 100644
index 0000000000..386fdfcb48
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryRenamer.java
@@ -0,0 +1,104 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.ClassConstants;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * This DataEntryReader delegates to another DataEntryReader, renaming the
+ * data entries based on the given map. Entries whose name does not appear
+ * in the map may be passed to an alternative DataEntryReader.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryRenamer implements DataEntryReader
+{
+ private final Map nameMap;
+ private final DataEntryReader renamedDataEntryReader;
+ private final DataEntryReader missingDataEntryReader;
+
+
+ /**
+ * Creates a new DataEntryRenamer.
+ * @param nameMap the map from old names to new names.
+ * @param renamedDataEntryReader the DataEntryReader to which renamed data
+ * entries will be passed.
+ */
+ public DataEntryRenamer(Map nameMap,
+ DataEntryReader renamedDataEntryReader)
+ {
+ this(nameMap, renamedDataEntryReader, null);
+ }
+
+
+ /**
+ * Creates a new DataEntryRenamer.
+ * @param nameMap the map from old names to new names.
+ * @param renamedDataEntryReader the DataEntryReader to which renamed data
+ * entries will be passed.
+ * @param missingDataEntryReader the optional DataEntryReader to which data
+ * entries that can't be renamed will be
+ * passed.
+ */
+ public DataEntryRenamer(Map nameMap,
+ DataEntryReader renamedDataEntryReader,
+ DataEntryReader missingDataEntryReader)
+ {
+ this.nameMap = nameMap;
+ this.renamedDataEntryReader = renamedDataEntryReader;
+ this.missingDataEntryReader = missingDataEntryReader;
+ }
+
+
+ // Implementations for DataEntryReader.
+
+ public void read(DataEntry dataEntry) throws IOException
+ {
+ String name = dataEntry.getName();
+
+ // Add a directory separator if necessary.
+ if (dataEntry.isDirectory() &&
+ name.length() > 0)
+ {
+ name += ClassConstants.PACKAGE_SEPARATOR;
+ }
+
+ String newName = (String)nameMap.get(name);
+ if (newName != null)
+ {
+ // Remove the directory separator if necessary.
+ if (dataEntry.isDirectory() &&
+ newName.length() > 0)
+ {
+ newName = newName.substring(0, newName.length() - 1);
+ }
+
+ renamedDataEntryReader.read(new RenamedDataEntry(dataEntry, newName));
+ }
+ else if (missingDataEntryReader != null)
+ {
+ missingDataEntryReader.read(dataEntry);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryRewriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryRewriter.java
new file mode 100644
index 0000000000..827a932698
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryRewriter.java
@@ -0,0 +1,148 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.*;
+
+import java.io.*;
+
+/**
+ * This DataEntryReader writes the resource data entries that it reads to a
+ * given DataEntryWriter, updating their contents based on the renamed classes
+ * in the given ClassPool.
+ *
+ * @author Eric Lafortune
+ */
+public class DataEntryRewriter extends DataEntryCopier
+{
+ private final ClassPool classPool;
+
+
+ /**
+ * Creates a new DataEntryRewriter.
+ */
+ public DataEntryRewriter(ClassPool classPool,
+ DataEntryWriter dataEntryWriter)
+ {
+ super(dataEntryWriter);
+
+ this.classPool = classPool;
+ }
+
+
+ // Implementations for DataEntryCopier.
+
+ protected void copyData(InputStream inputStream,
+ OutputStream outputStream)
+ throws IOException
+ {
+ Reader reader = new BufferedReader(new InputStreamReader(inputStream));
+ Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream));
+
+ copyData(reader, writer);
+
+ writer.flush();
+ outputStream.flush();
+ }
+
+
+ /**
+ * Copies all data that it can read from the given reader to the given
+ * writer.
+ */
+ protected void copyData(Reader reader,
+ Writer writer)
+ throws IOException
+ {
+ StringBuffer word = new StringBuffer();
+
+ while (true)
+ {
+ int i = reader.read();
+ if (i < 0)
+ {
+ break;
+ }
+
+ // Is the character part of a word?
+ char c = (char)i;
+ if (Character.isJavaIdentifierPart(c) ||
+ c == '.' ||
+ c == '-')
+ {
+ // Collect the characters in this word.
+ word.append(c);
+ }
+ else
+ {
+ // Write out the updated word, if any.
+ writeUpdatedWord(writer, word.toString());
+ word.setLength(0);
+
+ // Write out the character that terminated it.
+ writer.write(c);
+ }
+ }
+
+ // Write out the final word.
+ writeUpdatedWord(writer, word.toString());
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Writes the given word to the given writer, after having adapted it,
+ * based on the renamed class names.
+ */
+ private void writeUpdatedWord(Writer writer, String word)
+ throws IOException
+ {
+ if (word.length() > 0)
+ {
+ String newWord = word;
+
+ boolean containsDots = word.indexOf('.') >= 0;
+
+ // Replace dots by forward slashes.
+ String className = containsDots ?
+ word.replace('.', ClassConstants.PACKAGE_SEPARATOR) :
+ word;
+
+ // Find the class corrsponding to the word.
+ Clazz clazz = classPool.getClass(className);
+ if (clazz != null)
+ {
+ // Update the word if necessary.
+ String newClassName = clazz.getName();
+ if (!className.equals(newClassName))
+ {
+ // Replace forward slashes by dots.
+ newWord = containsDots ?
+ newClassName.replace(ClassConstants.PACKAGE_SEPARATOR, '.') :
+ newClassName;
+ }
+ }
+
+ writer.write(newWord);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryWriter.java
new file mode 100644
index 0000000000..1fe2ea6a6a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DataEntryWriter.java
@@ -0,0 +1,73 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.*;
+
+
+/**
+ * This interface provides methods for writing data entries, such as ZIP entries
+ * or files. The implementation determines to which type of data entry the
+ * data will be written.
+ *
+ * @author Eric Lafortune
+ */
+public interface DataEntryWriter
+{
+ /**
+ * Creates a directory.
+ * @param dataEntry the data entry for which the directory is to be created.
+ * @return whether the directory has been created.
+ */
+ public boolean createDirectory(DataEntry dataEntry) throws IOException;
+
+
+ /**
+ * Returns an output stream for writing data. The caller must not close
+ * the output stream; closing the output stream is the responsibility of
+ * the implementation of this interface.
+ * @param dataEntry the data entry for which the output stream is to be created.
+ * @return the output stream. The stream may be <code>null</code> to indicate
+ * that the data entry should not be written.
+ */
+ public OutputStream getOutputStream(DataEntry dataEntry) throws IOException;
+
+
+ /**
+ * Returns an output stream for writing data. The caller must not close
+ * the output stream; closing the output stream is the responsibility of
+ * the implementation of this interface.
+ * @param dataEntry the data entry for which the output stream is to be created.
+ * @param finisher the optional finisher that will be called before this
+ * class closes the output stream (at some later point in
+ * time) that will be returned (now).
+ * @return the output stream. The stream may be <code>null</code> to indicate
+ * that the data entry should not be written.
+ */
+ public OutputStream getOutputStream(DataEntry dataEntry,
+ Finisher finisher) throws IOException;
+
+
+ /**
+ * Finishes writing all data entries.
+ */
+ public void close() throws IOException;
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryFilter.java
new file mode 100644
index 0000000000..a973b5cc4d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryFilter.java
@@ -0,0 +1,52 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+/**
+ * This DataEntryReader delegates to one of two other DataEntryReader instances,
+ * depending on whether the data entry represents a directory or not.
+ *
+ * @author Eric Lafortune
+ */
+public class DirectoryFilter extends FilteredDataEntryReader
+{
+ /**
+ * Creates a new ClassFilter that delegates reading directories to the
+ * given reader.
+ */
+ public DirectoryFilter(DataEntryReader directoryReader)
+ {
+ this (directoryReader, null);
+ }
+
+
+ /**
+ * Creates a new ClassFilter that delegates to either of the two given
+ * readers.
+ */
+ public DirectoryFilter(DataEntryReader directoryReader,
+ DataEntryReader otherReader)
+ {
+ super(new DataEntryDirectoryFilter(),
+ directoryReader,
+ otherReader);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryPump.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryPump.java
new file mode 100644
index 0000000000..f191fabe9a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryPump.java
@@ -0,0 +1,86 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.*;
+
+
+/**
+ * This class can read a given file or directory, recursively, applying a given
+ * DataEntryReader to all files it comes across.
+ *
+ * @author Eric Lafortune
+ */
+public class DirectoryPump implements DataEntryPump
+{
+ private final File directory;
+
+
+ public DirectoryPump(File directory)
+ {
+ this.directory = directory;
+ }
+
+
+ // Implementations for DataEntryPump.
+
+ public void pumpDataEntries(DataEntryReader dataEntryReader)
+ throws IOException
+ {
+ if (!directory.exists())
+ {
+ throw new IOException("No such file or directory");
+ }
+
+ readFiles(directory, dataEntryReader);
+ }
+
+
+ /**
+ * Reads the given subdirectory recursively, applying the given DataEntryReader
+ * to all files that are encountered.
+ */
+ private void readFiles(File file, DataEntryReader dataEntryReader)
+ throws IOException
+ {
+ // Pass the file data entry to the reader.
+ dataEntryReader.read(new FileDataEntry(directory, file));
+
+ if (file.isDirectory())
+ {
+ // Recurse into the subdirectory.
+ File[] listedFiles = file.listFiles();
+
+ for (int index = 0; index < listedFiles.length; index++)
+ {
+ File listedFile = listedFiles[index];
+ try
+ {
+ readFiles(listedFile, dataEntryReader);
+ }
+ catch (IOException e)
+ {
+ throw (IOException)new IOException("Can't read ["+listedFile.getName()+"] ("+e.getMessage()+")").initCause(e);
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryWriter.java
new file mode 100644
index 0000000000..c4383ce7d1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/DirectoryWriter.java
@@ -0,0 +1,165 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.ClassConstants;
+
+import java.io.*;
+
+
+/**
+ * This DataEntryWriter writes data entries to individual files in a given
+ * directory.
+ *
+ * @author Eric Lafortune
+ */
+public class DirectoryWriter implements DataEntryWriter
+{
+ private final File baseFile;
+ private final boolean isFile;
+
+ private File currentFile;
+ private OutputStream currentOutputStream;
+ private Finisher currentFinisher;
+
+
+ /**
+ * Creates a new DirectoryWriter.
+ * @param baseFile the base directory to which all files will be written.
+ */
+ public DirectoryWriter(File baseFile,
+ boolean isFile)
+ {
+ this.baseFile = baseFile;
+ this.isFile = isFile;
+ }
+
+
+ // Implementations for DataEntryWriter.
+
+ public boolean createDirectory(DataEntry dataEntry) throws IOException
+ {
+ // Should we close the current file?
+ if (!isFile &&
+ currentFile != null)
+ {
+ closeEntry();
+ }
+
+ File directory = getFile(dataEntry);
+ if (!directory.exists() &&
+ !directory.mkdirs())
+ {
+ throw new IOException("Can't create directory [" + directory.getPath() + "]");
+ }
+
+ return true;
+ }
+
+
+ public OutputStream getOutputStream(DataEntry dataEntry) throws IOException
+ {
+ return getOutputStream(dataEntry, null);
+ }
+
+
+ public OutputStream getOutputStream(DataEntry dataEntry,
+ Finisher finisher) throws IOException
+ {
+ File file = getFile(dataEntry);
+
+ // Should we close the current file?
+ if (!isFile &&
+ currentFile != null &&
+ !currentFile.equals(file))
+ {
+ closeEntry();
+ }
+
+ // Do we need a new stream?
+ if (currentOutputStream == null)
+ {
+ // Make sure the parent directories exist.
+ File parentDirectory = file.getParentFile();
+ if (parentDirectory != null &&
+ !parentDirectory.exists() &&
+ !parentDirectory.mkdirs())
+ {
+ throw new IOException("Can't create directory [" + parentDirectory.getPath() + "]");
+ }
+
+ // Open a new output stream for writing to the file.
+ currentOutputStream =
+ new BufferedOutputStream(
+ new FileOutputStream(file));
+
+ currentFinisher = finisher;
+ currentFile = file;
+ }
+
+ return currentOutputStream;
+ }
+
+
+ public void close() throws IOException
+ {
+ // Close the file stream, if any.
+ closeEntry();
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the file for the given data entry.
+ */
+ private File getFile(DataEntry dataEntry)
+ {
+ // Use the specified file, or construct a new file.
+ return isFile ?
+ baseFile :
+ new File(baseFile,
+ dataEntry.getName().replace(ClassConstants.PACKAGE_SEPARATOR,
+ File.separatorChar));
+ }
+
+
+ /**
+ * Closes the previous file, if any.
+ */
+ private void closeEntry() throws IOException
+ {
+ // Close the file stream, if any.
+ if (currentOutputStream != null)
+ {
+ // Let any finisher finish up first.
+ if (currentFinisher != null)
+ {
+ currentFinisher.finish();
+ currentFinisher = null;
+ }
+
+ currentOutputStream.close();
+ currentOutputStream = null;
+ currentFile = null;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/FileDataEntry.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/FileDataEntry.java
new file mode 100644
index 0000000000..cc3e853890
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/FileDataEntry.java
@@ -0,0 +1,96 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.ClassConstants;
+
+import java.io.*;
+
+/**
+ * This <code>DataEntry</code> represents a file.
+ *
+ * @author Eric Lafortune
+ */
+public class FileDataEntry implements DataEntry
+{
+ private final File directory;
+ private final File file;
+ private InputStream inputStream;
+
+
+ public FileDataEntry(File directory,
+ File file)
+ {
+ this.directory = directory;
+ this.file = file;
+ }
+
+
+ // Implementations for DataEntry.
+
+ public String getName()
+ {
+ // Chop the directory name from the file name and get the right separators.
+ return file.equals(directory) ?
+ file.getName() :
+ file.getPath()
+ .substring(directory.getPath().length() + File.separator.length())
+ .replace(File.separatorChar, ClassConstants.PACKAGE_SEPARATOR);
+ }
+
+
+ public boolean isDirectory()
+ {
+ return file.isDirectory();
+ }
+
+
+ public InputStream getInputStream() throws IOException
+ {
+ if (inputStream == null)
+ {
+ inputStream = new BufferedInputStream(new FileInputStream(file));
+ }
+
+ return inputStream;
+ }
+
+
+ public void closeInputStream() throws IOException
+ {
+ inputStream.close();
+ inputStream = null;
+ }
+
+
+ public DataEntry getParent()
+ {
+ return null;
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return getName();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/FilteredDataEntryReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/FilteredDataEntryReader.java
new file mode 100644
index 0000000000..c2449bdbe6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/FilteredDataEntryReader.java
@@ -0,0 +1,90 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.IOException;
+
+
+/**
+ * This DataEntryReader delegates to one of two other DataEntryReader instances,
+ * depending on whether the data entry passes through a given data entry filter
+ * or not.
+ *
+ * @author Eric Lafortune
+ */
+public class FilteredDataEntryReader implements DataEntryReader
+{
+ private final DataEntryFilter dataEntryFilter;
+ private final DataEntryReader acceptedDataEntryReader;
+ private final DataEntryReader rejectedDataEntryReader;
+
+
+ /**
+ * Creates a new FilteredDataEntryReader with only a reader for accepted
+ * data entries.
+ * @param dataEntryFilter the data entry filter.
+ * @param acceptedDataEntryReader the DataEntryReader to which the reading
+ * will be delegated if the filter accepts
+ * the data entry. May be <code>null</code>.
+ */
+ public FilteredDataEntryReader(DataEntryFilter dataEntryFilter,
+ DataEntryReader acceptedDataEntryReader)
+ {
+ this(dataEntryFilter, acceptedDataEntryReader, null);
+ }
+
+
+ /**
+ * Creates a new FilteredDataEntryReader.
+ * @param dataEntryFilter the data entry filter.
+ * @param acceptedDataEntryReader the DataEntryReader to which the reading
+ * will be delegated if the filter accepts
+ * the data entry. May be <code>null</code>.
+ * @param rejectedDataEntryReader the DataEntryReader to which the reading
+ * will be delegated if the filter does not
+ * accept the data entry. May be
+ * <code>null</code>.
+ */
+ public FilteredDataEntryReader(DataEntryFilter dataEntryFilter,
+ DataEntryReader acceptedDataEntryReader,
+ DataEntryReader rejectedDataEntryReader)
+ {
+ this.dataEntryFilter = dataEntryFilter;
+ this.acceptedDataEntryReader = acceptedDataEntryReader;
+ this.rejectedDataEntryReader = rejectedDataEntryReader;
+ }
+
+
+ // Implementations for DataEntryReader.
+
+ public void read(DataEntry dataEntry)
+ throws IOException
+ {
+ DataEntryReader dataEntryReader = dataEntryFilter.accepts(dataEntry) ?
+ acceptedDataEntryReader :
+ rejectedDataEntryReader;
+
+ if (dataEntryReader != null)
+ {
+ dataEntryReader.read(dataEntry);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/FilteredDataEntryWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/FilteredDataEntryWriter.java
new file mode 100644
index 0000000000..7b0dfc9aa6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/FilteredDataEntryWriter.java
@@ -0,0 +1,125 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.*;
+
+/**
+ * This DataEntryWriter delegates to one of two other DataEntryWriter instances,
+ * depending on whether the data entry passes through a given data entry filter
+ * or not.
+ *
+ * @author Eric Lafortune
+ */
+public class FilteredDataEntryWriter implements DataEntryWriter
+{
+ private final DataEntryFilter dataEntryFilter;
+ private DataEntryWriter acceptedDataEntryWriter;
+ private DataEntryWriter rejectedDataEntryWriter;
+
+
+ /**
+ * Creates a new FilteredDataEntryWriter with only a writer for accepted
+ * data entries.
+ * @param dataEntryFilter the data entry filter.
+ * @param acceptedDataEntryWriter the DataEntryWriter to which the writing
+ * will be delegated if the filter accepts
+ * the data entry. May be <code>null</code>.
+ */
+ public FilteredDataEntryWriter(DataEntryFilter dataEntryFilter,
+ DataEntryWriter acceptedDataEntryWriter)
+ {
+ this(dataEntryFilter, acceptedDataEntryWriter, null);
+ }
+
+
+ /**
+ * Creates a new FilteredDataEntryWriter.
+ * @param dataEntryFilter the data entry filter.
+ * @param acceptedDataEntryWriter the DataEntryWriter to which the writing
+ * will be delegated if the filter accepts
+ * the data entry. May be <code>null</code>.
+ * @param rejectedDataEntryWriter the DataEntryWriter to which the writing
+ * will be delegated if the filter does not
+ * accept the data entry. May be
+ * <code>null</code>.
+ */
+ public FilteredDataEntryWriter(DataEntryFilter dataEntryFilter,
+ DataEntryWriter acceptedDataEntryWriter,
+ DataEntryWriter rejectedDataEntryWriter)
+ {
+ this.dataEntryFilter = dataEntryFilter;
+ this.acceptedDataEntryWriter = acceptedDataEntryWriter;
+ this.rejectedDataEntryWriter = rejectedDataEntryWriter;
+ }
+
+
+ // Implementations for DataEntryWriter.
+
+ public boolean createDirectory(DataEntry dataEntry) throws IOException
+ {
+ // Get the right data entry writer.
+ DataEntryWriter dataEntryWriter = dataEntryFilter.accepts(dataEntry) ?
+ acceptedDataEntryWriter :
+ rejectedDataEntryWriter;
+
+ // Delegate to it, if it's not null.
+ return dataEntryWriter != null &&
+ dataEntryWriter.createDirectory(dataEntry);
+ }
+
+
+ public OutputStream getOutputStream(DataEntry dataEntry) throws IOException
+ {
+ return getOutputStream(dataEntry, null);
+ }
+
+
+ public OutputStream getOutputStream(DataEntry dataEntry,
+ Finisher finisher) throws IOException
+ {
+ // Get the right data entry writer.
+ DataEntryWriter dataEntryWriter = dataEntryFilter.accepts(dataEntry) ?
+ acceptedDataEntryWriter :
+ rejectedDataEntryWriter;
+
+ // Delegate to it, if it's not null.
+ return dataEntryWriter != null ?
+ dataEntryWriter.getOutputStream(dataEntry, finisher) :
+ null;
+ }
+
+
+ public void close() throws IOException
+ {
+ if (acceptedDataEntryWriter != null)
+ {
+ acceptedDataEntryWriter.close();
+ acceptedDataEntryWriter = null;
+ }
+
+ if (rejectedDataEntryWriter != null)
+ {
+ rejectedDataEntryWriter.close();
+ rejectedDataEntryWriter = null;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/Finisher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/Finisher.java
new file mode 100644
index 0000000000..c92632ca25
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/Finisher.java
@@ -0,0 +1,37 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.IOException;
+
+/**
+ * This interface specifies a listener that is called to finish an output stream
+ * before it is closed.
+ *
+ * @author Eric Lafortune
+ */
+public interface Finisher
+{
+ /**
+ * Finishes an output stream right before it is closed.
+ */
+ public void finish() throws IOException;
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/JarReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/JarReader.java
new file mode 100644
index 0000000000..718af32f65
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/JarReader.java
@@ -0,0 +1,75 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.IOException;
+import java.util.zip.*;
+
+/**
+ * This DataEntryReader lets a given DataEntryReader read all data entries of
+ * the read jar/war/zip data entries.
+ *
+ * @author Eric Lafortune
+ */
+public class JarReader implements DataEntryReader
+{
+ private final DataEntryReader dataEntryReader;
+
+
+ /**
+ * Creates a new JarReader.
+ */
+ public JarReader(DataEntryReader dataEntryReader)
+ {
+ this.dataEntryReader = dataEntryReader;
+ }
+
+
+ // Implementation for DataEntryReader.
+
+ public void read(DataEntry dataEntry) throws IOException
+ {
+ ZipInputStream zipInputStream = new ZipInputStream(dataEntry.getInputStream());
+
+ try
+ {
+ // Get all entries from the input jar.
+ while (true)
+ {
+ // Can we get another entry?
+ ZipEntry zipEntry = zipInputStream.getNextEntry();
+ if (zipEntry == null)
+ {
+ break;
+ }
+
+ // Delegate the actual reading to the data entry reader.
+ dataEntryReader.read(new ZipDataEntry(dataEntry,
+ zipEntry,
+ zipInputStream));
+ }
+ }
+ finally
+ {
+ dataEntry.closeInputStream();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/JarWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/JarWriter.java
new file mode 100644
index 0000000000..5faa0ff60a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/JarWriter.java
@@ -0,0 +1,234 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.ClassConstants;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+import java.util.zip.*;
+
+/**
+ * This DataEntryWriter sends data entries to a given jar/zip file.
+ * The manifest and comment properties can optionally be set.
+ *
+ * @author Eric Lafortune
+ */
+public class JarWriter implements DataEntryWriter, Finisher
+{
+ private final DataEntryWriter dataEntryWriter;
+ private final Manifest manifest;
+ private final String comment;
+
+ private OutputStream currentParentOutputStream;
+ private ZipOutputStream currentJarOutputStream;
+ private Finisher currentFinisher;
+ private DataEntry currentDataEntry;
+
+ // The names of the jar entries that are already in the jar.
+ private final Set jarEntryNames = new HashSet();
+
+
+ /**
+ * Creates a new JarWriter without manifest or comment.
+ */
+ public JarWriter(DataEntryWriter dataEntryWriter)
+ {
+ this(dataEntryWriter, null, null);
+ }
+
+
+ /**
+ * Creates a new JarWriter.
+ */
+ public JarWriter(DataEntryWriter dataEntryWriter,
+ Manifest manifest,
+ String comment)
+ {
+ this.dataEntryWriter = dataEntryWriter;
+ this.manifest = manifest;
+ this.comment = comment;
+ }
+
+
+ // Implementations for DataEntryWriter.
+
+ public boolean createDirectory(DataEntry dataEntry) throws IOException
+ {
+ // Make sure we can start with a new entry.
+ if (!prepareEntry(dataEntry))
+ {
+ return false;
+ }
+
+ // Close the previous ZIP entry, if any.
+ closeEntry();
+
+ // Get the directory entry name.
+ String name = dataEntry.getName() + ClassConstants.PACKAGE_SEPARATOR;
+
+ // We have to check if the name is already used, because
+ // ZipOutputStream doesn't handle this case properly (it throws
+ // an exception which can be caught, but the ZipDataEntry is
+ // remembered anyway).
+ if (jarEntryNames.add(name))
+ {
+ // Create a new directory entry.
+ currentJarOutputStream.putNextEntry(new ZipEntry(name));
+ currentJarOutputStream.closeEntry();
+ }
+
+ // Clear the finisher.
+ currentFinisher = null;
+ currentDataEntry = null;
+
+ return true;
+ }
+
+
+ public OutputStream getOutputStream(DataEntry dataEntry) throws IOException
+ {
+ return getOutputStream(dataEntry, null);
+ }
+
+
+ public OutputStream getOutputStream(DataEntry dataEntry,
+ Finisher finisher) throws IOException
+ {
+ //Make sure we can start with a new entry.
+ if (!prepareEntry(dataEntry))
+ {
+ return null;
+ }
+
+ // Do we need a new entry?
+ if (!dataEntry.equals(currentDataEntry))
+ {
+ // Close the previous ZIP entry, if any.
+ closeEntry();
+
+ // Get the entry name.
+ String name = dataEntry.getName();
+
+ // We have to check if the name is already used, because
+ // ZipOutputStream doesn't handle this case properly (it throws
+ // an exception which can be caught, but the ZipDataEntry is
+ // remembered anyway).
+ if (!jarEntryNames.add(name))
+ {
+ throw new IOException("Duplicate zip entry ["+dataEntry+"]");
+ }
+
+ // Create a new entry.
+ currentJarOutputStream.putNextEntry(new ZipEntry(name));
+
+ // Set up the finisher for the entry.
+ currentFinisher = finisher;
+ currentDataEntry = dataEntry;
+ }
+
+ return currentJarOutputStream;
+ }
+
+
+ public void finish() throws IOException
+ {
+ // Finish the entire ZIP stream, if any.
+ if (currentJarOutputStream != null)
+ {
+ // Close the previous ZIP entry, if any.
+ closeEntry();
+
+ // Finish the entire ZIP stream.
+ currentJarOutputStream.finish();
+ currentJarOutputStream = null;
+ currentParentOutputStream = null;
+ jarEntryNames.clear();
+ }
+ }
+
+
+ public void close() throws IOException
+ {
+ // Close the parent stream.
+ dataEntryWriter.close();
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Makes sure the current output stream is set up for the given entry.
+ */
+ private boolean prepareEntry(DataEntry dataEntry) throws IOException
+ {
+ // Get the parent stream, new or existing.
+ // This may finish our own jar output stream.
+ OutputStream parentOutputStream =
+ dataEntryWriter.getOutputStream(dataEntry.getParent(), this);
+
+ // Did we get a stream?
+ if (parentOutputStream == null)
+ {
+ return false;
+ }
+
+ // Do we need a new stream?
+ if (currentParentOutputStream == null)
+ {
+ currentParentOutputStream = parentOutputStream;
+
+ // Create a new jar stream, with a manifest, if set.
+ currentJarOutputStream = manifest != null ?
+ new JarOutputStream(parentOutputStream, manifest) :
+ new ZipOutputStream(parentOutputStream);
+
+ // Add a comment, if set.
+ if (comment != null)
+ {
+ currentJarOutputStream.setComment(comment);
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Closes the previous ZIP entry, if any.
+ */
+ private void closeEntry() throws IOException
+ {
+ if (currentDataEntry != null)
+ {
+ // Let any finisher finish up first.
+ if (currentFinisher != null)
+ {
+ currentFinisher.finish();
+ currentFinisher = null;
+ }
+
+ currentJarOutputStream.closeEntry();
+ currentDataEntry = null;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/ManifestRewriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ManifestRewriter.java
new file mode 100644
index 0000000000..1d790649fe
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ManifestRewriter.java
@@ -0,0 +1,211 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.ClassPool;
+
+import java.io.*;
+
+/**
+ * This DataEntryReader writes the manifest data entries that it reads to a
+ * given DataEntryWriter, updating their contents based on the renamed classes
+ * in the given ClassPool.
+ *
+ * @author Eric Lafortune
+ */
+public class ManifestRewriter extends DataEntryRewriter
+{
+ /**
+ * Creates a new ManifestRewriter.
+ */
+ public ManifestRewriter(ClassPool classPool,
+ DataEntryWriter dataEntryWriter)
+ {
+ super(classPool, dataEntryWriter);
+ }
+
+
+ // Implementations for DataEntryRewriter.
+
+ protected void copyData(Reader reader,
+ Writer writer)
+ throws IOException
+ {
+ super.copyData(new SplitLineReader(reader),
+ new SplitLineWriter(writer));
+ }
+
+
+ /**
+ * This Reader reads manifest files, joining any split lines. It replaces
+ * the allowed CR/LF/CR+LF alternatives by simple LF in the process.
+ */
+ private static class SplitLineReader extends FilterReader
+ {
+ private static final int NONE = -2;
+
+ private int bufferedCharacter = NONE;
+
+
+ public SplitLineReader(Reader reader)
+ {
+ super(reader);
+ }
+
+
+ // Implementations for Reader.
+
+ public int read() throws IOException
+ {
+ while (true)
+ {
+ // Get the buffered character or the first character.
+ int c1 = bufferedCharacter != NONE ?
+ bufferedCharacter :
+ super.read();
+
+ // Clear the buffered character.
+ bufferedCharacter = NONE;
+
+ // Return it if it's an ordinary character.
+ if (c1 != '\n' && c1 != '\r')
+ {
+ return c1;
+ }
+
+ // It's a newline. Read the second character to see if it's a
+ // continuation.
+ int c2 = super.read();
+
+ // Skip any corresponding, redundant \n or \r.
+ if ((c2 == '\n' || c2 == '\r') && c1 != c2)
+ {
+ c2 = super.read();
+ }
+
+ // Isn't it a continuation after all?
+ if (c2 != ' ')
+ {
+ // Buffer the second character and return a newline.
+ bufferedCharacter = c2;
+ return '\n';
+ }
+
+ // Just continue after the continuation characters.
+ }
+ }
+
+
+ public int read(char[] cbuf, int off, int len) throws IOException
+ {
+ // Delegate to reading a single character at a time.
+ int count = 0;
+ while (count < len)
+ {
+ int c = read();
+ if (c == -1)
+ {
+ break;
+ }
+
+ cbuf[off + count++] = (char)c;
+ }
+
+ return count;
+ }
+
+
+ public long skip(long n) throws IOException
+ {
+ // Delegate to reading a single character at a time.
+ int count = 0;
+ while (count < n)
+ {
+ int c = read();
+ if (c == -1)
+ {
+ break;
+ }
+
+ count++;
+ }
+
+ return count;
+ }
+ }
+
+
+ /**
+ * This Writer writes manifest files, splitting any long lines.
+ */
+ private static class SplitLineWriter extends FilterWriter
+ {
+ private int counter = 0;
+
+
+ public SplitLineWriter(Writer writer)
+ {
+ super(writer);
+ }
+
+
+ // Implementations for Reader.
+
+ public void write(int c) throws IOException
+ {
+ // TODO: We should actually count the Utf-8 bytes, not the characters.
+ if (c == '\n')
+ {
+ // Reset the character count.
+ counter = 0;
+ }
+ else if (counter == 70)
+ {
+ // Insert a newline and a space.
+ super.write('\n');
+ super.write(' ');
+
+ counter = 2;
+ }
+ else
+ {
+ counter++;
+ }
+
+ super.write(c);
+ }
+
+
+ public void write(char[] cbuf, int off, int len) throws IOException
+ {
+ for (int count = 0; count < len; count++)
+ {
+ write(cbuf[off + count]);
+ }
+ }
+
+
+ public void write(String str, int off, int len) throws IOException
+ {
+ write(str.toCharArray(), off, len);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/NameFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/NameFilter.java
new file mode 100644
index 0000000000..e30606beb8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/NameFilter.java
@@ -0,0 +1,83 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.util.*;
+
+import java.util.List;
+
+/**
+ * This DataEntryReader delegates to one of two other DataEntryReader instances,
+ * depending on the name of the data entry.
+ *
+ * @author Eric Lafortune
+ */
+public class NameFilter extends FilteredDataEntryReader
+{
+ /**
+ * Creates a new NameFilter that delegates to the given reader, depending
+ * on the given list of filters.
+ */
+ public NameFilter(String regularExpression,
+ DataEntryReader acceptedDataEntryReader)
+ {
+ this(regularExpression, acceptedDataEntryReader, null);
+ }
+
+
+ /**
+ * Creates a new NameFilter that delegates to either of the two given
+ * readers, depending on the given list of filters.
+ */
+ public NameFilter(String regularExpression,
+ DataEntryReader acceptedDataEntryReader,
+ DataEntryReader rejectedDataEntryReader)
+ {
+ super(new DataEntryNameFilter(new ListParser(new FileNameParser()).parse(regularExpression)),
+ acceptedDataEntryReader,
+ rejectedDataEntryReader);
+ }
+
+
+ /**
+ * Creates a new NameFilter that delegates to the given reader, depending
+ * on the given list of filters.
+ */
+ public NameFilter(List regularExpressions,
+ DataEntryReader acceptedDataEntryReader)
+ {
+ this(regularExpressions, acceptedDataEntryReader, null);
+ }
+
+
+ /**
+ * Creates a new NameFilter that delegates to either of the two given
+ * readers, depending on the given list of filters.
+ */
+ public NameFilter(List regularExpressions,
+ DataEntryReader acceptedDataEntryReader,
+ DataEntryReader rejectedDataEntryReader)
+ {
+ super(new DataEntryNameFilter(new ListParser(new FileNameParser()).parse(regularExpressions)),
+ acceptedDataEntryReader,
+ rejectedDataEntryReader);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/ParentDataEntryWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ParentDataEntryWriter.java
new file mode 100644
index 0000000000..8590296b4b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ParentDataEntryWriter.java
@@ -0,0 +1,75 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.*;
+
+/**
+ * This DataEntryWriter lets another DataEntryWriter write the parent data
+ * entries.
+ *
+ * @author Eric Lafortune
+ */
+public class ParentDataEntryWriter implements DataEntryWriter
+{
+ private DataEntryWriter dataEntryWriter;
+
+
+ /**
+ * Creates a new ParentDataEntryWriter.
+ * @param dataEntryWriter the DataEntryWriter to which the writing will be
+ * delegated, passing the data entries' parents.
+ */
+ public ParentDataEntryWriter(DataEntryWriter dataEntryWriter)
+ {
+ this.dataEntryWriter = dataEntryWriter;
+ }
+
+
+ // Implementations for DataEntryWriter.
+
+
+ public boolean createDirectory(DataEntry dataEntry) throws IOException
+ {
+ return getOutputStream(dataEntry) != null;
+ }
+
+
+ public OutputStream getOutputStream(DataEntry dataEntry) throws IOException
+ {
+ return getOutputStream(dataEntry, null);
+ }
+
+
+ public OutputStream getOutputStream(DataEntry dataEntry,
+ Finisher finisher) throws IOException
+ {
+ return dataEntryWriter.getOutputStream(dataEntry.getParent(),
+ finisher);
+ }
+
+
+ public void close() throws IOException
+ {
+ dataEntryWriter.close();
+ dataEntryWriter = null;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/RenamedDataEntry.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/RenamedDataEntry.java
new file mode 100644
index 0000000000..3ac3f18728
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/RenamedDataEntry.java
@@ -0,0 +1,83 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import java.io.*;
+
+/**
+ * This DataEntry wraps another data entry, returning a different name instead
+ * of the wrapped data entry's name.
+ *
+ * @author Eric Lafortune
+ */
+public class RenamedDataEntry implements DataEntry
+{
+ private final DataEntry dataEntry;
+ private final String name;
+
+
+ public RenamedDataEntry(DataEntry dataEntry,
+ String name)
+ {
+ this.dataEntry = dataEntry;
+ this.name = name;
+ }
+
+
+ // Implementations for DataEntry.
+
+ public String getName()
+ {
+ return name;
+ }
+
+
+ public boolean isDirectory()
+ {
+ return dataEntry.isDirectory();
+ }
+
+
+ public InputStream getInputStream() throws IOException
+ {
+ return dataEntry.getInputStream();
+ }
+
+
+ public void closeInputStream() throws IOException
+ {
+ dataEntry.closeInputStream();
+ }
+
+
+ public DataEntry getParent()
+ {
+ return dataEntry.getParent();
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return name + " == " + dataEntry;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/ZipDataEntry.java b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ZipDataEntry.java
new file mode 100644
index 0000000000..7425745b30
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/ZipDataEntry.java
@@ -0,0 +1,105 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.io;
+
+import proguard.classfile.ClassConstants;
+
+import java.io.*;
+import java.util.zip.*;
+
+/**
+ * This <code>DataEntry</code> represents a ZIP entry.
+ *
+ * @author Eric Lafortune
+ */
+public class ZipDataEntry implements DataEntry
+{
+ private final DataEntry parent;
+ private final ZipEntry zipEntry;
+ private ZipInputStream zipInputStream;
+ private InputStream bufferedInputStream;
+
+
+ public ZipDataEntry(DataEntry parent,
+ ZipEntry zipEntry,
+ ZipInputStream zipInputStream)
+ {
+ this.parent = parent;
+ this.zipEntry = zipEntry;
+ this.zipInputStream = zipInputStream;
+ }
+
+
+ // Implementations for DataEntry.
+
+ public String getName()
+ {
+ // Get the right separators.
+ String name = zipEntry.getName()
+ .replace(File.separatorChar, ClassConstants.PACKAGE_SEPARATOR);
+
+ // Chop the trailing directory slash, if any.
+ int length = name.length();
+ return length > 0 &&
+ name.charAt(length-1) == ClassConstants.PACKAGE_SEPARATOR ?
+ name.substring(0, length -1) :
+ name;
+ }
+
+
+ public boolean isDirectory()
+ {
+ return zipEntry.isDirectory();
+ }
+
+
+ public InputStream getInputStream() throws IOException
+ {
+ if (bufferedInputStream == null)
+ {
+ bufferedInputStream = new BufferedInputStream(zipInputStream);
+ }
+
+ return bufferedInputStream;
+ }
+
+
+ public void closeInputStream() throws IOException
+ {
+ zipInputStream.closeEntry();
+ zipInputStream = null;
+ bufferedInputStream = null;
+ }
+
+
+ public DataEntry getParent()
+ {
+ return parent;
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return parent.toString() + ':' + getName();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/io/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/io/package.html
new file mode 100644
index 0000000000..4ad9f41937
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/io/package.html
@@ -0,0 +1,4 @@
+<body>
+This package contains classes to read and write files, optionally wrapped in
+jars, wars, ears, zips, directories,...
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/AttributeShrinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/AttributeShrinker.java
new file mode 100644
index 0000000000..1916797a37
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/AttributeShrinker.java
@@ -0,0 +1,120 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+import java.util.Arrays;
+
+/**
+ * This ClassVisitor removes attributes that are not marked as being used or
+ * required.
+ *
+ * @see AttributeUsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class AttributeShrinker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Compact the array for class attributes.
+ programClass.u2attributesCount =
+ shrinkArray(programClass.attributes,
+ programClass.u2attributesCount);
+
+ // Compact the attributes in fields, methods, and class attributes,
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+ programClass.attributesAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Library classes are left unchanged.
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ // Compact the attributes array.
+ programMember.u2attributesCount =
+ shrinkArray(programMember.attributes,
+ programMember.u2attributesCount);
+
+ // Compact any attributes of the remaining attributes.
+ programMember.attributesAccept(programClass, this);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Compact the attributes array.
+ codeAttribute.u2attributesCount =
+ shrinkArray(codeAttribute.attributes,
+ codeAttribute.u2attributesCount);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Removes all VisitorAccepter objects that are not marked as being used
+ * from the given array.
+ * @return the new number of VisitorAccepter objects.
+ */
+ private static int shrinkArray(VisitorAccepter[] array, int length)
+ {
+ int counter = 0;
+
+ // Shift the used objects together.
+ for (int index = 0; index < length; index++)
+ {
+ if (AttributeUsageMarker.isUsed(array[index]))
+ {
+ array[counter++] = array[index];
+ }
+ }
+
+ // Clear the remaining array elements.
+ Arrays.fill(array, counter, length, null);
+
+ return counter;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/AttributeUsageMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/AttributeUsageMarker.java
new file mode 100644
index 0000000000..45b7fabd09
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/AttributeUsageMarker.java
@@ -0,0 +1,71 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor marks all attributes that it visits.
+ *
+ * @see AttributeShrinker
+ *
+ * @author Eric Lafortune
+ */
+public class AttributeUsageMarker
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ // A visitor info flag to indicate the attribute is being used.
+ private static final Object USED = new Object();
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute)
+ {
+ markAsUsed(attribute);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given VisitorAccepter as being used (or useful).
+ * In this context, the VisitorAccepter will be an Attribute object.
+ */
+ private static void markAsUsed(VisitorAccepter visitorAccepter)
+ {
+ visitorAccepter.setVisitorInfo(USED);
+ }
+
+
+ /**
+ * Returns whether the given VisitorAccepter has been marked as being used.
+ * In this context, the VisitorAccepter will be an Attribute object.
+ */
+ static boolean isUsed(VisitorAccepter visitorAccepter)
+ {
+ return visitorAccepter.getVisitorInfo() == USED;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ClassObfuscator.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ClassObfuscator.java
new file mode 100644
index 0000000000..bafe1ffc1e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ClassObfuscator.java
@@ -0,0 +1,569 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.ClassVisitor;
+import proguard.util.*;
+
+import java.util.*;
+
+/**
+ * This <code>ClassVisitor</code> comes up with obfuscated names for the
+ * classes it visits, and for their class members. The actual renaming is
+ * done afterward.
+ *
+ * @see ClassRenamer
+ *
+ * @author Eric Lafortune
+ */
+public class ClassObfuscator
+extends SimplifiedVisitor
+implements ClassVisitor,
+ AttributeVisitor,
+ InnerClassesInfoVisitor,
+ ConstantVisitor
+{
+ private final DictionaryNameFactory classNameFactory;
+ private final DictionaryNameFactory packageNameFactory;
+ private final boolean useMixedCaseClassNames;
+ private final StringMatcher keepPackageNamesMatcher;
+ private final String flattenPackageHierarchy;
+ private final String repackageClasses;
+ private final boolean allowAccessModification;
+
+ private final Set classNamesToAvoid = new HashSet();
+
+ // Map: [package prefix - new package prefix]
+ private final Map packagePrefixMap = new HashMap();
+
+ // Map: [package prefix - package name factory]
+ private final Map packagePrefixPackageNameFactoryMap = new HashMap();
+
+ // Map: [package prefix - numeric class name factory]
+ private final Map packagePrefixClassNameFactoryMap = new HashMap();
+
+ // Map: [package prefix - numeric class name factory]
+ private final Map packagePrefixNumericClassNameFactoryMap = new HashMap();
+
+ // Field acting as temporary variables and as return values for names
+ // of outer classes and types of inner classes.
+ private String newClassName;
+ private boolean numericClassName;
+
+
+ /**
+ * Creates a new ClassObfuscator.
+ * @param programClassPool the class pool in which class names
+ * have to be unique.
+ * @param libraryClassPool the class pool from which class names
+ * have to be avoided.
+ * @param classNameFactory the optional class obfuscation dictionary.
+ * @param packageNameFactory the optional package obfuscation
+ * dictionary.
+ * @param useMixedCaseClassNames specifies whether obfuscated packages and
+ * classes can get mixed-case names.
+ * @param keepPackageNames the optional filter for which matching
+ * package names are kept.
+ * @param flattenPackageHierarchy the base package if the obfuscated package
+ * hierarchy is to be flattened.
+ * @param repackageClasses the base package if the obfuscated classes
+ * are to be repackaged.
+ * @param allowAccessModification specifies whether obfuscated classes can
+ * be freely moved between packages.
+ */
+ public ClassObfuscator(ClassPool programClassPool,
+ ClassPool libraryClassPool,
+ DictionaryNameFactory classNameFactory,
+ DictionaryNameFactory packageNameFactory,
+ boolean useMixedCaseClassNames,
+ List keepPackageNames,
+ String flattenPackageHierarchy,
+ String repackageClasses,
+ boolean allowAccessModification)
+ {
+ this.classNameFactory = classNameFactory;
+ this.packageNameFactory = packageNameFactory;
+
+ // First append the package separator if necessary.
+ if (flattenPackageHierarchy != null &&
+ flattenPackageHierarchy.length() > 0)
+ {
+ flattenPackageHierarchy += ClassConstants.PACKAGE_SEPARATOR;
+ }
+
+ // First append the package separator if necessary.
+ if (repackageClasses != null &&
+ repackageClasses.length() > 0)
+ {
+ repackageClasses += ClassConstants.PACKAGE_SEPARATOR;
+ }
+
+ this.useMixedCaseClassNames = useMixedCaseClassNames;
+ this.keepPackageNamesMatcher = keepPackageNames == null ? null :
+ new ListParser(new FileNameParser()).parse(keepPackageNames);
+ this.flattenPackageHierarchy = flattenPackageHierarchy;
+ this.repackageClasses = repackageClasses;
+ this.allowAccessModification = allowAccessModification;
+
+ // Map the root package onto the root package.
+ packagePrefixMap.put("", "");
+
+ // Collect all names that have already been taken.
+ programClassPool.classesAccept(new MyKeepCollector());
+ libraryClassPool.classesAccept(new MyKeepCollector());
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Does this class still need a new name?
+ newClassName = newClassName(programClass);
+ if (newClassName == null)
+ {
+ // Make sure the outer class has a name, if it exists. The name will
+ // be stored as the new class name, as a side effect, so we'll be
+ // able to use it as a prefix.
+ programClass.attributesAccept(this);
+
+ // Figure out a package prefix. The package prefix may actually be
+ // the an outer class prefix, if any, or it may be the fixed base
+ // package, if classes are to be repackaged.
+ String newPackagePrefix = newClassName != null ?
+ newClassName + ClassConstants.INNER_CLASS_SEPARATOR :
+ newPackagePrefix(ClassUtil.internalPackagePrefix(programClass.getName()));
+
+ // Come up with a new class name, numeric or ordinary.
+ newClassName = newClassName != null && numericClassName ?
+ generateUniqueNumericClassName(newPackagePrefix) :
+ generateUniqueClassName(newPackagePrefix);
+
+ setNewClassName(programClass, newClassName);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // This can happen for dubious input, if the outer class of a program
+ // class is a library class, and its name is requested.
+ newClassName = libraryClass.getName();
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ // Make sure the outer classes have a name, if they exist.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ // Make sure the enclosing class has a name.
+ enclosingMethodAttribute.referencedClassAccept(this);
+
+ String innerClassName = clazz.getName();
+ String outerClassName = clazz.getClassName(enclosingMethodAttribute.u2classIndex);
+
+ numericClassName = isNumericClassName(innerClassName,
+ outerClassName);
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ // Make sure the outer class has a name, if it exists.
+ int innerClassIndex = innerClassesInfo.u2innerClassIndex;
+ int outerClassIndex = innerClassesInfo.u2outerClassIndex;
+ if (innerClassIndex != 0 &&
+ outerClassIndex != 0)
+ {
+ String innerClassName = clazz.getClassName(innerClassIndex);
+ if (innerClassName.equals(clazz.getName()))
+ {
+ clazz.constantPoolEntryAccept(outerClassIndex, this);
+
+ String outerClassName = clazz.getClassName(outerClassIndex);
+
+ numericClassName = isNumericClassName(innerClassName,
+ outerClassName);
+ }
+ }
+ }
+
+
+ /**
+ * Returns whether the given inner class name is a numeric name.
+ */
+ private boolean isNumericClassName(String innerClassName,
+ String outerClassName)
+ {
+ int innerClassNameStart = outerClassName.length() + 1;
+ int innerClassNameLength = innerClassName.length();
+
+ if (innerClassNameStart >= innerClassNameLength)
+ {
+ return false;
+ }
+
+ for (int index = innerClassNameStart; index < innerClassNameLength; index++)
+ {
+ if (!Character.isDigit(innerClassName.charAt(index)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Make sure the outer class has a name.
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ /**
+ * This ClassVisitor collects package names and class names that have to
+ * be kept.
+ */
+ private class MyKeepCollector implements ClassVisitor
+ {
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Does the program class already have a new name?
+ String newClassName = newClassName(programClass);
+ if (newClassName != null)
+ {
+ // Remember not to use this name.
+ classNamesToAvoid.add(mixedCaseClassName(newClassName));
+
+ // Are we not aggressively repackaging all obfuscated classes?
+ if (repackageClasses == null ||
+ !allowAccessModification)
+ {
+ String className = programClass.getName();
+
+ // Keep the package name for all other classes in the same
+ // package. Do this recursively if we're not doing any
+ // repackaging.
+ mapPackageName(className,
+ newClassName,
+ repackageClasses == null &&
+ flattenPackageHierarchy == null);
+ }
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Get the new name or the original name of the library class.
+ String newClassName = newClassName(libraryClass);
+ if (newClassName == null)
+ {
+ newClassName = libraryClass.getName();
+ }
+
+ // Remember not to use this name.
+ classNamesToAvoid.add(mixedCaseClassName(newClassName));
+
+ // Are we not aggressively repackaging all obfuscated classes?
+ if (repackageClasses == null ||
+ !allowAccessModification)
+ {
+ String className = libraryClass.getName();
+
+ // Keep the package name for all other classes in the same
+ // package. Do this recursively if we're not doing any
+ // repackaging.
+ mapPackageName(className,
+ newClassName,
+ repackageClasses == null &&
+ flattenPackageHierarchy == null);
+ }
+ }
+
+
+ /**
+ * Makes sure the package name of the given class will always be mapped
+ * consistently with its new name.
+ */
+ private void mapPackageName(String className,
+ String newClassName,
+ boolean recursively)
+ {
+ String packagePrefix = ClassUtil.internalPackagePrefix(className);
+ String newPackagePrefix = ClassUtil.internalPackagePrefix(newClassName);
+
+ // Put the mapping of this package prefix, and possibly of its
+ // entire hierarchy, into the package prefix map.
+ do
+ {
+ packagePrefixMap.put(packagePrefix, newPackagePrefix);
+
+ if (!recursively)
+ {
+ break;
+ }
+
+ packagePrefix = ClassUtil.internalPackagePrefix(packagePrefix);
+ newPackagePrefix = ClassUtil.internalPackagePrefix(newPackagePrefix);
+ }
+ while (packagePrefix.length() > 0 &&
+ newPackagePrefix.length() > 0);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Finds or creates the new package prefix for the given package.
+ */
+ private String newPackagePrefix(String packagePrefix)
+ {
+ // Doesn't the package prefix have a new package prefix yet?
+ String newPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
+ if (newPackagePrefix == null)
+ {
+ // Are we keeping the package name?
+ if (keepPackageNamesMatcher != null &&
+ keepPackageNamesMatcher.matches(packagePrefix.length() > 0 ?
+ packagePrefix.substring(0, packagePrefix.length()-1) :
+ packagePrefix))
+ {
+ return packagePrefix;
+ }
+
+ // Are we forcing a new package prefix?
+ if (repackageClasses != null)
+ {
+ return repackageClasses;
+ }
+
+ // Are we forcing a new superpackage prefix?
+ // Otherwise figure out the new superpackage prefix, recursively.
+ String newSuperPackagePrefix = flattenPackageHierarchy != null ?
+ flattenPackageHierarchy :
+ newPackagePrefix(ClassUtil.internalPackagePrefix(packagePrefix));
+
+ // Come up with a new package prefix.
+ newPackagePrefix = generateUniquePackagePrefix(newSuperPackagePrefix);
+
+ // Remember to use this mapping in the future.
+ packagePrefixMap.put(packagePrefix, newPackagePrefix);
+ }
+
+ return newPackagePrefix;
+ }
+
+
+ /**
+ * Creates a new package prefix in the given new superpackage.
+ */
+ private String generateUniquePackagePrefix(String newSuperPackagePrefix)
+ {
+ // Find the right name factory for this package.
+ NameFactory packageNameFactory =
+ (NameFactory)packagePrefixPackageNameFactoryMap.get(newSuperPackagePrefix);
+ if (packageNameFactory == null)
+ {
+ // We haven't seen packages in this superpackage before. Create
+ // a new name factory for them.
+ packageNameFactory = new SimpleNameFactory(useMixedCaseClassNames);
+ if (this.packageNameFactory != null)
+ {
+ packageNameFactory =
+ new DictionaryNameFactory(this.packageNameFactory,
+ packageNameFactory);
+ }
+
+ packagePrefixPackageNameFactoryMap.put(newSuperPackagePrefix,
+ packageNameFactory);
+ }
+
+ return generateUniquePackagePrefix(newSuperPackagePrefix, packageNameFactory);
+ }
+
+
+ /**
+ * Creates a new package prefix in the given new superpackage, with the
+ * given package name factory.
+ */
+ private String generateUniquePackagePrefix(String newSuperPackagePrefix,
+ NameFactory packageNameFactory)
+ {
+ // Come up with package names until we get an original one.
+ String newPackagePrefix;
+ do
+ {
+ // Let the factory produce a package name.
+ newPackagePrefix = newSuperPackagePrefix +
+ packageNameFactory.nextName() +
+ ClassConstants.PACKAGE_SEPARATOR;
+ }
+ while (packagePrefixMap.containsValue(newPackagePrefix));
+
+ return newPackagePrefix;
+ }
+
+
+ /**
+ * Creates a new class name in the given new package.
+ */
+ private String generateUniqueClassName(String newPackagePrefix)
+ {
+ // Find the right name factory for this package.
+ NameFactory classNameFactory =
+ (NameFactory)packagePrefixClassNameFactoryMap.get(newPackagePrefix);
+ if (classNameFactory == null)
+ {
+ // We haven't seen classes in this package before.
+ // Create a new name factory for them.
+ classNameFactory = new SimpleNameFactory(useMixedCaseClassNames);
+ if (this.classNameFactory != null)
+ {
+ classNameFactory =
+ new DictionaryNameFactory(this.classNameFactory,
+ classNameFactory);
+ }
+
+ packagePrefixClassNameFactoryMap.put(newPackagePrefix,
+ classNameFactory);
+ }
+
+ return generateUniqueClassName(newPackagePrefix, classNameFactory);
+ }
+
+
+ /**
+ * Creates a new class name in the given new package.
+ */
+ private String generateUniqueNumericClassName(String newPackagePrefix)
+ {
+ // Find the right name factory for this package.
+ NameFactory classNameFactory =
+ (NameFactory)packagePrefixNumericClassNameFactoryMap.get(newPackagePrefix);
+ if (classNameFactory == null)
+ {
+ // We haven't seen classes in this package before.
+ // Create a new name factory for them.
+ classNameFactory = new NumericNameFactory();
+
+ packagePrefixNumericClassNameFactoryMap.put(newPackagePrefix,
+ classNameFactory);
+ }
+
+ return generateUniqueClassName(newPackagePrefix, classNameFactory);
+ }
+
+
+ /**
+ * Creates a new class name in the given new package, with the given
+ * class name factory.
+ */
+ private String generateUniqueClassName(String newPackagePrefix,
+ NameFactory classNameFactory)
+ {
+ // Come up with class names until we get an original one.
+ String newClassName;
+ String newMixedCaseClassName;
+ do
+ {
+ // Let the factory produce a class name.
+ newClassName = newPackagePrefix +
+ classNameFactory.nextName();
+
+ newMixedCaseClassName = mixedCaseClassName(newClassName);
+ }
+ while (classNamesToAvoid.contains(newMixedCaseClassName));
+
+ // Explicitly make sure the name isn't used again if we have a
+ // user-specified dictionary and we're not allowed to have mixed case
+ // class names -- just to protect against problematic dictionaries.
+ if (this.classNameFactory != null &&
+ !useMixedCaseClassNames)
+ {
+ classNamesToAvoid.add(newMixedCaseClassName);
+ }
+
+ return newClassName;
+ }
+
+
+ /**
+ * Returns the given class name, unchanged if mixed-case class names are
+ * allowed, or the lower-case version otherwise.
+ */
+ private String mixedCaseClassName(String className)
+ {
+ return useMixedCaseClassNames ?
+ className :
+ className.toLowerCase();
+ }
+
+
+ /**
+ * Assigns a new name to the given class.
+ * @param clazz the given class.
+ * @param name the new name.
+ */
+ static void setNewClassName(Clazz clazz, String name)
+ {
+ clazz.setVisitorInfo(name);
+ }
+
+
+ /**
+ * Retrieves the new name of the given class.
+ * @param clazz the given class.
+ * @return the class's new name, or <code>null</code> if it doesn't
+ * have one yet.
+ */
+ static String newClassName(Clazz clazz)
+ {
+ Object visitorInfo = clazz.getVisitorInfo();
+
+ return visitorInfo instanceof String ?
+ (String)visitorInfo :
+ null;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ClassRenamer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ClassRenamer.java
new file mode 100644
index 0000000000..47a6568985
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ClassRenamer.java
@@ -0,0 +1,109 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.ConstantPoolEditor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This <code>ClassVisitor</code> renames the class names and class member
+ * names of the classes it visits, using names previously determined by the
+ * obfuscator.
+ *
+ * @see ClassObfuscator
+ * @see MemberObfuscator
+ *
+ * @author Eric Lafortune
+ */
+public class ClassRenamer
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ ConstantVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Rename this class.
+ programClass.thisClassConstantAccept(this);
+
+ // Rename the class members.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ libraryClass.thisClassName = ClassObfuscator.newClassName(libraryClass);
+
+ // Rename the class members.
+ libraryClass.fieldsAccept(this);
+ libraryClass.methodsAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass,
+ ProgramMember programMember)
+ {
+ // Has the class member name changed?
+ String name = programMember.getName(programClass);
+ String newName = MemberObfuscator.newMemberName(programMember);
+ if (newName != null &&
+ !newName.equals(name))
+ {
+ programMember.u2nameIndex =
+ new ConstantPoolEditor(programClass).addUtf8Constant(newName);
+ }
+ }
+
+ public void visitLibraryMember(LibraryClass libraryClass,
+ LibraryMember libraryMember)
+ {
+ String newName = MemberObfuscator.newMemberName(libraryMember);
+ if (newName != null)
+ {
+ libraryMember.name = newName;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Update the Class entry if required.
+ String newName = ClassObfuscator.newClassName(clazz);
+ if (newName != null)
+ {
+ // Refer to a new Utf8 entry.
+ classConstant.u2nameIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newName);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/DictionaryNameFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/DictionaryNameFactory.java
new file mode 100644
index 0000000000..59fa69b580
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/DictionaryNameFactory.java
@@ -0,0 +1,189 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This <code>NameFactory</code> generates names that are read from a
+ * specified input file.
+ * Comments (everything starting with '#' on a single line) are ignored.
+ *
+ * @author Eric Lafortune
+ */
+public class DictionaryNameFactory implements NameFactory
+{
+ private static final char COMMENT_CHARACTER = '#';
+
+
+ private final List names;
+ private final NameFactory nameFactory;
+
+ private int index = 0;
+
+
+ /**
+ * Creates a new <code>DictionaryNameFactory</code>.
+ * @param file the file from which the names can be read.
+ * @param nameFactory the name factory from which names will be retrieved
+ * if the list of read names has been exhausted.
+ */
+ public DictionaryNameFactory(File file,
+ NameFactory nameFactory) throws IOException
+ {
+ this.names = new ArrayList();
+ this.nameFactory = nameFactory;
+
+ Reader reader = new FileReader(file);
+
+ try
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ while (true)
+ {
+ // Read the next character.
+ int c = reader.read();
+
+ // Is it a valid identifier character?
+ if (c != -1 &&
+ (buffer.length() == 0 ?
+ Character.isJavaIdentifierStart((char)c) :
+ Character.isJavaIdentifierPart((char)c)))
+ {
+ // Append it to the current identifier.
+ buffer.append((char)c);
+ }
+ else
+ {
+ // Did we collect a new identifier?
+ if (buffer.length() > 0)
+ {
+ // Add the completed name to the list of names, if it's
+ // not in it yet.
+ String name = buffer.toString();
+ if (!names.contains(name))
+ {
+ names.add(name);
+ }
+
+ // Clear the buffer.
+ buffer.setLength(0);
+ }
+
+ // Is this the beginning of a comment line?
+ if (c == COMMENT_CHARACTER)
+ {
+ // Skip all characters till the end of the line.
+ do
+ {
+ c = reader.read();
+ }
+ while (c != -1 &&
+ c != '\n' &&
+ c != '\r');
+ }
+
+ // Is this the end of the file?
+ if (c == -1)
+ {
+ // Just return.
+ return;
+ }
+ }
+ }
+ }
+ finally
+ {
+ reader.close();
+ }
+ }
+
+
+ /**
+ * Creates a new <code>DictionaryNameFactory</code>.
+ * @param dictionaryNameFactory the dictionary name factory whose dictionary
+ * will be used.
+ * @param nameFactory the name factory from which names will be
+ * retrieved if the list of read names has been
+ * exhausted.
+ */
+ public DictionaryNameFactory(DictionaryNameFactory dictionaryNameFactory,
+ NameFactory nameFactory)
+ {
+ this.names = dictionaryNameFactory.names;
+ this.nameFactory = nameFactory;
+ }
+
+
+ // Implementations for NameFactory.
+
+ public void reset()
+ {
+ index = 0;
+
+ nameFactory.reset();
+ }
+
+
+ public String nextName()
+ {
+ String name;
+
+ // Do we still have names?
+ if (index < names.size())
+ {
+ // Return the next name.
+ name = (String)names.get(index++);
+ }
+ else
+ {
+ // Return the next different name from the other name factory.
+ do
+ {
+ name = nameFactory.nextName();
+ }
+ while (names.contains(name));
+ }
+
+ return name;
+ }
+
+
+ public static void main(String[] args)
+ {
+ try
+ {
+ DictionaryNameFactory factory =
+ new DictionaryNameFactory(new File(args[0]), new SimpleNameFactory());
+
+ for (int counter = 0; counter < 50; counter++)
+ {
+ System.out.println("["+factory.nextName()+"]");
+ }
+ }
+ catch (IOException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MapCleaner.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MapCleaner.java
new file mode 100644
index 0000000000..70bc4c33ec
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MapCleaner.java
@@ -0,0 +1,57 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.util.Map;
+
+/**
+ * This ClassVisitor clears a given map whenever it visits a class.
+ *
+ * @author Eric Lafortune
+ */
+public class MapCleaner
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final Map map;
+
+
+ /**
+ * Creates a new MapCleaner.
+ * @param map the map to be cleared.
+ */
+ public MapCleaner(Map map)
+ {
+ this.map = map;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ map.clear();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingKeeper.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingKeeper.java
new file mode 100644
index 0000000000..4025c1a21a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingKeeper.java
@@ -0,0 +1,180 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.util.ListUtil;
+
+/**
+ * This MappingKeeper applies the mappings that it receives to its class pool,
+ * so these mappings are ensured in a subsequent obfuscation step.
+ *
+ * @author Eric Lafortune
+ */
+public class MappingKeeper implements MappingProcessor
+{
+ private final ClassPool classPool;
+ private final WarningPrinter warningPrinter;
+
+ // A field acting as a parameter.
+ private Clazz clazz;
+
+
+ /**
+ * Creates a new MappingKeeper.
+ * @param classPool the class pool in which class names and class
+ * member names have to be mapped.
+ * @param warningPrinter the optional warning printer to which warnings
+ * can be printed.
+ */
+ public MappingKeeper(ClassPool classPool,
+ WarningPrinter warningPrinter)
+ {
+ this.classPool = classPool;
+ this.warningPrinter = warningPrinter;
+ }
+
+
+ // Implementations for MappingProcessor.
+
+ public boolean processClassMapping(String className,
+ String newClassName)
+ {
+ // Find the class.
+ String name = ClassUtil.internalClassName(className);
+
+ clazz = classPool.getClass(name);
+ if (clazz != null)
+ {
+ String newName = ClassUtil.internalClassName(newClassName);
+
+ // Print out a warning if the mapping conflicts with a name that
+ // was set before.
+ if (warningPrinter != null)
+ {
+ String currentNewName = ClassObfuscator.newClassName(clazz);
+ if (currentNewName != null &&
+ !currentNewName.equals(newName))
+ {
+ warningPrinter.print(name,
+ currentNewName,
+ "Warning: " +
+ className +
+ " is not being kept as '" +
+ ClassUtil.externalClassName(currentNewName) +
+ "', but remapped to '" +
+ newClassName + "'");
+ }
+ }
+
+ ClassObfuscator.setNewClassName(clazz, newName);
+
+ // The class members have to be kept as well.
+ return true;
+ }
+
+ return false;
+ }
+
+
+ public void processFieldMapping(String className,
+ String fieldType,
+ String fieldName,
+ String newClassName,
+ String newFieldName)
+ {
+ if (clazz != null && className.equals(newClassName))
+ {
+ // Find the field.
+ String name = fieldName;
+ String descriptor = ClassUtil.internalType(fieldType);
+
+ Field field = clazz.findField(name, descriptor);
+ if (field != null)
+ {
+ // Print out a warning if the mapping conflicts with a name that
+ // was set before.
+ if (warningPrinter != null)
+ {
+ String currentNewName = MemberObfuscator.newMemberName(field);
+ if (currentNewName != null &&
+ !currentNewName.equals(newFieldName))
+ {
+ warningPrinter.print(ClassUtil.internalClassName(className),
+ "Warning: " +
+ className +
+ ": field '" + fieldType + " " + fieldName +
+ "' is not being kept as '" + currentNewName +
+ "', but remapped to '" + newFieldName + "'");
+ }
+ }
+
+ // Make sure the mapping name will be kept.
+ MemberObfuscator.setFixedNewMemberName(field, newFieldName);
+ }
+ }
+ }
+
+
+ public void processMethodMapping(String className,
+ int firstLineNumber,
+ int lastLineNumber,
+ String methodReturnType,
+ String methodName,
+ String methodArguments,
+ String newClassName,
+ int newFirstLineNumber,
+ int newLastLineNumber,
+ String newMethodName)
+ {
+ if (clazz != null && className.equals(newClassName))
+ {
+ // Find the method.
+ String descriptor = ClassUtil.internalMethodDescriptor(methodReturnType,
+ ListUtil.commaSeparatedList(methodArguments));
+
+ Method method = clazz.findMethod(methodName, descriptor);
+ if (method != null)
+ {
+ // Print out a warning if the mapping conflicts with a name that
+ // was set before.
+ if (warningPrinter != null)
+ {
+ String currentNewName = MemberObfuscator.newMemberName(method);
+ if (currentNewName != null &&
+ !currentNewName.equals(newMethodName))
+ {
+ warningPrinter.print(ClassUtil.internalClassName(className),
+ "Warning: " +
+ className +
+ ": method '" + methodReturnType + " " + methodName + JavaConstants.METHOD_ARGUMENTS_OPEN + methodArguments + JavaConstants.METHOD_ARGUMENTS_CLOSE +
+ "' is not being kept as '" + currentNewName +
+ "', but remapped to '" + newMethodName + "'");
+ }
+ }
+
+ // Make sure the mapping name will be kept.
+ MemberObfuscator.setFixedNewMemberName(method, newMethodName);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingPrinter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingPrinter.java
new file mode 100644
index 0000000000..50f6e49bc0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingPrinter.java
@@ -0,0 +1,365 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.optimize.peephole.LineNumberLinearizer;
+
+import java.io.PrintStream;
+import java.util.Stack;
+
+
+/**
+ * This ClassVisitor prints out the renamed classes and class members with
+ * their old names and new names.
+ *
+ * @see ClassRenamer
+ *
+ * @author Eric Lafortune
+ */
+public class MappingPrinter
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor
+{
+ private final PrintStream ps;
+
+ // A field serving as a return value for the visitor methods.
+ private boolean printed;
+
+
+ /**
+ * Creates a new MappingPrinter that prints to <code>System.out</code>.
+ */
+ public MappingPrinter()
+ {
+ this(System.out);
+ }
+
+
+ /**
+ * Creates a new MappingPrinter that prints to the given stream.
+ * @param printStream the stream to which to print
+ */
+ public MappingPrinter(PrintStream printStream)
+ {
+ this.ps = printStream;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ String name = programClass.getName();
+ String newName = ClassObfuscator.newClassName(programClass);
+
+ // Print out the class mapping.
+ ps.println(ClassUtil.externalClassName(name) +
+ " -> " +
+ ClassUtil.externalClassName(newName) +
+ ":");
+
+ // Print out the class members.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ String fieldName = programField.getName(programClass);
+ String obfuscatedFieldName = MemberObfuscator.newMemberName(programField);
+ if (obfuscatedFieldName == null)
+ {
+ obfuscatedFieldName = fieldName;
+ }
+
+ // Print out the field mapping.
+ ps.println(" " +
+ ClassUtil.externalType(programField.getDescriptor(programClass)) + " " +
+ fieldName +
+ " -> " +
+ obfuscatedFieldName);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ String methodName = programMethod.getName(programClass);
+ String obfuscatedMethodName = MemberObfuscator.newMemberName(programMethod);
+ if (obfuscatedMethodName == null)
+ {
+ obfuscatedMethodName = methodName;
+ }
+
+ // Print out the method mapping, if it has line numbers.
+ printed = false;
+ programMethod.attributesAccept(programClass, this);
+
+ // Otherwise print out the method mapping without line numbers.
+ if (!printed)
+ {
+ ps.println(" " +
+ ClassUtil.externalMethodReturnType(programMethod.getDescriptor(programClass)) + " " +
+ methodName + JavaConstants.METHOD_ARGUMENTS_OPEN +
+ ClassUtil.externalMethodArguments(programMethod.getDescriptor(programClass)) + JavaConstants.METHOD_ARGUMENTS_CLOSE +
+ " -> " +
+ obfuscatedMethodName);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ LineNumberInfo[] lineNumberTable = lineNumberTableAttribute.lineNumberTable;
+ int lineNumberTableLength = lineNumberTableAttribute.u2lineNumberTableLength;
+
+ String methodName = method.getName(clazz);
+ String methodDescriptor = method.getDescriptor(clazz);
+ String obfuscatedMethodName = MemberObfuscator.newMemberName(method);
+ if (obfuscatedMethodName == null)
+ {
+ obfuscatedMethodName = methodName;
+ }
+
+ int lowestLineNumber = lineNumberTableAttribute.getLowestLineNumber();
+ int highestLineNumber = lineNumberTableAttribute.getHighestLineNumber();
+
+ // Does the method have any local line numbers at all?
+ if (lineNumberTableAttribute.getSource(codeAttribute.u4codeLength) == null)
+ {
+ if (lowestLineNumber > 0)
+ {
+ // Print out the line number range of the method,
+ // ignoring line numbers of any inlined methods.
+ ps.println(" " +
+ lowestLineNumber + ":" +
+ highestLineNumber + ":" +
+ ClassUtil.externalMethodReturnType(method.getDescriptor(clazz)) + " " +
+ methodName + JavaConstants.METHOD_ARGUMENTS_OPEN +
+ ClassUtil.externalMethodArguments(method.getDescriptor(clazz)) + JavaConstants.METHOD_ARGUMENTS_CLOSE +
+ " -> " +
+ obfuscatedMethodName);
+ }
+ else
+ {
+ // Print out the method mapping without line numbers.
+ ps.println(" " +
+ ClassUtil.externalMethodReturnType(method.getDescriptor(clazz)) + " " +
+ methodName + JavaConstants.METHOD_ARGUMENTS_OPEN +
+ ClassUtil.externalMethodArguments(method.getDescriptor(clazz)) + JavaConstants.METHOD_ARGUMENTS_CLOSE +
+ " -> " +
+ obfuscatedMethodName);
+ }
+ }
+
+ // Print out the line numbers of any inlined methods and their
+ // enclosing methods.
+ Stack enclosingLineNumbers = new Stack();
+
+ LineNumberInfo previousInfo = new LineNumberInfo(0, 0);
+
+ for (int index = 0; index < lineNumberTableLength; index++)
+ {
+ LineNumberInfo info = lineNumberTable[index];
+
+ // Are we entering or exiting an inlined block (or a merged block)?
+ // We're testing on the identities out of convenience.
+ String previousSource = previousInfo.getSource();
+ String source = info.getSource();
+ if (source != previousSource)
+ {
+ // Are we entering or exiting the block?
+ int previousLineNumber = previousInfo.u2lineNumber;
+ int lineNumber = info.u2lineNumber;
+ if (lineNumber > previousLineNumber)
+ {
+ // We're entering an inlined block.
+ // Accumulate its enclosing line numbers, so they can be
+ // printed out for each inlined block.
+ if (index > 0)
+ {
+ enclosingLineNumbers.push(previousInfo);
+ }
+
+ printInlinedMethodMapping(clazz.getName(),
+ methodName,
+ methodDescriptor,
+ info,
+ enclosingLineNumbers,
+ obfuscatedMethodName);
+ }
+ // TODO: There appear to be cases where the stack is empty at this point, so we've added a check.
+ else if (!enclosingLineNumbers.isEmpty())
+ {
+ // We're exiting an inlined block.
+ // Pop its enclosing line number.
+ enclosingLineNumbers.pop();
+ }
+ }
+
+ previousInfo = info;
+ }
+
+ printed = true;
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Prints out the mapping of the specified inlined methods and its
+ * enclosing methods.
+ */
+ private void printInlinedMethodMapping(String className,
+ String methodName,
+ String methodDescriptor,
+ LineNumberInfo inlinedInfo,
+ Stack enclosingLineNumbers,
+ String obfuscatedMethodName)
+ {
+ String source = inlinedInfo.getSource();
+
+ // Parse the information from the source string of the
+ // inlined method.
+ int separatorIndex1 = source.indexOf('.');
+ int separatorIndex2 = source.indexOf('(', separatorIndex1 + 1);
+ int separatorIndex3 = source.indexOf(':', separatorIndex2 + 1);
+ int separatorIndex4 = source.indexOf(':', separatorIndex3 + 1);
+
+ String inlinedClassName = source.substring(0, separatorIndex1);
+ String inlinedMethodName = source.substring(separatorIndex1 + 1, separatorIndex2);
+ String inlinedMethodDescriptor = source.substring(separatorIndex2, separatorIndex3);
+ String inlinedRange = source.substring(separatorIndex3);
+
+ int startLineNumber = Integer.parseInt(source.substring(separatorIndex3 + 1, separatorIndex4));
+ int endLineNumber = Integer.parseInt(source.substring(separatorIndex4 + 1));
+
+ // Compute the shifted line number range.
+ int shiftedStartLineNumber = inlinedInfo.u2lineNumber;
+ int shiftedEndLineNumber = shiftedStartLineNumber + endLineNumber - startLineNumber;
+
+ // Print out the line number range of the inlined method.
+ ps.println(" " +
+ shiftedStartLineNumber + ":" +
+ shiftedEndLineNumber + ":" +
+ ClassUtil.externalMethodReturnType(inlinedMethodDescriptor) + " " +
+ (inlinedClassName.equals(className) ? "" :
+ ClassUtil.externalClassName(inlinedClassName) + JavaConstants.PACKAGE_SEPARATOR) +
+ inlinedMethodName + JavaConstants.METHOD_ARGUMENTS_OPEN +
+ ClassUtil.externalMethodArguments(inlinedMethodDescriptor) + JavaConstants.METHOD_ARGUMENTS_CLOSE +
+ inlinedRange + " -> " +
+ obfuscatedMethodName);
+
+ // Print out the line numbers of the accumulated enclosing
+ // methods.
+ for (int enclosingIndex = enclosingLineNumbers.size()-1; enclosingIndex >= 0; enclosingIndex--)
+ {
+ LineNumberInfo enclosingInfo =
+ (LineNumberInfo)enclosingLineNumbers.get(enclosingIndex);
+
+ printEnclosingMethodMapping(className,
+ methodName,
+ methodDescriptor,
+ shiftedStartLineNumber + ":" +
+ shiftedEndLineNumber,
+ enclosingInfo,
+ obfuscatedMethodName);
+
+
+ }
+ }
+
+
+ /**
+ * Prints out the mapping of the specified enclosing method.
+ */
+ private void printEnclosingMethodMapping(String className,
+ String methodName,
+ String methodDescriptor,
+ String shiftedRange,
+ LineNumberInfo enclosingInfo,
+ String obfuscatedMethodName)
+ {
+ // Parse the information from the source string of the enclosing
+ // method.
+ String enclosingSource = enclosingInfo.getSource();
+
+ String enclosingClassName;
+ String enclosingMethodName;
+ String enclosingMethodDescriptor;
+ int enclosingLineNumber;
+
+ if (enclosingSource == null)
+ {
+ enclosingClassName = className;
+ enclosingMethodName = methodName;
+ enclosingMethodDescriptor = methodDescriptor;
+ enclosingLineNumber = enclosingInfo.u2lineNumber;
+ }
+ else
+ {
+ int enclosingSeparatorIndex1 = enclosingSource.indexOf('.');
+ int enclosingSeparatorIndex2 = enclosingSource.indexOf('(', enclosingSeparatorIndex1 + 1);
+ int enclosingSeparatorIndex3 = enclosingSource.indexOf(':', enclosingSeparatorIndex2 + 1);
+ int enclosingSeparatorIndex4 = enclosingSource.indexOf(':', enclosingSeparatorIndex3 + 1);
+
+ // We need the first line number to correct the shifted enclosing
+ // line number back to its original range.
+ int firstLineNumber = Integer.parseInt(enclosingSource.substring(enclosingSeparatorIndex3 + 1, enclosingSeparatorIndex4));
+
+ enclosingClassName = enclosingSource.substring(0, enclosingSeparatorIndex1);
+ enclosingMethodName = enclosingSource.substring(enclosingSeparatorIndex1 + 1, enclosingSeparatorIndex2);
+ enclosingMethodDescriptor = enclosingSource.substring(enclosingSeparatorIndex2, enclosingSeparatorIndex3);
+ enclosingLineNumber = (enclosingInfo.u2lineNumber - firstLineNumber) % LineNumberLinearizer.SHIFT_ROUNDING + firstLineNumber;
+ }
+
+ // Print out the line number of the enclosing method.
+ ps.println(" " +
+ shiftedRange + ":" +
+ ClassUtil.externalMethodReturnType(enclosingMethodDescriptor) + " " +
+ (enclosingClassName.equals(className) ? "" :
+ ClassUtil.externalClassName(enclosingClassName) + JavaConstants.PACKAGE_SEPARATOR) +
+ enclosingMethodName + JavaConstants.METHOD_ARGUMENTS_OPEN +
+ ClassUtil.externalMethodArguments(enclosingMethodDescriptor) + JavaConstants.METHOD_ARGUMENTS_CLOSE + ":" +
+ enclosingLineNumber + " -> " +
+ obfuscatedMethodName);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingProcessor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingProcessor.java
new file mode 100644
index 0000000000..d7494cad85
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingProcessor.java
@@ -0,0 +1,86 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+/**
+ * This interface specifies methods to process name mappings between original
+ * classes and their obfuscated versions. The mappings are typically read
+ * from a mapping file.
+ *
+ * @see MappingReader
+ *
+ * @author Eric Lafortune
+ */
+public interface MappingProcessor
+{
+ /**
+ * Processes the given class name mapping.
+ *
+ * @param className the original class name.
+ * @param newClassName the new class name.
+ * @return whether the processor is interested in receiving mappings of the
+ * class members of this class.
+ */
+ public boolean processClassMapping(String className,
+ String newClassName);
+
+ /**
+ * Processes the given field name mapping.
+ * @param className the original class name.
+ * @param fieldType the original external field type.
+ * @param fieldName the original field name.
+ * @param newClassName the new class name.
+ * @param newFieldName the new field name.
+ */
+ public void processFieldMapping(String className,
+ String fieldType,
+ String fieldName,
+ String newClassName,
+ String newFieldName);
+
+ /**
+ * Processes the given method name mapping.
+ * @param className the original class name.
+ * @param firstLineNumber the first line number of the method, or 0 if
+ * it is not known.
+ * @param lastLineNumber the last line number of the method, or 0 if
+ * it is not known.
+ * @param methodReturnType the original external method return type.
+ * @param methodName the original external method name.
+ * @param methodArguments the original external method arguments.
+ * @param newClassName the new class name.
+ * @param newFirstLineNumber the new first line number of the method, or 0
+ * if it is not known.
+ * @param newLastLineNumber the new last line number of the method, or 0
+ * if it is not known.
+ * @param newMethodName the new method name.
+ */
+ public void processMethodMapping(String className,
+ int firstLineNumber,
+ int lastLineNumber,
+ String methodReturnType,
+ String methodName,
+ String methodArguments,
+ String newClassName,
+ int newFirstLineNumber,
+ int newLastLineNumber,
+ String newMethodName);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingReader.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingReader.java
new file mode 100644
index 0000000000..bb672bf9b5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MappingReader.java
@@ -0,0 +1,238 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import java.io.*;
+
+
+/**
+ * This class can parse mapping files and invoke a processor for each of the
+ * mapping entries.
+ *
+ * @author Eric Lafortune
+ */
+public class MappingReader
+{
+ private final File mappingFile;
+
+
+ public MappingReader(File mappingFile)
+ {
+ this.mappingFile = mappingFile;
+ }
+
+
+ /**
+ * Reads the mapping file, presenting all of the encountered mapping entries
+ * to the given processor.
+ */
+ public void pump(MappingProcessor mappingProcessor) throws IOException
+ {
+ LineNumberReader reader = new LineNumberReader(
+ new BufferedReader(
+ new FileReader(mappingFile)));
+ try
+ {
+ String className = null;
+
+ // Read the subsequent class mappings and class member mappings.
+ while (true)
+ {
+ String line = reader.readLine();
+
+ if (line == null)
+ {
+ break;
+ }
+
+ line = line.trim();
+
+ // Is it a non-comment line?
+ if (!line.startsWith("#"))
+ {
+ // Is it a class mapping or a class member mapping?
+ if (line.endsWith(":"))
+ {
+ // Process the class mapping and remember the class's
+ // old name.
+ className = processClassMapping(line, mappingProcessor);
+ }
+ else if (className != null)
+ {
+ // Process the class member mapping, in the context of
+ // the current old class name.
+ processClassMemberMapping(className, line, mappingProcessor);
+ }
+ }
+ }
+ }
+ catch (IOException ex)
+ {
+ throw new IOException("Can't process mapping file (" + ex.getMessage() + ")");
+ }
+ finally
+ {
+ try
+ {
+ reader.close();
+ }
+ catch (IOException ex)
+ {
+ // This shouldn't happen.
+ }
+ }
+ }
+
+
+ /**
+ * Parses the given line with a class mapping and processes the
+ * results with the given mapping processor. Returns the old class name,
+ * or null if any subsequent class member lines can be ignored.
+ */
+ private String processClassMapping(String line,
+ MappingProcessor mappingProcessor)
+ {
+ // See if we can parse "___ -> ___:", containing the original
+ // class name and the new class name.
+
+ int arrowIndex = line.indexOf("->");
+ if (arrowIndex < 0)
+ {
+ return null;
+ }
+
+ int colonIndex = line.indexOf(':', arrowIndex + 2);
+ if (colonIndex < 0)
+ {
+ return null;
+ }
+
+ // Extract the elements.
+ String className = line.substring(0, arrowIndex).trim();
+ String newClassName = line.substring(arrowIndex + 2, colonIndex).trim();
+
+ // Process this class name mapping.
+ boolean interested = mappingProcessor.processClassMapping(className, newClassName);
+
+ return interested ? className : null;
+ }
+
+
+ /**
+ * Parses the given line with a class member mapping and processes the
+ * results with the given mapping processor.
+ */
+ private void processClassMemberMapping(String className,
+ String line,
+ MappingProcessor mappingProcessor)
+ {
+ // See if we can parse one of
+ // ___ ___ -> ___
+ // ___:___:___ ___(___) -> ___
+ // ___:___:___ ___(___):___ -> ___
+ // ___:___:___ ___(___):___:___ -> ___
+ // containing the optional line numbers, the return type, the original
+ // field/method name, optional arguments, the optional original line
+ // numbers, and the new field/method name. The original field/method
+ // name may contain an original class name "___.___".
+
+ int colonIndex1 = line.indexOf(':');
+ int colonIndex2 = colonIndex1 < 0 ? -1 : line.indexOf(':', colonIndex1 + 1);
+ int spaceIndex = line.indexOf(' ', colonIndex2 + 2);
+ int argumentIndex1 = line.indexOf('(', spaceIndex + 1);
+ int argumentIndex2 = argumentIndex1 < 0 ? -1 : line.indexOf(')', argumentIndex1 + 1);
+ int colonIndex3 = argumentIndex2 < 0 ? -1 : line.indexOf(':', argumentIndex2 + 1);
+ int colonIndex4 = colonIndex3 < 0 ? -1 : line.indexOf(':', colonIndex3 + 1);
+ int arrowIndex = line.indexOf("->", (colonIndex4 >= 0 ? colonIndex4 :
+ colonIndex3 >= 0 ? colonIndex3 :
+ argumentIndex2 >= 0 ? argumentIndex2 :
+ spaceIndex) + 1);
+
+ if (spaceIndex < 0 ||
+ arrowIndex < 0)
+ {
+ return;
+ }
+
+ // Extract the elements.
+ String type = line.substring(colonIndex2 + 1, spaceIndex).trim();
+ String name = line.substring(spaceIndex + 1, argumentIndex1 >= 0 ? argumentIndex1 : arrowIndex).trim();
+ String newName = line.substring(arrowIndex + 2).trim();
+
+ // Does the method name contain an explicit original class name?
+ String newClassName = className;
+ int dotIndex = name.lastIndexOf('.');
+ if (dotIndex >= 0)
+ {
+ className = name.substring(0, dotIndex);
+ name = name.substring(dotIndex + 1);
+ }
+
+ // Process this class member mapping.
+ if (type.length() > 0 &&
+ name.length() > 0 &&
+ newName.length() > 0)
+ {
+ // Is it a field or a method?
+ if (argumentIndex2 < 0)
+ {
+ mappingProcessor.processFieldMapping(className,
+ type,
+ name,
+ newClassName,
+ newName);
+ }
+ else
+ {
+ int firstLineNumber = 0;
+ int lastLineNumber = 0;
+ int newFirstLineNumber = 0;
+ int newLastLineNumber = 0;
+
+ if (colonIndex2 >= 0)
+ {
+ firstLineNumber = newFirstLineNumber = Integer.parseInt(line.substring(0, colonIndex1).trim());
+ lastLineNumber = newLastLineNumber = Integer.parseInt(line.substring(colonIndex1 + 1, colonIndex2).trim());
+ }
+
+ if (colonIndex3 >= 0)
+ {
+ firstLineNumber = Integer.parseInt(line.substring(colonIndex3 + 1, colonIndex4 > 0 ? colonIndex4 : arrowIndex).trim());
+ lastLineNumber = colonIndex4 < 0 ? firstLineNumber :
+ Integer.parseInt(line.substring(colonIndex4 + 1, arrowIndex).trim());
+ }
+
+ String arguments = line.substring(argumentIndex1 + 1, argumentIndex2).trim();
+
+ mappingProcessor.processMethodMapping(className,
+ firstLineNumber,
+ lastLineNumber,
+ type,
+ name,
+ arguments,
+ newClassName,
+ newFirstLineNumber,
+ newLastLineNumber,
+ newName);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameCleaner.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameCleaner.java
new file mode 100644
index 0000000000..f069100e7c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameCleaner.java
@@ -0,0 +1,60 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This <code>MemberVisitor</code> clears the new names of the class members
+ * that it visits.
+ *
+ * @see MemberObfuscator
+ *
+ * @author Eric Lafortune
+ */
+public class MemberNameCleaner implements MemberVisitor
+{
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ MemberObfuscator.setNewMemberName(programField, null);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ MemberObfuscator.setNewMemberName(programMethod, null);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ MemberObfuscator.setNewMemberName(libraryField, null);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ MemberObfuscator.setNewMemberName(libraryMethod, null);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameCollector.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameCollector.java
new file mode 100644
index 0000000000..fcb62772c1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameCollector.java
@@ -0,0 +1,105 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+import java.util.Map;
+
+/**
+ * This MemberVisitor collects all new (obfuscation) names of the members
+ * that it visits.
+ *
+ * @see MemberObfuscator
+ *
+ * @author Eric Lafortune
+ */
+public class MemberNameCollector
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final boolean allowAggressiveOverloading;
+ private final Map descriptorMap;
+
+
+ /**
+ * Creates a new MemberNameCollector.
+ * @param allowAggressiveOverloading a flag that specifies whether class
+ * members can be overloaded aggressively.
+ * @param descriptorMap the map of descriptors to
+ * [new name - old name] maps.
+ */
+ public MemberNameCollector(boolean allowAggressiveOverloading,
+ Map descriptorMap)
+ {
+ this.allowAggressiveOverloading = allowAggressiveOverloading;
+ this.descriptorMap = descriptorMap;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ // Special cases: <clinit> and <init> are always kept unchanged.
+ // We can ignore them here.
+ String name = member.getName(clazz);
+ if (ClassUtil.isInitializer(name))
+ {
+ return;
+ }
+
+ // Get the member's new name.
+ String newName = MemberObfuscator.newMemberName(member);
+
+ // Remember it, if it has already been set.
+ if (newName != null)
+ {
+ // Get the member's descriptor.
+ String descriptor = member.getDescriptor(clazz);
+
+ // Check whether we're allowed to do aggressive overloading
+ if (!allowAggressiveOverloading)
+ {
+ // Trim the return argument from the descriptor if not.
+ // Works for fields and methods alike.
+ descriptor = descriptor.substring(0, descriptor.indexOf(')')+1);
+ }
+
+ // Put the [descriptor - new name] in the map,
+ // creating a new [new name - old name] map if necessary.
+ Map nameMap = MemberObfuscator.retrieveNameMap(descriptorMap, descriptor);
+
+ // Isn't there another original name for this new name, or should
+ // this original name get priority?
+ String otherName = (String)nameMap.get(newName);
+ if (otherName == null ||
+ MemberObfuscator.hasFixedNewMemberName(member) ||
+ name.compareTo(otherName) < 0)
+ {
+ // Remember not to use the new name again in this name space.
+ nameMap.put(newName, name);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameConflictFixer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameConflictFixer.java
new file mode 100644
index 0000000000..44a43cb01a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameConflictFixer.java
@@ -0,0 +1,158 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+import java.util.Map;
+
+/**
+ * This MemberInfoVisitor solves obfuscation naming conflicts in all class
+ * members that it visits. It avoids names from the given descriptor map,
+ * delegating to the given obfuscator in order to get a new name if necessary.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberNameConflictFixer implements MemberVisitor
+{
+ private final boolean allowAggressiveOverloading;
+ private final Map descriptorMap;
+ private final WarningPrinter warningPrinter;
+ private final MemberObfuscator memberObfuscator;
+
+
+ /**
+ * Creates a new MemberNameConflictFixer.
+ * @param allowAggressiveOverloading a flag that specifies whether class
+ * members can be overloaded aggressively.
+ * @param descriptorMap the map of descriptors to
+ * [new name - old name] maps.
+ * @param warningPrinter an optional warning printer to which
+ * warnings about conflicting name
+ * mappings can be printed.
+ * @param memberObfuscator the obfuscator that can assign new
+ * names to members with conflicting
+ * names.
+ */
+ public MemberNameConflictFixer(boolean allowAggressiveOverloading,
+ Map descriptorMap,
+ WarningPrinter warningPrinter,
+ MemberObfuscator memberObfuscator)
+ {
+ this.allowAggressiveOverloading = allowAggressiveOverloading;
+ this.descriptorMap = descriptorMap;
+ this.warningPrinter = warningPrinter;
+ this.memberObfuscator = memberObfuscator;
+ }
+
+
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ visitMember(programClass, programField, true);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Special cases: <clinit> and <init> are always kept unchanged.
+ // We can ignore them here.
+ String name = programMethod.getName(programClass);
+ if (ClassUtil.isInitializer(name))
+ {
+ return;
+ }
+
+ visitMember(programClass, programMethod, false);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) {}
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) {}
+
+
+ /**
+ * Obfuscates the given class member.
+ * @param clazz the class of the given member.
+ * @param member the class member to be obfuscated.
+ * @param isField specifies whether the class member is a field.
+ */
+ private void visitMember(Clazz clazz,
+ Member member,
+ boolean isField)
+ {
+ // Get the member's name and descriptor.
+ String name = member.getName(clazz);
+ String descriptor = member.getDescriptor(clazz);
+
+ // Check whether we're allowed to overload aggressively.
+ if (!allowAggressiveOverloading)
+ {
+ // Trim the return argument from the descriptor if not.
+ // Works for fields and methods alike.
+ descriptor = descriptor.substring(0, descriptor.indexOf(')')+1);
+ }
+
+ // Get the name map.
+ Map nameMap = MemberObfuscator.retrieveNameMap(descriptorMap, descriptor);
+
+ // Get the member's new name.
+ String newName = MemberObfuscator.newMemberName(member);
+
+ // Get the expected old name for this new name.
+ String previousName = (String)nameMap.get(newName);
+ if (previousName != null &&
+ !name.equals(previousName))
+ {
+ // There's a conflict! A member (with a given old name) in a
+ // first namespace has received the same new name as this
+ // member (with a different old name) in a second name space,
+ // and now these two have to live together in this name space.
+ if (MemberObfuscator.hasFixedNewMemberName(member) &&
+ warningPrinter != null)
+ {
+ descriptor = member.getDescriptor(clazz);
+ warningPrinter.print(clazz.getName(),
+ "Warning: " + ClassUtil.externalClassName(clazz.getName()) +
+ (isField ?
+ ": field '" + ClassUtil.externalFullFieldDescription(0, name, descriptor) :
+ ": method '" + ClassUtil.externalFullMethodDescription(clazz.getName(), 0, name, descriptor)) +
+ "' can't be mapped to '" + newName +
+ "' because it would conflict with " +
+ (isField ?
+ "field '" :
+ "method '" ) + previousName +
+ "', which is already being mapped to '" + newName + "'");
+ }
+
+ // Clear the conflicting name.
+ MemberObfuscator.setNewMemberName(member, null);
+
+ // Assign a new name.
+ member.accept(clazz, memberObfuscator);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameFilter.java
new file mode 100644
index 0000000000..a7791b9462
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberNameFilter.java
@@ -0,0 +1,120 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to another given
+ * <code>MemberVisitor</code>, but only when the visited member has a new name.
+ * Constructors are judged based on the class name.
+ *
+ * @see ClassObfuscator
+ * @see MemberObfuscator
+ *
+ * @author Eric Lafortune
+ */
+public class MemberNameFilter implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new MemberNameFilter.
+ * @param memberVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public MemberNameFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (hasName(programField))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (hasName(programClass, programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (hasName(libraryField))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (hasName(libraryClass, libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the given class has a new name.
+ */
+ private boolean hasName(Clazz clazz)
+ {
+ return ClassObfuscator.newClassName(clazz) != null;
+ }
+
+
+ /**
+ * Returns whether the given method has a new name.
+ */
+ private boolean hasName(Clazz clazz, Method method)
+ {
+ return
+ hasName(method) ||
+ (hasName(clazz) &&
+ method.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT));
+ }
+
+
+ /**
+ * Returns whether the given class member has a new name.
+ */
+ private boolean hasName(Member member)
+ {
+ return MemberObfuscator.newMemberName(member) != null;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberObfuscator.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberObfuscator.java
new file mode 100644
index 0000000000..792e794044
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberObfuscator.java
@@ -0,0 +1,229 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+import java.util.*;
+
+/**
+ * This MemberVisitor obfuscates all class members that it visits.
+ * It uses names from the given name factory. At the same time, it avoids names
+ * from the given descriptor map.
+ * <p>
+ * The class members must have been linked before applying this visitor.
+ *
+ * @see MethodLinker
+ *
+ * @author Eric Lafortune
+ */
+public class MemberObfuscator
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final boolean allowAggressiveOverloading;
+ private final NameFactory nameFactory;
+ private final Map descriptorMap;
+
+
+ /**
+ * Creates a new MemberObfuscator.
+ * @param allowAggressiveOverloading a flag that specifies whether class
+ * members can be overloaded aggressively.
+ * @param nameFactory the factory that can produce
+ * obfuscated member names.
+ * @param descriptorMap the map of descriptors to
+ * [new name - old name] maps.
+ */
+ public MemberObfuscator(boolean allowAggressiveOverloading,
+ NameFactory nameFactory,
+ Map descriptorMap)
+ {
+ this.allowAggressiveOverloading = allowAggressiveOverloading;
+ this.nameFactory = nameFactory;
+ this.descriptorMap = descriptorMap;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ // Special cases: <clinit> and <init> are always kept unchanged.
+ // We can ignore them here.
+ String name = member.getName(clazz);
+ if (ClassUtil.isInitializer(name))
+ {
+ return;
+ }
+
+ // Get the member's descriptor.
+ String descriptor = member.getDescriptor(clazz);
+
+ // Check whether we're allowed to overload aggressively.
+ if (!allowAggressiveOverloading)
+ {
+ // Trim the return argument from the descriptor if not.
+ // Works for fields and methods alike.
+ descriptor = descriptor.substring(0, descriptor.indexOf(')')+1);
+ }
+
+ // Get the name map, creating a new one if necessary.
+ Map nameMap = retrieveNameMap(descriptorMap, descriptor);
+
+ // Get the member's new name.
+ String newName = newMemberName(member);
+
+ // Assign a new one, if necessary.
+ if (newName == null)
+ {
+ // Find an acceptable new name.
+ nameFactory.reset();
+
+ do
+ {
+ newName = nameFactory.nextName();
+ }
+ while (nameMap.containsKey(newName));
+
+ // Remember not to use the new name again in this name space.
+ nameMap.put(newName, name);
+
+ // Assign the new name.
+ setNewMemberName(member, newName);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Gets the name map, based on the given map and a given descriptor.
+ * A new empty map is created if necessary.
+ * @param descriptorMap the map of descriptors to [new name - old name] maps.
+ * @param descriptor the class member descriptor.
+ * @return the corresponding name map.
+ */
+ static Map retrieveNameMap(Map descriptorMap, String descriptor)
+ {
+ // See if we can find the nested map with this descriptor key.
+ Map nameMap = (Map)descriptorMap.get(descriptor);
+
+ // Create a new one if not.
+ if (nameMap == null)
+ {
+ nameMap = new HashMap();
+ descriptorMap.put(descriptor, nameMap);
+ }
+
+ return nameMap;
+ }
+
+
+ /**
+ * Assigns a fixed new name to the given class member.
+ * @param member the class member.
+ * @param name the new name.
+ */
+ static void setFixedNewMemberName(Member member, String name)
+ {
+ VisitorAccepter lastVisitorAccepter = MethodLinker.lastVisitorAccepter(member);
+
+ if (!(lastVisitorAccepter instanceof LibraryMember) &&
+ !(lastVisitorAccepter instanceof MyFixedName))
+ {
+ lastVisitorAccepter.setVisitorInfo(new MyFixedName(name));
+ }
+ else
+ {
+ lastVisitorAccepter.setVisitorInfo(name);
+ }
+ }
+
+
+ /**
+ * Assigns a new name to the given class member.
+ * @param member the class member.
+ * @param name the new name.
+ */
+ static void setNewMemberName(Member member, String name)
+ {
+ MethodLinker.lastVisitorAccepter(member).setVisitorInfo(name);
+ }
+
+
+ /**
+ * Returns whether the new name of the given class member is fixed.
+ * @param member the class member.
+ * @return whether its new name is fixed.
+ */
+ static boolean hasFixedNewMemberName(Member member)
+ {
+ VisitorAccepter lastVisitorAccepter = MethodLinker.lastVisitorAccepter(member);
+
+ return lastVisitorAccepter instanceof LibraryMember ||
+ lastVisitorAccepter instanceof MyFixedName;
+ }
+
+
+ /**
+ * Retrieves the new name of the given class member.
+ * @param member the class member.
+ * @return the class member's new name, or <code>null</code> if it doesn't
+ * have one yet.
+ */
+ static String newMemberName(Member member)
+ {
+ return (String)MethodLinker.lastVisitorAccepter(member).getVisitorInfo();
+ }
+
+
+ /**
+ * This VisitorAccepter can be used to wrap a name string, to indicate that
+ * the name is fixed.
+ */
+ private static class MyFixedName implements VisitorAccepter
+ {
+ private String newName;
+
+
+ public MyFixedName(String newName)
+ {
+ this.newName = newName;
+ }
+
+
+ // Implementations for VisitorAccepter.
+
+ public Object getVisitorInfo()
+ {
+ return newName;
+ }
+
+
+ public void setVisitorInfo(Object visitorInfo)
+ {
+ newName = (String)visitorInfo;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberSpecialNameFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberSpecialNameFilter.java
new file mode 100644
index 0000000000..99949e64d5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MemberSpecialNameFilter.java
@@ -0,0 +1,101 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to another given
+ * <code>MemberVisitor</code>, but only when the visited member has a
+ * special new name. A special name is a name that might have been produced by
+ * a <code>SpecialNameFactory</code>.
+ *
+ * @see MemberObfuscator
+ * @see SpecialNameFactory
+ *
+ * @author Eric Lafortune
+ */
+public class MemberSpecialNameFilter implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new MemberSpecialNameFilter.
+ * @param memberVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public MemberSpecialNameFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (hasSpecialName(programField))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (hasSpecialName(programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (hasSpecialName(libraryField))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (hasSpecialName(libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the given class member has a special new name.
+ * @param member the class member.
+ */
+ private static boolean hasSpecialName(Member member)
+ {
+ return SpecialNameFactory.isSpecialName(MemberObfuscator.newMemberName(member));
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MultiMappingProcessor.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MultiMappingProcessor.java
new file mode 100644
index 0000000000..0c18ade6e5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/MultiMappingProcessor.java
@@ -0,0 +1,105 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+/**
+ * This MappingKeeper delegates all method calls to each MappingProcessor
+ * in a given list.
+ *
+ * @author Eric Lafortune
+ */
+public class MultiMappingProcessor
+implements MappingProcessor
+{
+ private final MappingProcessor[] mappingProcessors;
+
+
+ /**
+ * Creates a new MultiMappingProcessor.
+ * @param mappingProcessors the mapping processors to which method calls
+ * will be delegated.
+ */
+ public MultiMappingProcessor(MappingProcessor[] mappingProcessors)
+ {
+ this.mappingProcessors = mappingProcessors;
+ }
+
+
+ // Implementations for MappingProcessor.
+
+ public boolean processClassMapping(String className,
+ String newClassName)
+ {
+ boolean result = false;
+
+ for (int index = 0; index < mappingProcessors.length; index++)
+ {
+ result |= mappingProcessors[index].processClassMapping(className,
+ newClassName);
+ }
+
+ return result;
+ }
+
+
+ public void processFieldMapping(String className,
+ String fieldType,
+ String fieldName,
+ String newClassName,
+ String newFieldName)
+ {
+ for (int index = 0; index < mappingProcessors.length; index++)
+ {
+ mappingProcessors[index].processFieldMapping(className,
+ fieldType,
+ fieldName,
+ newClassName,
+ newFieldName);
+ }
+ }
+
+
+ public void processMethodMapping(String className,
+ int firstLineNumber,
+ int lastLineNumber,
+ String methodReturnType,
+ String methodName,
+ String methodArguments,
+ String newClassName,
+ int newFirstLineNumber,
+ int newLastLineNumber,
+ String newMethodName)
+ {
+ for (int index = 0; index < mappingProcessors.length; index++)
+ {
+ mappingProcessors[index].processMethodMapping(className,
+ firstLineNumber,
+ lastLineNumber,
+ methodReturnType,
+ methodName,
+ methodArguments,
+ newClassName,
+ newFirstLineNumber,
+ newLastLineNumber,
+ newMethodName);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameFactory.java
new file mode 100644
index 0000000000..dd5e459d25
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameFactory.java
@@ -0,0 +1,34 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+/**
+ * This interfaces provides methods to generate unique sequences of names.
+ * The names must be valid Java identifiers.
+ *
+ * @author Eric Lafortune
+ */
+public interface NameFactory
+{
+ public void reset();
+
+ public String nextName();
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameFactoryResetter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameFactoryResetter.java
new file mode 100644
index 0000000000..96a92bf7d2
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameFactoryResetter.java
@@ -0,0 +1,59 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor resets a given name factory whenever it visits a class
+ * file.
+ *
+ * @author Eric Lafortune
+ */
+public class NameFactoryResetter implements ClassVisitor
+{
+ private final NameFactory nameFactory;
+
+
+ /**
+ * Creates a new NameFactoryResetter.
+ * @param nameFactory the name factory to be reset.
+ */
+ public NameFactoryResetter(NameFactory nameFactory)
+ {
+ this.nameFactory = nameFactory;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ nameFactory.reset();
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ nameFactory.reset();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameMarker.java
new file mode 100644
index 0000000000..6afe300efc
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NameMarker.java
@@ -0,0 +1,164 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+
+/**
+ * This <code>ClassVisitor</code> and <code>MemberVisitor</code>
+ * marks names of the classes and class members it visits. The marked names
+ * will remain unchanged in the obfuscation step.
+ *
+ * @see ClassObfuscator
+ * @see MemberObfuscator
+ *
+ * @author Eric Lafortune
+ */
+class NameMarker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor,
+ InnerClassesInfoVisitor,
+ ConstantVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ keepClassName(programClass);
+
+ // Make sure any outer class names are kept as well.
+ programClass.attributesAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ keepClassName(libraryClass);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ keepFieldName(programClass, programField);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ keepMethodName(programClass, programMethod);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ keepFieldName(libraryClass, libraryField);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ keepMethodName(libraryClass, libraryMethod);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ // Make sure the outer class names are kept as well.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ // Make sure the outer class name is kept as well.
+ int innerClassIndex = innerClassesInfo.u2innerClassIndex;
+ int outerClassIndex = innerClassesInfo.u2outerClassIndex;
+ if (innerClassIndex != 0 &&
+ outerClassIndex != 0 &&
+ clazz.getClassName(innerClassIndex).equals(clazz.getName()))
+ {
+ clazz.constantPoolEntryAccept(outerClassIndex, this);
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Make sure the outer class name is kept as well.
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Small utility method.
+
+ /**
+ * Ensures the name of the given class name will be kept.
+ */
+ public void keepClassName(Clazz clazz)
+ {
+ ClassObfuscator.setNewClassName(clazz,
+ clazz.getName());
+ }
+
+
+ /**
+ * Ensures the name of the given field name will be kept.
+ */
+ private void keepFieldName(Clazz clazz, Field field)
+ {
+ MemberObfuscator.setFixedNewMemberName(field,
+ field.getName(clazz));
+ }
+
+
+ /**
+ * Ensures the name of the given method name will be kept.
+ */
+ private void keepMethodName(Clazz clazz, Method method)
+ {
+ String name = method.getName(clazz);
+
+ if (!ClassUtil.isInitializer(name))
+ {
+ MemberObfuscator.setFixedNewMemberName(method, name);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NumericNameFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NumericNameFactory.java
new file mode 100644
index 0000000000..d6609d3c48
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/NumericNameFactory.java
@@ -0,0 +1,46 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+/**
+ * This <code>NameFactory</code> generates unique numeric names, starting at
+ * "1".
+ *
+ * @author Eric Lafortune
+ */
+public class NumericNameFactory implements NameFactory
+{
+ private int index;
+
+
+ // Implementations for NameFactory.
+
+ public void reset()
+ {
+ index = 0;
+ }
+
+
+ public String nextName()
+ {
+ return Integer.toString(++index);
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/Obfuscator.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/Obfuscator.java
new file mode 100644
index 0000000000..4b1f561612
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/Obfuscator.java
@@ -0,0 +1,476 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.*;
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.visitor.AllConstantVisitor;
+import proguard.classfile.editor.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.util.*;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class can perform obfuscation of class pools according to a given
+ * specification.
+ *
+ * @author Eric Lafortune
+ */
+public class Obfuscator
+{
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new Obfuscator.
+ */
+ public Obfuscator(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Performs obfuscation of the given program class pool.
+ */
+ public void execute(ClassPool programClassPool,
+ ClassPool libraryClassPool) throws IOException
+ {
+ // Check if we have at least some keep commands.
+ if (configuration.keep == null &&
+ configuration.applyMapping == null &&
+ configuration.printMapping == null)
+ {
+ throw new IOException("You have to specify '-keep' options for the obfuscation step.");
+ }
+
+ // Clean up any old visitor info.
+ programClassPool.classesAccept(new ClassCleaner());
+ libraryClassPool.classesAccept(new ClassCleaner());
+
+ // If the class member names have to correspond globally,
+ // link all class members in all classes, otherwise
+ // link all non-private methods in all class hierarchies.
+ ClassVisitor memberInfoLinker =
+ configuration.useUniqueClassMemberNames ?
+ (ClassVisitor)new AllMemberVisitor(new MethodLinker()) :
+ (ClassVisitor)new BottomClassFilter(new MethodLinker());
+
+ programClassPool.classesAccept(memberInfoLinker);
+ libraryClassPool.classesAccept(memberInfoLinker);
+
+ // Create a visitor for marking the seeds.
+ NameMarker nameMarker = new NameMarker();
+ ClassPoolVisitor classPoolvisitor =
+ ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep,
+ nameMarker,
+ nameMarker,
+ false,
+ false,
+ true);
+ // Mark the seeds.
+ programClassPool.accept(classPoolvisitor);
+ libraryClassPool.accept(classPoolvisitor);
+
+ // All library classes and library class members keep their names.
+ libraryClassPool.classesAccept(nameMarker);
+ libraryClassPool.classesAccept(new AllMemberVisitor(nameMarker));
+
+ // We also keep the names of all methods of classes that are returned
+ // by dynamic method invocations. They may return dynamic
+ // implementations of interfaces. The method names then have to match
+ // with the invoke dynamic names.
+ programClassPool.classesAccept(
+ new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_7,
+ new AllConstantVisitor(
+ new DynamicReturnedClassVisitor(
+ new AllMemberVisitor(nameMarker)))));
+
+ // Mark attributes that have to be kept.
+ AttributeVisitor attributeUsageMarker =
+ new NonEmptyAttributeFilter(
+ new AttributeUsageMarker());
+
+ AttributeVisitor optionalAttributeUsageMarker =
+ configuration.keepAttributes == null ? null :
+ new AttributeNameFilter(configuration.keepAttributes,
+ attributeUsageMarker);
+
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(true,
+ new RequiredAttributeFilter(attributeUsageMarker,
+ optionalAttributeUsageMarker)));
+
+ // Keep parameter names and types if specified.
+ if (configuration.keepParameterNames)
+ {
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new MemberNameFilter(
+ new AllAttributeVisitor(true,
+ new ParameterNameMarker(attributeUsageMarker)))));
+ }
+
+ // Remove the attributes that can be discarded. Note that the attributes
+ // may only be discarded after the seeds have been marked, since the
+ // configuration may rely on annotations.
+ programClassPool.classesAccept(new AttributeShrinker());
+
+ // Apply the mapping, if one has been specified. The mapping can
+ // override the names of library classes and of library class members.
+ if (configuration.applyMapping != null)
+ {
+ WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn);
+
+ MappingReader reader = new MappingReader(configuration.applyMapping);
+
+ MappingProcessor keeper =
+ new MultiMappingProcessor(new MappingProcessor[]
+ {
+ new MappingKeeper(programClassPool, warningPrinter),
+ new MappingKeeper(libraryClassPool, null),
+ });
+
+ reader.pump(keeper);
+
+ // Print out a summary of the warnings if necessary.
+ int warningCount = warningPrinter.getWarningCount();
+ if (warningCount > 0)
+ {
+ System.err.println("Warning: there were " + warningCount +
+ " kept classes and class members that were remapped anyway.");
+ System.err.println(" You should adapt your configuration or edit the mapping file.");
+
+ if (!configuration.ignoreWarnings)
+ {
+ System.err.println(" If you are sure this remapping won't hurt, you could try your luck");
+ System.err.println(" using the '-ignorewarnings' option.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#mappingconflict1)");
+
+ if (!configuration.ignoreWarnings)
+ {
+ throw new IOException("Please correct the above warnings first.");
+ }
+ }
+ }
+
+ // Come up with new names for all classes.
+ DictionaryNameFactory classNameFactory = configuration.classObfuscationDictionary != null ?
+ new DictionaryNameFactory(configuration.classObfuscationDictionary, null) :
+ null;
+
+ DictionaryNameFactory packageNameFactory = configuration.packageObfuscationDictionary != null ?
+ new DictionaryNameFactory(configuration.packageObfuscationDictionary, null) :
+ null;
+
+ programClassPool.classesAccept(
+ new ClassObfuscator(programClassPool,
+ libraryClassPool,
+ classNameFactory,
+ packageNameFactory,
+ configuration.useMixedCaseClassNames,
+ configuration.keepPackageNames,
+ configuration.flattenPackageHierarchy,
+ configuration.repackageClasses,
+ configuration.allowAccessModification));
+
+ // Come up with new names for all class members.
+ NameFactory nameFactory = new SimpleNameFactory();
+
+ if (configuration.obfuscationDictionary != null)
+ {
+ nameFactory = new DictionaryNameFactory(configuration.obfuscationDictionary,
+ nameFactory);
+ }
+
+ WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn);
+
+ // Maintain a map of names to avoid [descriptor - new name - old name].
+ Map descriptorMap = new HashMap();
+
+ // Do the class member names have to be globally unique?
+ if (configuration.useUniqueClassMemberNames)
+ {
+ // Collect all member names in all classes.
+ programClassPool.classesAccept(
+ new AllMemberVisitor(
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap)));
+
+ // Assign new names to all members in all classes.
+ programClassPool.classesAccept(
+ new AllMemberVisitor(
+ new MemberObfuscator(configuration.overloadAggressively,
+ nameFactory,
+ descriptorMap)));
+ }
+ else
+ {
+ // Come up with new names for all non-private class members.
+ programClassPool.classesAccept(
+ new MultiClassVisitor(new ClassVisitor[]
+ {
+ // Collect all private member names in this class and down
+ // the hierarchy.
+ new ClassHierarchyTraveler(true, false, false, true,
+ new AllMemberVisitor(
+ new MemberAccessFilter(ClassConstants.ACC_PRIVATE, 0,
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap)))),
+
+ // Collect all non-private member names anywhere in the hierarchy.
+ new ClassHierarchyTraveler(true, true, true, true,
+ new AllMemberVisitor(
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE,
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap)))),
+
+ // Assign new names to all non-private members in this class.
+ new AllMemberVisitor(
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE,
+ new MemberObfuscator(configuration.overloadAggressively,
+ nameFactory,
+ descriptorMap))),
+
+ // Clear the collected names.
+ new MapCleaner(descriptorMap)
+ }));
+
+ // Come up with new names for all private class members.
+ programClassPool.classesAccept(
+ new MultiClassVisitor(new ClassVisitor[]
+ {
+ // Collect all member names in this class.
+ new AllMemberVisitor(
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap)),
+
+ // Collect all non-private member names higher up the hierarchy.
+ new ClassHierarchyTraveler(false, true, true, false,
+ new AllMemberVisitor(
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE,
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap)))),
+
+ // Collect all member names from interfaces of abstract
+ // classes down the hierarchy.
+ // Due to an error in the JLS/JVMS, virtual invocations
+ // may end up at a private method otherwise (Sun/Oracle
+ // bugs #6691741 and #6684387, ProGuard bug #3471941,
+ // and ProGuard test #1180).
+ new ClassHierarchyTraveler(false, false, false, true,
+ new ClassAccessFilter(ClassConstants.ACC_ABSTRACT, 0,
+ new ClassHierarchyTraveler(false, false, true, false,
+ new AllMemberVisitor(
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap))))),
+
+ // Assign new names to all private members in this class.
+ new AllMemberVisitor(
+ new MemberAccessFilter(ClassConstants.ACC_PRIVATE, 0,
+ new MemberObfuscator(configuration.overloadAggressively,
+ nameFactory,
+ descriptorMap))),
+
+ // Clear the collected names.
+ new MapCleaner(descriptorMap)
+ }));
+ }
+
+ // Some class members may have ended up with conflicting names.
+ // Come up with new, globally unique names for them.
+ NameFactory specialNameFactory =
+ new SpecialNameFactory(new SimpleNameFactory());
+
+ // Collect a map of special names to avoid
+ // [descriptor - new name - old name].
+ Map specialDescriptorMap = new HashMap();
+
+ programClassPool.classesAccept(
+ new AllMemberVisitor(
+ new MemberSpecialNameFilter(
+ new MemberNameCollector(configuration.overloadAggressively,
+ specialDescriptorMap))));
+
+ libraryClassPool.classesAccept(
+ new AllMemberVisitor(
+ new MemberSpecialNameFilter(
+ new MemberNameCollector(configuration.overloadAggressively,
+ specialDescriptorMap))));
+
+ // Replace conflicting non-private member names with special names.
+ programClassPool.classesAccept(
+ new MultiClassVisitor(new ClassVisitor[]
+ {
+ // Collect all private member names in this class and down
+ // the hierarchy.
+ new ClassHierarchyTraveler(true, false, false, true,
+ new AllMemberVisitor(
+ new MemberAccessFilter(ClassConstants.ACC_PRIVATE, 0,
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap)))),
+
+ // Collect all non-private member names in this class and
+ // higher up the hierarchy.
+ new ClassHierarchyTraveler(true, true, true, false,
+ new AllMemberVisitor(
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE,
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap)))),
+
+ // Assign new names to all conflicting non-private members
+ // in this class and higher up the hierarchy.
+ new ClassHierarchyTraveler(true, true, true, false,
+ new AllMemberVisitor(
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE,
+ new MemberNameConflictFixer(configuration.overloadAggressively,
+ descriptorMap,
+ warningPrinter,
+ new MemberObfuscator(configuration.overloadAggressively,
+ specialNameFactory,
+ specialDescriptorMap))))),
+
+ // Clear the collected names.
+ new MapCleaner(descriptorMap)
+ }));
+
+ // Replace conflicting private member names with special names.
+ // This is only possible if those names were kept or mapped.
+ programClassPool.classesAccept(
+ new MultiClassVisitor(new ClassVisitor[]
+ {
+ // Collect all member names in this class.
+ new AllMemberVisitor(
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap)),
+
+ // Collect all non-private member names higher up the hierarchy.
+ new ClassHierarchyTraveler(false, true, true, false,
+ new AllMemberVisitor(
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE,
+ new MemberNameCollector(configuration.overloadAggressively,
+ descriptorMap)))),
+
+ // Assign new names to all conflicting private members in this
+ // class.
+ new AllMemberVisitor(
+ new MemberAccessFilter(ClassConstants.ACC_PRIVATE, 0,
+ new MemberNameConflictFixer(configuration.overloadAggressively,
+ descriptorMap,
+ warningPrinter,
+ new MemberObfuscator(configuration.overloadAggressively,
+ specialNameFactory,
+ specialDescriptorMap)))),
+
+ // Clear the collected names.
+ new MapCleaner(descriptorMap)
+ }));
+
+ // Print out any warnings about member name conflicts.
+ int warningCount = warningPrinter.getWarningCount();
+ if (warningCount > 0)
+ {
+ System.err.println("Warning: there were " + warningCount +
+ " conflicting class member name mappings.");
+ System.err.println(" Your configuration may be inconsistent.");
+
+ if (!configuration.ignoreWarnings)
+ {
+ System.err.println(" If you are sure the conflicts are harmless,");
+ System.err.println(" you could try your luck using the '-ignorewarnings' option.");
+ }
+
+ System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#mappingconflict2)");
+
+ if (!configuration.ignoreWarnings)
+ {
+ throw new IOException("Please correct the above warnings first.");
+ }
+ }
+
+ // Print out the mapping, if requested.
+ if (configuration.printMapping != null)
+ {
+ PrintStream ps =
+ configuration.printMapping == Configuration.STD_OUT ? System.out :
+ new PrintStream(
+ new BufferedOutputStream(
+ new FileOutputStream(configuration.printMapping)));
+
+ // Print out items that will be removed.
+ programClassPool.classesAcceptAlphabetically(new MappingPrinter(ps));
+
+ if (ps == System.out)
+ {
+ ps.flush();
+ }
+ else
+ {
+ ps.close();
+ }
+ }
+
+ // Actually apply the new names.
+ programClassPool.classesAccept(new ClassRenamer());
+ libraryClassPool.classesAccept(new ClassRenamer());
+
+ // Update all references to these new names.
+ programClassPool.classesAccept(new ClassReferenceFixer(false));
+ libraryClassPool.classesAccept(new ClassReferenceFixer(false));
+ programClassPool.classesAccept(new MemberReferenceFixer());
+
+ // Make package visible elements public or protected, if obfuscated
+ // classes are being repackaged aggressively.
+ if (configuration.repackageClasses != null &&
+ configuration.allowAccessModification)
+ {
+ programClassPool.classesAccept(
+ new AccessFixer());
+
+ // Fix the access flags of the inner classes information.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(
+ new AllInnerClassesInfoVisitor(
+ new InnerClassesAccessFixer())));
+ }
+
+ // Fix the bridge method flags.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new BridgeMethodFixer()));
+
+ // Rename the source file attributes, if requested.
+ if (configuration.newSourceFileAttribute != null)
+ {
+ programClassPool.classesAccept(new SourceFileRenamer(configuration.newSourceFileAttribute));
+ }
+
+ // Remove unused constants.
+ programClassPool.classesAccept(
+ new ConstantPoolShrinker());
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ParameterNameMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ParameterNameMarker.java
new file mode 100644
index 0000000000..6070715d32
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/ParameterNameMarker.java
@@ -0,0 +1,128 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor trims and marks all local variable (type) table
+ * attributes that it visits. It keeps parameter names and types and removes
+ * the ordinary local variable names and types.
+ *
+ * @author Eric Lafortune
+ */
+public class ParameterNameMarker
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final AttributeVisitor attributeUsageMarker;
+
+
+ /**
+ * Constructs a new ParameterNameMarker.
+ * @param attributeUsageMarker the marker that will be used to mark
+ * attributes containing local variable info.
+ */
+ public ParameterNameMarker(AttributeVisitor attributeUsageMarker)
+ {
+ this.attributeUsageMarker = attributeUsageMarker;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ if (!AttributeUsageMarker.isUsed(localVariableTableAttribute) &&
+ hasParameters(clazz, method))
+ {
+ // Shift the entries that start at offset 0 to the front.
+ int newIndex = 0;
+
+ for (int index = 0; index < localVariableTableAttribute.u2localVariableTableLength; index++)
+ {
+ LocalVariableInfo localVariableInfo =
+ localVariableTableAttribute.localVariableTable[index];
+
+ if (localVariableInfo.u2startPC == 0)
+ {
+ localVariableTableAttribute.localVariableTable[newIndex++] =
+ localVariableInfo;
+ }
+ }
+
+ // Trim the table.
+ localVariableTableAttribute.u2localVariableTableLength = newIndex;
+
+ // Mark the table if there are any entries.
+ if (newIndex > 0)
+ {
+ attributeUsageMarker.visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute);
+ }
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ if (!AttributeUsageMarker.isUsed(localVariableTypeTableAttribute) &&
+ hasParameters(clazz, method))
+ {
+ // Shift the entries that start at offset 0 to the front.
+ int newIndex = 0;
+
+ for (int index = 0; index < localVariableTypeTableAttribute.u2localVariableTypeTableLength; index++)
+ {
+ LocalVariableTypeInfo localVariableTypeInfo =
+ localVariableTypeTableAttribute.localVariableTypeTable[index];
+
+ if (localVariableTypeInfo.u2startPC == 0)
+ {
+ localVariableTypeTableAttribute.localVariableTypeTable[newIndex++] =
+ localVariableTypeInfo;
+ }
+ }
+
+ // Trim the table.
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength = newIndex;
+
+ // Mark the table if there are any entries.
+ if (newIndex > 0)
+ {
+ attributeUsageMarker.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute);
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean hasParameters(Clazz clazz, Method method)
+ {
+ return method.getDescriptor(clazz).charAt(1) != ClassConstants.METHOD_ARGUMENTS_CLOSE;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SimpleNameFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SimpleNameFactory.java
new file mode 100644
index 0000000000..1dc9d62e69
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SimpleNameFactory.java
@@ -0,0 +1,156 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import java.util.*;
+
+
+/**
+ * This <code>NameFactory</code> generates unique short names, using mixed-case
+ * characters or lower-case characters only.
+ *
+ * @author Eric Lafortune
+ */
+public class SimpleNameFactory implements NameFactory
+{
+ private static final int CHARACTER_COUNT = 26;
+
+ private static final List cachedMixedCaseNames = new ArrayList();
+ private static final List cachedLowerCaseNames = new ArrayList();
+
+ private final boolean generateMixedCaseNames;
+ private int index = 0;
+
+
+ /**
+ * Creates a new <code>SimpleNameFactory</code> that generates mixed-case names.
+ */
+ public SimpleNameFactory()
+ {
+ this(true);
+ }
+
+
+ /**
+ * Creates a new <code>SimpleNameFactory</code>.
+ * @param generateMixedCaseNames a flag to indicate whether the generated
+ * names will be mixed-case, or lower-case only.
+ */
+ public SimpleNameFactory(boolean generateMixedCaseNames)
+ {
+ this.generateMixedCaseNames = generateMixedCaseNames;
+ }
+
+
+ // Implementations for NameFactory.
+
+ public void reset()
+ {
+ index = 0;
+ }
+
+
+ public String nextName()
+ {
+ return name(index++);
+ }
+
+
+ /**
+ * Returns the name at the given index.
+ */
+ private String name(int index)
+ {
+ // Which cache do we need?
+ List cachedNames = generateMixedCaseNames ?
+ cachedMixedCaseNames :
+ cachedLowerCaseNames;
+
+ // Do we have the name in the cache?
+ if (index < cachedNames.size())
+ {
+ return (String)cachedNames.get(index);
+ }
+
+ // Create a new name and cache it.
+ String name = newName(index);
+ cachedNames.add(index, name);
+
+ return name;
+ }
+
+
+ /**
+ * Creates and returns the name at the given index.
+ */
+ private String newName(int index)
+ {
+ // If we're allowed to generate mixed-case names, we can use twice as
+ // many characters.
+ int totalCharacterCount = generateMixedCaseNames ?
+ 2 * CHARACTER_COUNT :
+ CHARACTER_COUNT;
+
+ int baseIndex = index / totalCharacterCount;
+ int offset = index % totalCharacterCount;
+
+ char newChar = charAt(offset);
+
+ String newName = baseIndex == 0 ?
+ new String(new char[] { newChar }) :
+ (name(baseIndex-1) + newChar);
+
+ return newName;
+ }
+
+
+ /**
+ * Returns the character with the given index, between 0 and the number of
+ * acceptable characters.
+ */
+ private char charAt(int index)
+ {
+ return (char)((index < CHARACTER_COUNT ? 'a' - 0 :
+ 'A' - CHARACTER_COUNT) + index);
+ }
+
+
+ public static void main(String[] args)
+ {
+ System.out.println("Some mixed-case names:");
+ printNameSamples(new SimpleNameFactory(true), 60);
+ System.out.println("Some lower-case names:");
+ printNameSamples(new SimpleNameFactory(false), 60);
+ System.out.println("Some more mixed-case names:");
+ printNameSamples(new SimpleNameFactory(true), 80);
+ System.out.println("Some more lower-case names:");
+ printNameSamples(new SimpleNameFactory(false), 80);
+ }
+
+
+ private static void printNameSamples(SimpleNameFactory factory, int count)
+ {
+ for (int counter = 0; counter < count; counter++)
+ {
+ System.out.println(" ["+factory.nextName()+"]");
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SourceFileRenamer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SourceFileRenamer.java
new file mode 100644
index 0000000000..7e2d8d7003
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SourceFileRenamer.java
@@ -0,0 +1,84 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.ConstantPoolEditor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor changes the name stored in the source file attributes
+ * and source dir attributes of the classes that it visits, if the
+ * attributes are present.
+ *
+ * @author Eric Lafortune
+ */
+public class SourceFileRenamer
+extends SimplifiedVisitor
+implements ClassVisitor,
+ AttributeVisitor
+{
+ private final String newSourceFileAttribute;
+
+
+ /**
+ * Creates a new SourceFileRenamer.
+ * @param newSourceFileAttribute the new string to be put in the source file
+ * attributes.
+ */
+ public SourceFileRenamer(String newSourceFileAttribute)
+ {
+ this.newSourceFileAttribute = newSourceFileAttribute;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Only visit the class attributes.
+ programClass.attributesAccept(this);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ // Fix the source file attribute.
+ sourceFileAttribute.u2sourceFileIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSourceFileAttribute);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ // Fix the source file attribute.
+ sourceDirAttribute.u2sourceDirIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSourceFileAttribute);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SpecialNameFactory.java b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SpecialNameFactory.java
new file mode 100644
index 0000000000..0e7f56be83
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/SpecialNameFactory.java
@@ -0,0 +1,83 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.obfuscate;
+
+/**
+ * This <code>NameFactory</code> generates names that are special, by appending
+ * a suffix.
+ *
+ * @author Eric Lafortune
+ */
+public class SpecialNameFactory implements NameFactory
+{
+ private static final char SPECIAL_SUFFIX = '_';
+
+
+ private final NameFactory nameFactory;
+
+
+ /**
+ * Creates a new <code>SpecialNameFactory</code>.
+ * @param nameFactory the name factory from which original names will be
+ * retrieved.
+ */
+ public SpecialNameFactory(NameFactory nameFactory)
+ {
+ this.nameFactory = nameFactory;
+ }
+
+
+ // Implementations for NameFactory.
+
+ public void reset()
+ {
+ nameFactory.reset();
+ }
+
+
+ public String nextName()
+ {
+ return nameFactory.nextName() + SPECIAL_SUFFIX;
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the given name is special.
+ */
+ static boolean isSpecialName(String name)
+ {
+ return name != null &&
+ name.charAt(name.length()-1) == SPECIAL_SUFFIX;
+ }
+
+
+ public static void main(String[] args)
+ {
+ SpecialNameFactory factory = new SpecialNameFactory(new SimpleNameFactory());
+
+ for (int counter = 0; counter < 50; counter++)
+ {
+ System.out.println("["+factory.nextName()+"]");
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/package.html
new file mode 100644
index 0000000000..a82d26681a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/obfuscate/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains classes to perform obfuscation of class files.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/BootstrapMethodArgumentShrinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/BootstrapMethodArgumentShrinker.java
new file mode 100644
index 0000000000..5507ed9e11
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/BootstrapMethodArgumentShrinker.java
@@ -0,0 +1,104 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.BootstrapMethodInfo;
+import proguard.classfile.attribute.visitor.BootstrapMethodInfoVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.info.*;
+import proguard.optimize.peephole.VariableShrinker;
+
+/**
+ * This BootstrapMethodInfoVisitor removes unused constant arguments from
+ * bootstrap method entries that it visits.
+ *
+ * @see ParameterUsageMarker
+ * @see VariableUsageMarker
+ * @see VariableShrinker
+ * @author Eric Lafortune
+ */
+public class BootstrapMethodArgumentShrinker
+extends SimplifiedVisitor
+implements BootstrapMethodInfoVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ private long usedParameters;
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ // Check which method parameters are used.
+ usedParameters = -1L;
+ clazz.constantPoolEntryAccept(bootstrapMethodInfo.u2methodHandleIndex, this);
+
+ // Remove the unused arguments.
+ int methodArgumentCount = bootstrapMethodInfo.u2methodArgumentCount;
+ int[] methodArguments = bootstrapMethodInfo.u2methodArguments;
+
+ int newArgumentIndex = 0;
+
+ for (int argumentIndex = 0; argumentIndex < methodArgumentCount; argumentIndex++)
+ {
+ if (argumentIndex >= 64 ||
+ (usedParameters & (1L << argumentIndex)) != 0L)
+ {
+ methodArguments[newArgumentIndex++] = methodArguments[argumentIndex];
+ }
+ }
+
+ // Update the number of arguments.
+ bootstrapMethodInfo.u2methodArgumentCount = newArgumentIndex;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Check the referenced bootstrap method.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Check the referenced class member itself.
+ refConstant.referencedMemberAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ usedParameters = ParameterUsageMarker.getUsedParameters(programMethod);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ChangedCodePrinter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ChangedCodePrinter.java
new file mode 100644
index 0000000000..71efd0290f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ChangedCodePrinter.java
@@ -0,0 +1,350 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.ClassUtil;
+
+/**
+ * This AttributeVisitor delegates its call to another AttributeVisitor, and
+ * prints out the code if the other visitor has changed it.
+ *
+ * @author Eric Lafortune
+ */
+public class ChangedCodePrinter
+implements AttributeVisitor
+{
+ private final AttributeVisitor attributeVisitor;
+
+
+ public ChangedCodePrinter(AttributeVisitor attributeVisitor)
+ {
+ this.attributeVisitor = attributeVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ attributeVisitor.visitUnknownAttribute(clazz, unknownAttribute);
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ attributeVisitor.visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute);
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ attributeVisitor.visitSourceFileAttribute(clazz, sourceFileAttribute);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ attributeVisitor.visitSourceDirAttribute(clazz, sourceDirAttribute);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ attributeVisitor.visitInnerClassesAttribute(clazz, innerClassesAttribute);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ attributeVisitor.visitEnclosingMethodAttribute(clazz, enclosingMethodAttribute);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, deprecatedAttribute);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, syntheticAttribute);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute syntheticAttribute)
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, syntheticAttribute);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute)
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, field, deprecatedAttribute);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute)
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, field, syntheticAttribute);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute syntheticAttribute)
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, field, syntheticAttribute);
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute)
+ {
+ attributeVisitor.visitDeprecatedAttribute(clazz, method, deprecatedAttribute);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute)
+ {
+ attributeVisitor.visitSyntheticAttribute(clazz, method, syntheticAttribute);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute syntheticAttribute)
+ {
+ attributeVisitor.visitSignatureAttribute(clazz, method, syntheticAttribute);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ attributeVisitor.visitConstantValueAttribute(clazz, field, constantValueAttribute);
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute exceptionsAttribute)
+ {
+ attributeVisitor.visitMethodParametersAttribute(clazz, method, exceptionsAttribute);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ attributeVisitor.visitExceptionsAttribute(clazz, method, exceptionsAttribute);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ attributeVisitor.visitStackMapAttribute(clazz, method, codeAttribute, stackMapAttribute);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ attributeVisitor.visitStackMapTableAttribute(clazz, method, codeAttribute, stackMapTableAttribute);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ attributeVisitor.visitLineNumberTableAttribute(clazz, method, codeAttribute, lineNumberTableAttribute);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ attributeVisitor.visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ attributeVisitor.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, runtimeVisibleAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, runtimeInvisibleAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, field, runtimeVisibleAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, field, runtimeInvisibleAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, method, runtimeVisibleAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, method, runtimeInvisibleAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeVisibleParameterAnnotationsAttribute(clazz, method, runtimeVisibleParameterAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeInvisibleParameterAnnotationsAttribute(clazz, method, runtimeInvisibleParameterAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, runtimeVisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeVisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
+ {
+ attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeInvisibleTypeAnnotationsAttribute);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ attributeVisitor.visitAnnotationDefaultAttribute(clazz, method, annotationDefaultAttribute);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ byte[] code = codeAttribute.code;
+ byte[] oldCode = new byte[code.length];
+
+ // Copy the current code.
+ System.arraycopy(code, 0, oldCode, 0, codeAttribute.u4codeLength);
+
+ // Delegate to the real visitor.
+ attributeVisitor.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Check if the code has changed.
+ if (codeHasChanged(codeAttribute, oldCode))
+ {
+ printChangedCode(clazz, method, codeAttribute, oldCode);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean codeHasChanged(CodeAttribute codeAttribute, byte[] oldCode)
+ {
+ if (oldCode.length != codeAttribute.u4codeLength)
+ {
+ return true;
+ }
+
+ for (int index = 0; index < codeAttribute.u4codeLength; index++)
+ {
+ if (oldCode[index] != codeAttribute.code[index])
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ private void printChangedCode(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ byte[] oldCode)
+ {
+ System.out.println("Class "+ClassUtil.externalClassName(clazz.getName()));
+ System.out.println("Method "+ClassUtil.externalFullMethodDescription(clazz.getName(),
+ 0,
+ method.getName(clazz),
+ method.getDescriptor(clazz)));
+
+ for (int index = 0; index < codeAttribute.u4codeLength; index++)
+ {
+ System.out.println(
+ (oldCode[index] == codeAttribute.code[index]? " -- ":" => ")+
+ index+": "+
+ Integer.toHexString(0x100|oldCode[index] &0xff).substring(1)+" "+
+ Integer.toHexString(0x100|codeAttribute.code[index]&0xff).substring(1));
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ConstantMemberFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ConstantMemberFilter.java
new file mode 100644
index 0000000000..640ddc0158
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ConstantMemberFilter.java
@@ -0,0 +1,77 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.evaluation.value.Value;
+import proguard.optimize.evaluation.StoringInvocationUnit;
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to program class members
+ * to another given <code>MemberVisitor</code>, but only when the visited
+ * class member has been marked as a constant.
+ *
+ * @see StoringInvocationUnit
+ * @author Eric Lafortune
+ */
+public class ConstantMemberFilter
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final MemberVisitor constantMemberVisitor;
+
+
+ /**
+ * Creates a new ConstantMemberFilter.
+ * @param constantMemberVisitor the <code>MemberVisitor</code> to which
+ * visits to constant members will be delegated.
+ */
+ public ConstantMemberFilter(MemberVisitor constantMemberVisitor)
+ {
+ this.constantMemberVisitor = constantMemberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ Value value = StoringInvocationUnit.getFieldValue(programField);
+ if (value != null &&
+ value.isParticular())
+ {
+ constantMemberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ Value value = StoringInvocationUnit.getMethodReturnValue(programMethod);
+ if (value != null &&
+ value.isParticular())
+ {
+ constantMemberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ConstantParameterFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ConstantParameterFilter.java
new file mode 100644
index 0000000000..af16d9a478
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ConstantParameterFilter.java
@@ -0,0 +1,78 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.evaluation.value.Value;
+import proguard.optimize.evaluation.StoringInvocationUnit;
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to program methods
+ * to another given <code>MemberVisitor</code>, for each method parameter
+ * that has been marked as constant.
+ *
+ * @see StoringInvocationUnit
+ * @author Eric Lafortune
+ */
+public class ConstantParameterFilter
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final MemberVisitor constantParameterVisitor;
+
+
+ /**
+ * Creates a new ConstantParameterFilter.
+ * @param constantParameterVisitor the <code>MemberVisitor</code> to which
+ * visits will be delegated.
+ */
+ public ConstantParameterFilter(MemberVisitor constantParameterVisitor)
+ {
+ this.constantParameterVisitor = constantParameterVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // All parameters of non-static methods are shifted by one in the local
+ // variable frame.
+ int firstParameterIndex =
+ (programMethod.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ?
+ 0 : 1;
+
+ int parameterCount =
+ ClassUtil.internalMethodParameterCount(programMethod.getDescriptor(programClass));
+
+ for (int index = firstParameterIndex; index < parameterCount; index++)
+ {
+ Value value = StoringInvocationUnit.getMethodParameterValue(programMethod, index);
+ if (value != null &&
+ value.isParticular())
+ {
+ constantParameterVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/DuplicateInitializerFixer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/DuplicateInitializerFixer.java
new file mode 100644
index 0000000000..a255343901
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/DuplicateInitializerFixer.java
@@ -0,0 +1,215 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.ConstantPoolEditor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor adds an additional parameter to the duplicate
+ * initialization methods that it visits.
+ */
+public class DuplicateInitializerFixer
+extends SimplifiedVisitor
+implements MemberVisitor,
+ AttributeVisitor
+{
+ private static final boolean DEBUG = false;
+
+ private static final char[] TYPES = new char[]
+ {
+ ClassConstants.TYPE_BYTE,
+ ClassConstants.TYPE_CHAR,
+ ClassConstants.TYPE_SHORT,
+ ClassConstants.TYPE_INT,
+ ClassConstants.TYPE_BOOLEAN
+ };
+
+
+ private final MemberVisitor extraFixedInitializerVisitor;
+
+
+ /**
+ * Creates a new DuplicateInitializerFixer.
+ */
+ public DuplicateInitializerFixer()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new DuplicateInitializerFixer with an extra visitor.
+ * @param extraFixedInitializerVisitor an optional extra visitor for all
+ * initializers that have been fixed.
+ */
+ public DuplicateInitializerFixer(MemberVisitor extraFixedInitializerVisitor)
+ {
+ this.extraFixedInitializerVisitor = extraFixedInitializerVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Is it a class instance initializer?
+ String name = programMethod.getName(programClass);
+ if (name.equals(ClassConstants.METHOD_NAME_INIT))
+ {
+ // Is there already another initializer with the same descriptor?
+ String descriptor = programMethod.getDescriptor(programClass);
+ Method similarMethod = programClass.findMethod(name, descriptor);
+ if (!programMethod.equals(similarMethod))
+ {
+ // Should this initializer be preserved?
+ if (KeepMarker.isKept(programMethod))
+ {
+ // Fix the other initializer.
+ programMethod = (ProgramMethod)similarMethod;
+ }
+
+ int index = descriptor.indexOf(ClassConstants.METHOD_ARGUMENTS_CLOSE);
+
+ // Try to find a new, unique descriptor.
+ int typeCounter = 0;
+ while (true)
+ {
+ // Construct the new descriptor by inserting a new type
+ // as an additional last argument.
+ StringBuffer newDescriptorBuffer =
+ new StringBuffer(descriptor.substring(0, index));
+
+ for (int arrayDimension = 0; arrayDimension < typeCounter / TYPES.length; arrayDimension++)
+ {
+ newDescriptorBuffer.append(ClassConstants.TYPE_ARRAY);
+ }
+
+ newDescriptorBuffer.append(TYPES[typeCounter % TYPES.length]);
+ newDescriptorBuffer.append(descriptor.substring(index));
+
+ String newDescriptor = newDescriptorBuffer.toString();
+
+ // Is the new initializer descriptor unique?
+ if (programClass.findMethod(name, newDescriptor) == null)
+ {
+ if (DEBUG)
+ {
+ System.out.println("DuplicateInitializerFixer:");
+ System.out.println(" ["+programClass.getName()+"."+name+descriptor+"] ("+ClassUtil.externalClassAccessFlags(programMethod.getAccessFlags())+") -> ["+newDescriptor+"]");
+ }
+
+ // Update the descriptor.
+ programMethod.u2descriptorIndex =
+ new ConstantPoolEditor(programClass).addUtf8Constant(newDescriptor);
+
+ // Fix the local variable frame size, the method
+ // signature, and the parameter annotations, if
+ // necessary.
+ programMethod.attributesAccept(programClass,
+ this);
+
+ // Visit the initializer, if required.
+ if (extraFixedInitializerVisitor != null)
+ {
+ extraFixedInitializerVisitor.visitProgramMethod(programClass, programMethod);
+ }
+
+ // We're done with this constructor.
+ return;
+ }
+
+ typeCounter++;
+ }
+ }
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // The minimum variable size is determined by the arguments.
+ int maxLocals =
+ ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz),
+ method.getAccessFlags());
+
+ if (codeAttribute.u2maxLocals < maxLocals)
+ {
+ codeAttribute.u2maxLocals = maxLocals;
+ }
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute)
+ {
+ String descriptor = method.getDescriptor(clazz);
+ int descriptorIndex = descriptor.indexOf(ClassConstants.METHOD_ARGUMENTS_CLOSE);
+ String signature = signatureAttribute.getSignature(clazz);
+ int signatureIndex = signature.indexOf(ClassConstants.METHOD_ARGUMENTS_CLOSE);
+
+ String newSignature = signature.substring(0, signatureIndex) +
+ descriptor.charAt(descriptorIndex - 1) +
+ signature.substring(signatureIndex);
+
+ // Update the signature.
+ signatureAttribute.u2signatureIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Update the number of parameters.
+ int oldParametersCount = parameterAnnotationsAttribute.u1parametersCount++;
+
+ if (parameterAnnotationsAttribute.u2parameterAnnotationsCount == null ||
+ parameterAnnotationsAttribute.u2parameterAnnotationsCount.length < parameterAnnotationsAttribute.u1parametersCount)
+ {
+ int[] annotationsCounts = new int[parameterAnnotationsAttribute.u1parametersCount];
+ Annotation[][] annotations = new Annotation[parameterAnnotationsAttribute.u1parametersCount][];
+
+ System.arraycopy(parameterAnnotationsAttribute.u2parameterAnnotationsCount,
+ 0,
+ annotationsCounts,
+ 0,
+ oldParametersCount);
+
+ System.arraycopy(parameterAnnotationsAttribute.parameterAnnotations,
+ 0,
+ annotations,
+ 0,
+ oldParametersCount);
+
+ parameterAnnotationsAttribute.u2parameterAnnotationsCount = annotationsCounts;
+ parameterAnnotationsAttribute.parameterAnnotations = annotations;
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/DuplicateInitializerInvocationFixer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
new file mode 100644
index 0000000000..a080208e1a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
@@ -0,0 +1,165 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This AttributeVisitor adds an additional integer parameter to the tweaked
+ * initialization method invocations that it visits.
+ */
+public class DuplicateInitializerInvocationFixer
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ private static final boolean DEBUG = false;
+
+ private final InstructionVisitor extraAddedInstructionVisitor;
+
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
+
+ private String descriptor;
+ private int descriptorLengthDelta;
+
+
+ /**
+ * Creates a new DuplicateInitializerInvocationFixer.
+ */
+ public DuplicateInitializerInvocationFixer()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new DuplicateInitializerInvocationFixer.
+ * @param extraAddedInstructionVisitor an optional extra visitor for all
+ * added instructions.
+ */
+ public DuplicateInitializerInvocationFixer(InstructionVisitor extraAddedInstructionVisitor)
+ {
+ this.extraAddedInstructionVisitor = extraAddedInstructionVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+
+ // Reset the code changes.
+ codeAttributeEditor.reset(codeAttribute.u4codeLength);
+
+ // Fix any duplicate constructor invocations.
+ codeAttribute.instructionsAccept(clazz,
+ method,
+ this);
+
+ // Apply all accumulated changes to the code.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ if (constantInstruction.opcode == InstructionConstants.OP_INVOKESPECIAL)
+ {
+ descriptorLengthDelta = 0;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+
+ if (descriptorLengthDelta > 0)
+ {
+ Instruction extraInstruction =
+ new SimpleInstruction(descriptorLengthDelta == 1 ?
+ InstructionConstants.OP_ICONST_0 :
+ InstructionConstants.OP_ACONST_NULL);
+
+ codeAttributeEditor.insertBeforeInstruction(offset,
+ extraInstruction);
+
+ if (DEBUG)
+ {
+ System.out.println(" ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] Inserting "+extraInstruction.toString()+" before "+constantInstruction.toString(offset));
+ }
+
+ if (extraAddedInstructionVisitor != null)
+ {
+ extraInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
+ }
+ }
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Check the referenced constructor descriptor.
+ if (refConstant.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT))
+ {
+ descriptor = refConstant.getType(clazz);
+
+ refConstant.referencedMemberAccept(this);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ descriptorLengthDelta =
+ programMethod.getDescriptor(programClass).length() - descriptor.length();
+
+ if (DEBUG)
+ {
+ if (descriptorLengthDelta > 0)
+ {
+ System.out.println("DuplicateInitializerInvocationFixer:");
+ System.out.println(" ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] ("+ClassUtil.externalClassAccessFlags(programMethod.getAccessFlags())+") referenced by:");
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeepMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeepMarker.java
new file mode 100644
index 0000000000..c04b5f7df5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeepMarker.java
@@ -0,0 +1,103 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.util.MethodLinker;
+import proguard.classfile.visitor.*;
+import proguard.optimize.info.NoSideEffectMethodMarker;
+
+
+/**
+ * This <code>ClassVisitor</code> and <code>MemberVisitor</code>
+ * marks classes and class members it visits. The marked elements
+ * will remain unchanged as necessary in the optimization step.
+ *
+ * @see NoSideEffectMethodMarker
+ * @author Eric Lafortune
+ */
+public class KeepMarker
+implements ClassVisitor,
+ MemberVisitor
+{
+ // A visitor info flag to indicate the visitor accepter is being kept.
+ private static final Object KEPT = new Object();
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ markAsKept(programClass);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ markAsKept(libraryClass);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ markAsKept(programField);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ markAsKept(MethodLinker.lastMember(programMethod));
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ markAsKept(libraryField);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ markAsKept(MethodLinker.lastMember(libraryMethod));
+ }
+
+
+ // Small utility methods.
+
+ private static void markAsKept(VisitorAccepter visitorAccepter)
+ {
+ visitorAccepter.setVisitorInfo(KEPT);
+ }
+
+
+ public static boolean isKept(VisitorAccepter visitorAccepter)
+ {
+ // We're also checking for the constant in NoSideEffectMethodMarker,
+ // to keep things simple.
+ Object visitorInfo =
+ MethodLinker.lastVisitorAccepter(visitorAccepter).getVisitorInfo();
+
+ return visitorInfo == KEPT ||
+ visitorInfo == NoSideEffectMethodMarker.KEPT_BUT_NO_SIDE_EFFECTS;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeptClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeptClassFilter.java
new file mode 100644
index 0000000000..e1c7f08903
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeptClassFilter.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are marked as kept.
+ *
+ * @see KeepMarker
+ *
+ * @author Eric Lafortune
+ */
+public class KeptClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new KeptClassFilter.
+ * @param classVisitor the class visitor to which the visiting will be
+ * delegated.
+ */
+ public KeptClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (KeepMarker.isKept(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (KeepMarker.isKept(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeptMemberFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeptMemberFilter.java
new file mode 100644
index 0000000000..7c8eb7cc59
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/KeptMemberFilter.java
@@ -0,0 +1,87 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor delegates all its method calls to another MemberVisitor,
+ * but only for Member objects that are marked as kept.
+ *
+ * @see KeepMarker
+ *
+ * @author Eric Lafortune
+ */
+public class KeptMemberFilter
+implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new KeptMemberFilter.
+ * @param memberVisitor the member visitor to which the visiting will be
+ * delegated.
+ */
+ public KeptMemberFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (KeepMarker.isKept(programField))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (KeepMarker.isKept(programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (KeepMarker.isKept(libraryField))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (KeepMarker.isKept(libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MemberDescriptorSpecializer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MemberDescriptorSpecializer.java
new file mode 100644
index 0000000000..ed3a6ecdf6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MemberDescriptorSpecializer.java
@@ -0,0 +1,138 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.editor.ClassReferenceFixer;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.evaluation.value.Value;
+import proguard.optimize.evaluation.StoringInvocationUnit;
+
+/**
+ * This MemberVisitor specializes parameters in the descriptors of the
+ * methods that it visits.
+ *
+ * @see StoringInvocationUnit
+ * @see ClassReferenceFixer
+ * @author Eric Lafortune
+ */
+public class MemberDescriptorSpecializer
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ private final MemberVisitor extraParameterMemberVisitor;
+
+
+ /**
+ * Creates a new MethodDescriptorShrinker.
+ */
+ public MemberDescriptorSpecializer()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new MethodDescriptorShrinker with an extra visitor.
+ * @param extraParameterMemberVisitor an optional extra visitor for all
+ * class members whose parameters have
+ * been specialized.
+ */
+ public MemberDescriptorSpecializer(MemberVisitor extraParameterMemberVisitor)
+ {
+ this.extraParameterMemberVisitor = extraParameterMemberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ Value parameterValue = StoringInvocationUnit.getFieldValue(programField);
+ if (parameterValue.computationalType() == Value.TYPE_REFERENCE)
+ {
+ Clazz referencedClass = parameterValue.referenceValue().getReferencedClass();
+ if (programField.referencedClass != referencedClass)
+ {
+ if (DEBUG)
+ {
+ System.out.println("MemberDescriptorSpecializer: "+programClass.getName()+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass));
+ System.out.println(" "+programField.referencedClass.getName()+" -> "+referencedClass.getName());
+ }
+
+ programField.referencedClass = referencedClass;
+
+ // Visit the field, if required.
+ if (extraParameterMemberVisitor != null)
+ {
+ extraParameterMemberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // All parameters of non-static methods are shifted by one in the local
+ // variable frame.
+ int firstParameterIndex =
+ (programMethod.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ?
+ 0 : 1;
+
+ int parameterCount =
+ ClassUtil.internalMethodParameterCount(programMethod.getDescriptor(programClass));
+
+ int classIndex = 0;
+
+ // Go over the parameters.
+ for (int parameterIndex = firstParameterIndex; parameterIndex < parameterCount; parameterIndex++)
+ {
+ Value parameterValue = StoringInvocationUnit.getMethodParameterValue(programMethod, parameterIndex);
+ if (parameterValue.computationalType() == Value.TYPE_REFERENCE)
+ {
+ Clazz referencedClass = parameterValue.referenceValue().getReferencedClass();
+ if (programMethod.referencedClasses[classIndex] != referencedClass)
+ {
+ if (DEBUG)
+ {
+ System.out.println("MemberDescriptorSpecializer: "+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass));
+ System.out.println(" "+programMethod.referencedClasses[classIndex].getName()+" -> "+referencedClass.getName());
+ }
+
+ programMethod.referencedClasses[classIndex] = referencedClass;
+
+ // Visit the method, if required.
+ if (extraParameterMemberVisitor != null)
+ {
+ extraParameterMemberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+ classIndex++;
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MethodDescriptorShrinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MethodDescriptorShrinker.java
new file mode 100644
index 0000000000..b68877f025
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MethodDescriptorShrinker.java
@@ -0,0 +1,352 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.ConstantPoolEditor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.info.*;
+import proguard.optimize.peephole.VariableShrinker;
+
+import java.util.Arrays;
+
+/**
+ * This MemberVisitor removes unused parameters in the descriptors of the
+ * methods that it visits. It also updates the signatures and parameter
+ * annotations.
+ *
+ * @see ParameterUsageMarker
+ * @see VariableUsageMarker
+ * @see ParameterShrinker
+ * @author Eric Lafortune
+ */
+public class MethodDescriptorShrinker
+extends SimplifiedVisitor
+implements MemberVisitor,
+ AttributeVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ private final MemberVisitor extraMemberVisitor;
+
+
+ /**
+ * Creates a new MethodDescriptorShrinker.
+ */
+ public MethodDescriptorShrinker()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new MethodDescriptorShrinker with an extra visitor.
+ * @param extraMemberVisitor an optional extra visitor for all methods whose
+ * parameters have been simplified.
+ */
+ public MethodDescriptorShrinker(MemberVisitor extraMemberVisitor)
+ {
+ this.extraMemberVisitor = extraMemberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (DEBUG)
+ {
+ System.out.println("MethodDescriptorShrinker: ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"]");
+ }
+
+ // Update the descriptor if it has any unused parameters.
+ String descriptor = programMethod.getDescriptor(programClass);
+ String newDescriptor = shrinkDescriptor(programMethod, descriptor);
+
+ if (!newDescriptor.equals(descriptor))
+ {
+ // Shrink the signature and parameter annotations,
+ // before shrinking the descriptor itself.
+ programMethod.attributesAccept(programClass, this);
+
+ String name = programMethod.getName(programClass);
+ String newName = name;
+
+ // Append a code, if the method isn't a class instance initializer.
+ if (!name.equals(ClassConstants.METHOD_NAME_INIT))
+ {
+ newName += ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode()));
+ }
+
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor(programClass);
+
+ // Update the name, if necessary.
+ if (!newName.equals(name))
+ {
+ programMethod.u2nameIndex =
+ constantPoolEditor.addUtf8Constant(newName);
+ }
+
+ // Update the referenced classes.
+ programMethod.referencedClasses =
+ shrinkReferencedClasses(programMethod,
+ descriptor,
+ programMethod.referencedClasses);
+
+ // Finally, update the descriptor itself.
+ programMethod.u2descriptorIndex =
+ constantPoolEditor.addUtf8Constant(newDescriptor);
+
+ if (DEBUG)
+ {
+ System.out.println(" -> ["+newName+newDescriptor+"]");
+ }
+
+ // Visit the method, if required.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute)
+ {
+ if (DEBUG)
+ {
+ System.out.println(" ["+signatureAttribute.getSignature(clazz)+"]");
+ }
+
+ // Compute the new signature.
+ String signature = signatureAttribute.getSignature(clazz);
+ String newSignature = shrinkDescriptor(method, signature);
+
+ if (!newSignature.equals(signature))
+ {
+ // Update the signature.
+ signatureAttribute.u2signatureIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature);
+
+ // Update the referenced classes.
+ signatureAttribute.referencedClasses =
+ shrinkReferencedClasses(method,
+ signature,
+ signatureAttribute.referencedClasses);
+
+ if (DEBUG)
+ {
+ System.out.println(" -> ["+newSignature+"]");
+ }
+ }
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ int[] annotationsCounts = parameterAnnotationsAttribute.u2parameterAnnotationsCount;
+ Annotation[][] annotations = parameterAnnotationsAttribute.parameterAnnotations;
+
+ // All parameters of non-static methods are shifted by one in the local
+ // variable frame.
+ int parameterIndex =
+ (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ?
+ 0 : 1;
+
+ int annotationIndex = 0;
+ int newAnnotationIndex = 0;
+
+ // Go over the parameters.
+ String descriptor = method.getDescriptor(clazz);
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(descriptor);
+
+ while (internalTypeEnumeration.hasMoreTypes())
+ {
+ String type = internalTypeEnumeration.nextType();
+ if (ParameterUsageMarker.isParameterUsed(method, parameterIndex))
+ {
+ annotationsCounts[newAnnotationIndex] = annotationsCounts[annotationIndex];
+ annotations[newAnnotationIndex++] = annotations[annotationIndex];
+ }
+
+ annotationIndex++;
+
+ parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1;
+ }
+
+ // Update the number of parameters.
+ parameterAnnotationsAttribute.u1parametersCount = newAnnotationIndex;
+
+ // Clear the unused entries.
+ while (newAnnotationIndex < annotationIndex)
+ {
+ annotationsCounts[newAnnotationIndex] = 0;
+ annotations[newAnnotationIndex++] = null;
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns a shrunk descriptor or signature of the given method.
+ */
+ private String shrinkDescriptor(Method method, String descriptor)
+ {
+ // All parameters of non-static methods are shifted by one in the local
+ // variable frame.
+ int parameterIndex =
+ (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ?
+ 0 : 1;
+
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(descriptor);
+
+ StringBuffer newDescriptorBuffer =
+ new StringBuffer(descriptor.length());
+
+ // Copy the formal type parameters.
+ newDescriptorBuffer.append(internalTypeEnumeration.formalTypeParameters());
+ newDescriptorBuffer.append(ClassConstants.METHOD_ARGUMENTS_OPEN);
+
+ // Go over the parameters.
+ while (internalTypeEnumeration.hasMoreTypes())
+ {
+ String type = internalTypeEnumeration.nextType();
+ if (ParameterUsageMarker.isParameterUsed(method, parameterIndex))
+ {
+ newDescriptorBuffer.append(type);
+ }
+ else if (DEBUG)
+ {
+ System.out.println(" Deleting parameter #"+parameterIndex+" ["+type+"]");
+ }
+
+ parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1;
+ }
+
+ // Copy the return type.
+ newDescriptorBuffer.append(ClassConstants.METHOD_ARGUMENTS_CLOSE);
+ newDescriptorBuffer.append(internalTypeEnumeration.returnType());
+
+ return newDescriptorBuffer.toString();
+ }
+
+
+ /**
+ * Shrinks the array of referenced classes of the given method.
+ */
+ private Clazz[] shrinkReferencedClasses(Method method,
+ String descriptor,
+ Clazz[] referencedClasses)
+ {
+ if (referencedClasses != null)
+ {
+ // All parameters of non-static methods are shifted by one in the local
+ // variable frame.
+ int parameterIndex =
+ (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ?
+ 0 : 1;
+
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(descriptor);
+
+ int referencedClassIndex = 0;
+ int newReferencedClassIndex = 0;
+
+ // Copy the formal type parameters.
+ {
+ String type = internalTypeEnumeration.formalTypeParameters();
+ int count = new DescriptorClassEnumeration(type).classCount();
+ for (int counter = 0; counter < count; counter++)
+ {
+ referencedClasses[newReferencedClassIndex++] =
+ referencedClasses[referencedClassIndex++];
+ }
+ }
+
+ // Go over the parameters.
+ while (internalTypeEnumeration.hasMoreTypes())
+ {
+ // Consider the classes referenced by this parameter type.
+ String type = internalTypeEnumeration.nextType();
+ int count = new DescriptorClassEnumeration(type).classCount();
+
+ if (ParameterUsageMarker.isParameterUsed(method, parameterIndex))
+ {
+ // Copy the referenced classes.
+ for (int counter = 0; counter < count; counter++)
+ {
+ referencedClasses[newReferencedClassIndex++] =
+ referencedClasses[referencedClassIndex++];
+ }
+ }
+ else
+ {
+ // Skip the referenced classes.
+ referencedClassIndex += count;
+ }
+
+ parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1;
+ }
+
+ // Copy the return type.
+ {
+ String type = internalTypeEnumeration.returnType();
+ int count = new DescriptorClassEnumeration(type).classCount();
+ for (int counter = 0; counter < count; counter++)
+ {
+ referencedClasses[newReferencedClassIndex++] =
+ referencedClasses[referencedClassIndex++];
+ }
+ }
+
+ // Shrink the array to the proper size.
+ if (newReferencedClassIndex == 0)
+ {
+ referencedClasses = null;
+ }
+ else if (newReferencedClassIndex < referencedClassIndex)
+ {
+ Clazz[] newReferencedClasses = new Clazz[newReferencedClassIndex];
+ System.arraycopy(referencedClasses, 0,
+ newReferencedClasses, 0,
+ newReferencedClassIndex);
+
+ referencedClasses = newReferencedClasses;
+ }
+ }
+
+ return referencedClasses;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MethodStaticizer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MethodStaticizer.java
new file mode 100644
index 0000000000..0d87e6255f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/MethodStaticizer.java
@@ -0,0 +1,87 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.MethodInvocationFixer;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.info.ParameterUsageMarker;
+import proguard.optimize.peephole.VariableShrinker;
+
+/**
+ * This MemberVisitor makes all methods that it visits static, if their 'this'
+ * parameters are unused.
+ *
+ * @see ParameterUsageMarker
+ * @see MethodInvocationFixer
+ * @see VariableShrinker
+ * @author Eric Lafortune
+ */
+public class MethodStaticizer
+extends SimplifiedVisitor
+implements MemberVisitor,
+ AttributeVisitor
+{
+ private final MemberVisitor extraStaticMemberVisitor;
+
+
+ /**
+ * Creates a new MethodStaticizer.
+ */
+ public MethodStaticizer()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new MethodStaticizer with an extra visitor.
+ * @param extraStaticMemberVisitor an optional extra visitor for all
+ * methods that have been made static.
+ */
+ public MethodStaticizer(MemberVisitor extraStaticMemberVisitor)
+ {
+ this.extraStaticMemberVisitor = extraStaticMemberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Is the 'this' parameter being used?
+ if (!ParameterUsageMarker.isParameterUsed(programMethod, 0))
+ {
+ // Make the method static.
+ programMethod.u2accessFlags =
+ (programMethod.getAccessFlags() & ~ClassConstants.ACC_FINAL) |
+ ClassConstants.ACC_STATIC;
+
+ // Visit the method, if required.
+ if (extraStaticMemberVisitor != null)
+ {
+ extraStaticMemberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/OptimizationInfoClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/OptimizationInfoClassFilter.java
new file mode 100644
index 0000000000..93bf62eb61
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/OptimizationInfoClassFilter.java
@@ -0,0 +1,72 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.*;
+import proguard.optimize.info.ClassOptimizationInfo;
+
+/**
+ * This <code>ClassVisitor</code> delegates its visits to another given
+ * <code>ClassVisitor</code>, but only when the visited class has optimization
+ * info.
+ *
+ * @see ClassOptimizationInfo
+ * @author Eric Lafortune
+ */
+public class OptimizationInfoClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new OptimizationInfoClassFilter.
+ * @param classVisitor the <code>ClassVisitor</code> to which visits
+ * will be delegated.
+ */
+ public OptimizationInfoClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Does the class have optimization info?
+ if (ClassOptimizationInfo.getClassOptimizationInfo(programClass) != null)
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Does the class have optimization info?
+ if (ClassOptimizationInfo.getClassOptimizationInfo(libraryClass) != null)
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/OptimizationInfoMemberFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/OptimizationInfoMemberFilter.java
new file mode 100644
index 0000000000..950fcfa5bb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/OptimizationInfoMemberFilter.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.info.*;
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to another given
+ * <code>MemberVisitor</code>, but only when the visited member has optimization
+ * info.
+ *
+ * @see FieldOptimizationInfo
+ * @see MethodOptimizationInfo
+ * @author Eric Lafortune
+ */
+public class OptimizationInfoMemberFilter
+implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new OptimizationInfoMemberFilter.
+ * @param memberVisitor the <code>MemberVisitor</code> to which visits will
+ * be delegated.
+ */
+ public OptimizationInfoMemberFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Does the field have optimization info?
+ if (FieldOptimizationInfo.getFieldOptimizationInfo(programField) != null)
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ // Does the field have optimization info?
+ if (FieldOptimizationInfo.getFieldOptimizationInfo(libraryField) != null)
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Does the method have optimization info?
+ if (MethodOptimizationInfo.getMethodOptimizationInfo(programMethod) != null)
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ // Does the method have optimization info?
+ if (MethodOptimizationInfo.getMethodOptimizationInfo(libraryMethod) != null)
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/Optimizer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/Optimizer.java
new file mode 100644
index 0000000000..33c3c0ca30
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/Optimizer.java
@@ -0,0 +1,1126 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.*;
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.visitor.*;
+import proguard.classfile.editor.*;
+import proguard.classfile.instruction.visitor.*;
+import proguard.classfile.util.MethodLinker;
+import proguard.classfile.visitor.*;
+import proguard.evaluation.*;
+import proguard.evaluation.value.*;
+import proguard.optimize.evaluation.*;
+import proguard.optimize.info.*;
+import proguard.optimize.peephole.*;
+import proguard.util.*;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * This class optimizes class pools according to a given configuration.
+ *
+ * @author Eric Lafortune
+ */
+public class Optimizer
+{
+ private static final String CLASS_MARKING_FINAL = "class/marking/final";
+ private static final String CLASS_UNBOXING_ENUM = "class/unboxing/enum";
+ private static final String CLASS_MERGING_VERTICAL = "class/merging/vertical";
+ private static final String CLASS_MERGING_HORIZONTAL = "class/merging/horizontal";
+ private static final String FIELD_REMOVAL_WRITEONLY = "field/removal/writeonly";
+ private static final String FIELD_MARKING_PRIVATE = "field/marking/private";
+ private static final String FIELD_PROPAGATION_VALUE = "field/propagation/value";
+ private static final String METHOD_MARKING_PRIVATE = "method/marking/private";
+ private static final String METHOD_MARKING_STATIC = "method/marking/static";
+ private static final String METHOD_MARKING_FINAL = "method/marking/final";
+ private static final String METHOD_REMOVAL_PARAMETER = "method/removal/parameter";
+ private static final String METHOD_PROPAGATION_PARAMETER = "method/propagation/parameter";
+ private static final String METHOD_PROPAGATION_RETURNVALUE = "method/propagation/returnvalue";
+ private static final String METHOD_INLINING_SHORT = "method/inlining/short";
+ private static final String METHOD_INLINING_UNIQUE = "method/inlining/unique";
+ private static final String METHOD_INLINING_TAILRECURSION = "method/inlining/tailrecursion";
+ private static final String CODE_MERGING = "code/merging";
+ private static final String CODE_SIMPLIFICATION_VARIABLE = "code/simplification/variable";
+ private static final String CODE_SIMPLIFICATION_ARITHMETIC = "code/simplification/arithmetic";
+ private static final String CODE_SIMPLIFICATION_CAST = "code/simplification/cast";
+ private static final String CODE_SIMPLIFICATION_FIELD = "code/simplification/field";
+ private static final String CODE_SIMPLIFICATION_BRANCH = "code/simplification/branch";
+ private static final String CODE_SIMPLIFICATION_STRING = "code/simplification/string";
+ private static final String CODE_SIMPLIFICATION_ADVANCED = "code/simplification/advanced";
+ private static final String CODE_REMOVAL_ADVANCED = "code/removal/advanced";
+ private static final String CODE_REMOVAL_SIMPLE = "code/removal/simple";
+ private static final String CODE_REMOVAL_VARIABLE = "code/removal/variable";
+ private static final String CODE_REMOVAL_EXCEPTION = "code/removal/exception";
+ private static final String CODE_ALLOCATION_VARIABLE = "code/allocation/variable";
+
+
+ public static final String[] OPTIMIZATION_NAMES = new String[]
+ {
+ CLASS_MARKING_FINAL,
+ CLASS_MERGING_VERTICAL,
+ CLASS_MERGING_HORIZONTAL,
+ FIELD_REMOVAL_WRITEONLY,
+ FIELD_MARKING_PRIVATE,
+ FIELD_PROPAGATION_VALUE,
+ METHOD_MARKING_PRIVATE,
+ METHOD_MARKING_STATIC,
+ METHOD_MARKING_FINAL,
+ METHOD_REMOVAL_PARAMETER,
+ METHOD_PROPAGATION_PARAMETER,
+ METHOD_PROPAGATION_RETURNVALUE,
+ METHOD_INLINING_SHORT,
+ METHOD_INLINING_UNIQUE,
+ METHOD_INLINING_TAILRECURSION,
+ CODE_MERGING,
+ CODE_SIMPLIFICATION_VARIABLE,
+ CODE_SIMPLIFICATION_ARITHMETIC,
+ CODE_SIMPLIFICATION_CAST,
+ CODE_SIMPLIFICATION_FIELD,
+ CODE_SIMPLIFICATION_BRANCH,
+ CODE_SIMPLIFICATION_STRING,
+ CODE_SIMPLIFICATION_ADVANCED,
+ CODE_REMOVAL_ADVANCED,
+ CODE_REMOVAL_SIMPLE,
+ CODE_REMOVAL_VARIABLE,
+ CODE_REMOVAL_EXCEPTION,
+ CODE_ALLOCATION_VARIABLE,
+ };
+
+
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new Optimizer.
+ */
+ public Optimizer(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Performs optimization of the given program class pool.
+ */
+ public boolean execute(ClassPool programClassPool,
+ ClassPool libraryClassPool) throws IOException
+ {
+ // Check if we have at least some keep commands.
+ if (configuration.keep == null &&
+ configuration.applyMapping == null &&
+ configuration.printMapping == null)
+ {
+ throw new IOException("You have to specify '-keep' options for the optimization step.");
+ }
+
+ // Create a matcher for filtering optimizations.
+ StringMatcher filter = configuration.optimizations != null ?
+ new ListParser(new NameParser()).parse(configuration.optimizations) :
+ new ConstantMatcher(true);
+
+ boolean classMarkingFinal = filter.matches(CLASS_MARKING_FINAL);
+ boolean classUnboxingEnum = filter.matches(CLASS_UNBOXING_ENUM);
+ boolean classMergingVertical = filter.matches(CLASS_MERGING_VERTICAL);
+ boolean classMergingHorizontal = filter.matches(CLASS_MERGING_HORIZONTAL);
+ boolean fieldRemovalWriteonly = filter.matches(FIELD_REMOVAL_WRITEONLY);
+ boolean fieldMarkingPrivate = filter.matches(FIELD_MARKING_PRIVATE);
+ boolean fieldPropagationValue = filter.matches(FIELD_PROPAGATION_VALUE);
+ boolean methodMarkingPrivate = filter.matches(METHOD_MARKING_PRIVATE);
+ boolean methodMarkingStatic = filter.matches(METHOD_MARKING_STATIC);
+ boolean methodMarkingFinal = filter.matches(METHOD_MARKING_FINAL);
+ boolean methodRemovalParameter = filter.matches(METHOD_REMOVAL_PARAMETER);
+ boolean methodPropagationParameter = filter.matches(METHOD_PROPAGATION_PARAMETER);
+ boolean methodPropagationReturnvalue = filter.matches(METHOD_PROPAGATION_RETURNVALUE);
+ boolean methodInliningShort = filter.matches(METHOD_INLINING_SHORT);
+ boolean methodInliningUnique = filter.matches(METHOD_INLINING_UNIQUE);
+ boolean methodInliningTailrecursion = filter.matches(METHOD_INLINING_TAILRECURSION);
+ boolean codeMerging = filter.matches(CODE_MERGING);
+ boolean codeSimplificationVariable = filter.matches(CODE_SIMPLIFICATION_VARIABLE);
+ boolean codeSimplificationArithmetic = filter.matches(CODE_SIMPLIFICATION_ARITHMETIC);
+ boolean codeSimplificationCast = filter.matches(CODE_SIMPLIFICATION_CAST);
+ boolean codeSimplificationField = filter.matches(CODE_SIMPLIFICATION_FIELD);
+ boolean codeSimplificationBranch = filter.matches(CODE_SIMPLIFICATION_BRANCH);
+ boolean codeSimplificationString = filter.matches(CODE_SIMPLIFICATION_STRING);
+ boolean codeSimplificationAdvanced = filter.matches(CODE_SIMPLIFICATION_ADVANCED);
+ boolean codeRemovalAdvanced = filter.matches(CODE_REMOVAL_ADVANCED);
+ boolean codeRemovalSimple = filter.matches(CODE_REMOVAL_SIMPLE);
+ boolean codeRemovalVariable = filter.matches(CODE_REMOVAL_VARIABLE);
+ boolean codeRemovalException = filter.matches(CODE_REMOVAL_EXCEPTION);
+ boolean codeAllocationVariable = filter.matches(CODE_ALLOCATION_VARIABLE);
+
+ // Create counters to count the numbers of optimizations.
+ ClassCounter classMarkingFinalCounter = new ClassCounter();
+ ClassCounter classUnboxingEnumCounter = new ClassCounter();
+ ClassCounter classMergingVerticalCounter = new ClassCounter();
+ ClassCounter classMergingHorizontalCounter = new ClassCounter();
+ MemberCounter fieldRemovalWriteonlyCounter = new MemberCounter();
+ MemberCounter fieldMarkingPrivateCounter = new MemberCounter();
+ MemberCounter fieldPropagationValueCounter = new MemberCounter();
+ MemberCounter methodMarkingPrivateCounter = new MemberCounter();
+ MemberCounter methodMarkingStaticCounter = new MemberCounter();
+ MemberCounter methodMarkingFinalCounter = new MemberCounter();
+ MemberCounter methodRemovalParameterCounter = new MemberCounter();
+ MemberCounter methodPropagationParameterCounter = new MemberCounter();
+ MemberCounter methodPropagationReturnvalueCounter = new MemberCounter();
+ InstructionCounter methodInliningShortCounter = new InstructionCounter();
+ InstructionCounter methodInliningUniqueCounter = new InstructionCounter();
+ InstructionCounter methodInliningTailrecursionCounter = new InstructionCounter();
+ InstructionCounter codeMergingCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationVariableCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationArithmeticCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationCastCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationFieldCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationBranchCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationStringCounter = new InstructionCounter();
+ InstructionCounter codeSimplificationAdvancedCounter = new InstructionCounter();
+ InstructionCounter deletedCounter = new InstructionCounter();
+ InstructionCounter addedCounter = new InstructionCounter();
+ MemberCounter codeRemovalVariableCounter = new MemberCounter();
+ ExceptionCounter codeRemovalExceptionCounter = new ExceptionCounter();
+ MemberCounter codeAllocationVariableCounter = new MemberCounter();
+ MemberCounter initializerFixCounter1 = new MemberCounter();
+ MemberCounter initializerFixCounter2 = new MemberCounter();
+
+ // Some optimizations are required by other optimizations.
+ codeSimplificationAdvanced =
+ codeSimplificationAdvanced ||
+ fieldPropagationValue ||
+ methodPropagationParameter ||
+ methodPropagationReturnvalue;
+
+ codeRemovalAdvanced =
+ codeRemovalAdvanced ||
+ fieldRemovalWriteonly ||
+ methodMarkingStatic ||
+ methodRemovalParameter;
+
+ codeRemovalSimple =
+ codeRemovalSimple ||
+ codeSimplificationBranch;
+
+ codeRemovalException =
+ codeRemovalException ||
+ codeRemovalAdvanced ||
+ codeRemovalSimple;
+
+ // Clean up any old visitor info.
+ programClassPool.classesAccept(new ClassCleaner());
+ libraryClassPool.classesAccept(new ClassCleaner());
+
+ // Link all methods that should get the same optimization info.
+ programClassPool.classesAccept(new BottomClassFilter(
+ new MethodLinker()));
+ libraryClassPool.classesAccept(new BottomClassFilter(
+ new MethodLinker()));
+
+ // Create a visitor for marking the seeds.
+ KeepMarker keepMarker = new KeepMarker();
+ ClassPoolVisitor classPoolvisitor =
+ ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep,
+ keepMarker,
+ keepMarker,
+ false,
+ true,
+ false);
+ // Mark the seeds.
+ programClassPool.accept(classPoolvisitor);
+ libraryClassPool.accept(classPoolvisitor);
+
+ // All library classes and library class members remain unchanged.
+ libraryClassPool.classesAccept(keepMarker);
+ libraryClassPool.classesAccept(new AllMemberVisitor(keepMarker));
+
+ // We also keep all classes that are involved in .class constructs.
+ // We're not looking at enum classes though, so they can be simplified.
+ programClassPool.classesAccept(
+ new ClassAccessFilter(0, ClassConstants.ACC_ENUM,
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new AllInstructionVisitor(
+ new DotClassClassVisitor(keepMarker))))));
+
+ // We also keep all classes that are accessed dynamically.
+ programClassPool.classesAccept(
+ new AllConstantVisitor(
+ new ConstantTagFilter(ClassConstants.CONSTANT_String,
+ new ReferencedClassVisitor(keepMarker))));
+
+ // We also keep all class members that are accessed dynamically.
+ programClassPool.classesAccept(
+ new AllConstantVisitor(
+ new ConstantTagFilter(ClassConstants.CONSTANT_String,
+ new ReferencedMemberVisitor(keepMarker))));
+
+ // We also keep all bootstrap method signatures.
+ programClassPool.classesAccept(
+ new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_7,
+ new AllAttributeVisitor(
+ new AttributeNameFilter(ClassConstants.ATTR_BootstrapMethods,
+ new AllBootstrapMethodInfoVisitor(
+ new BootstrapMethodHandleTraveler(
+ new MethodrefTraveler(
+ new ReferencedMemberVisitor(keepMarker))))))));
+
+ // We also keep all bootstrap method arguments that point to methods.
+ // These arguments are typically the method handles for
+ // java.lang.invoke.LambdaMetafactory#metafactory, which provides the
+ // implementations for closures.
+ programClassPool.classesAccept(
+ new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_7,
+ new AllAttributeVisitor(
+ new AttributeNameFilter(ClassConstants.ATTR_BootstrapMethods,
+ new AllBootstrapMethodInfoVisitor(
+ new BootstrapMethodArgumentVisitor(
+ new MethodrefTraveler(
+ new ReferencedMemberVisitor(keepMarker))))))));
+
+ // We also keep all classes (and their methods) returned by dynamic
+ // method invocations. They may return dynamic implementations of
+ // interfaces that otherwise appear unused.
+ programClassPool.classesAccept(
+ new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_7,
+ new AllConstantVisitor(
+ new DynamicReturnedClassVisitor(
+ new MultiClassVisitor(new ClassVisitor[]
+ {
+ keepMarker,
+ new AllMemberVisitor(keepMarker)
+ })))));
+
+ // Attach some optimization info to all classes and class members, so
+ // it can be filled out later.
+ programClassPool.classesAccept(new ClassOptimizationInfoSetter());
+
+ programClassPool.classesAccept(new AllMemberVisitor(
+ new MemberOptimizationInfoSetter()));
+
+ if (configuration.assumeNoSideEffects != null)
+ {
+ // Create a visitor for marking methods that don't have any side effects.
+ NoSideEffectMethodMarker noSideEffectMethodMarker = new NoSideEffectMethodMarker();
+ ClassPoolVisitor noClassPoolvisitor =
+ ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.assumeNoSideEffects,
+ null,
+ noSideEffectMethodMarker);
+
+ // Mark the seeds.
+ programClassPool.accept(noClassPoolvisitor);
+ libraryClassPool.accept(noClassPoolvisitor);
+ }
+
+ if (classMarkingFinal)
+ {
+ // Make classes final, whereever possible.
+ programClassPool.classesAccept(
+ new ClassFinalizer(classMarkingFinalCounter));
+ }
+
+ if (methodMarkingFinal)
+ {
+ // Make methods final, whereever possible.
+ programClassPool.classesAccept(
+ new ClassAccessFilter(0, ClassConstants.ACC_INTERFACE,
+ new AllMethodVisitor(
+ new MethodFinalizer(methodMarkingFinalCounter))));
+ }
+
+ if (fieldRemovalWriteonly)
+ {
+ // Mark all fields that are write-only.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new AllInstructionVisitor(
+ new ReadWriteFieldMarker()))));
+
+ // Count the write-only fields.
+ programClassPool.classesAccept(
+ new AllFieldVisitor(
+ new WriteOnlyFieldFilter(fieldRemovalWriteonlyCounter)));
+ }
+ else
+ {
+ // Mark all fields as read/write.
+ programClassPool.classesAccept(
+ new AllFieldVisitor(
+ new ReadWriteFieldMarker()));
+ }
+
+ if (classUnboxingEnum)
+ {
+ ClassCounter counter = new ClassCounter();
+
+ // Mark all final enums that qualify as simple enums.
+ programClassPool.classesAccept(
+ new ClassAccessFilter(ClassConstants.ACC_FINAL |
+ ClassConstants.ACC_ENUM, 0,
+ new OptimizationInfoClassFilter(
+ new SimpleEnumClassChecker())));
+
+ // Count the preliminary number of simple enums.
+ programClassPool.classesAccept(
+ new SimpleEnumFilter(counter));
+
+ // Only continue checking simple enums if there are any candidates.
+ if (counter.getCount() > 0)
+ {
+ // Unmark all simple enums that are explicitly used as objects.
+ programClassPool.classesAccept(
+ new SimpleEnumUseChecker());
+
+ // Unmark all simple enums that are used in descriptors of
+ // kept class members. Changing their names could upset
+ // the name parameters of invokedynamic instructions.
+ programClassPool.classesAccept(
+ new SimpleEnumFilter(null,
+ new AllMemberVisitor(
+ new KeptMemberFilter(
+ new MemberDescriptorReferencedClassVisitor(
+ new OptimizationInfoClassFilter(
+ new SimpleEnumMarker(false)))))));
+
+ // Count the definitive number of simple enums.
+ programClassPool.classesAccept(
+ new SimpleEnumFilter(classUnboxingEnumCounter));
+
+ // Only start handling simple enums if there are any.
+ if (classUnboxingEnumCounter.getCount() > 0)
+ {
+ // Simplify the use of the enum classes in code.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new SimpleEnumUseSimplifier())));
+
+ // Simplify the static initializers of simple enum classes.
+ programClassPool.classesAccept(
+ new SimpleEnumFilter(
+ new SimpleEnumClassSimplifier()));
+
+ // Simplify the use of the enum classes in descriptors.
+ programClassPool.classesAccept(
+ new SimpleEnumDescriptorSimplifier());
+
+ // Update references to class members with simple enum classes.
+ programClassPool.classesAccept(new MemberReferenceFixer());
+ }
+ }
+ }
+
+ // Mark all used parameters, including the 'this' parameters.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new OptimizationInfoMemberFilter(
+ new ParameterUsageMarker(!methodMarkingStatic,
+ !methodRemovalParameter))));
+
+ // Mark all classes that have static initializers.
+ programClassPool.classesAccept(new StaticInitializerContainingClassMarker());
+
+ // Mark all methods that have side effects.
+ programClassPool.accept(new SideEffectMethodMarker());
+
+// System.out.println("Optimizer.execute: before evaluation simplification");
+// programClassPool.classAccept("abc/Def", new NamedMethodVisitor("abc", null, new ClassPrinter()));
+
+ // Perform partial evaluation for filling out fields, method parameters,
+ // and method return values, so they can be propagated.
+ if (fieldPropagationValue ||
+ methodPropagationParameter ||
+ methodPropagationReturnvalue)
+ {
+ // We'll create values to be stored with fields, method parameters,
+ // and return values.
+ ValueFactory valueFactory = new ParticularValueFactory();
+ ValueFactory detailedValueFactory = new DetailedValueFactory();
+
+ InvocationUnit storingInvocationUnit =
+ new StoringInvocationUnit(valueFactory,
+ fieldPropagationValue,
+ methodPropagationParameter,
+ methodPropagationReturnvalue);
+
+ // Evaluate synthetic classes in more detail, notably to propagate
+ // the arrays of the classes generated for enum switch statements.
+ programClassPool.classesAccept(
+ new ClassAccessFilter(ClassConstants.ACC_SYNTHETIC, 0,
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new PartialEvaluator(detailedValueFactory, storingInvocationUnit, false)))));
+
+ // Evaluate non-synthetic classes.
+ programClassPool.classesAccept(
+ new ClassAccessFilter(0, ClassConstants.ACC_SYNTHETIC,
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new PartialEvaluator(valueFactory, storingInvocationUnit, false)))));
+
+ if (fieldPropagationValue)
+ {
+ // Count the constant fields.
+ programClassPool.classesAccept(
+ new AllFieldVisitor(
+ new ConstantMemberFilter(fieldPropagationValueCounter)));
+ }
+
+ if (methodPropagationParameter)
+ {
+ // Count the constant method parameters.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new ConstantParameterFilter(methodPropagationParameterCounter)));
+ }
+
+ if (methodPropagationReturnvalue)
+ {
+ // Count the constant method return values.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new ConstantMemberFilter(methodPropagationReturnvalueCounter)));
+ }
+
+ if (classUnboxingEnumCounter.getCount() > 0)
+ {
+ // Propagate the simple enum constant counts.
+ programClassPool.classesAccept(
+ new SimpleEnumFilter(
+ new SimpleEnumArrayPropagator()));
+ }
+
+ if (codeSimplificationAdvanced)
+ {
+ // Fill out constants into the arrays of synthetic classes,
+ // notably the arrays of the classes generated for enum switch
+ // statements.
+ InvocationUnit loadingInvocationUnit =
+ new LoadingInvocationUnit(valueFactory,
+ fieldPropagationValue,
+ methodPropagationParameter,
+ methodPropagationReturnvalue);
+
+ programClassPool.classesAccept(
+ new ClassAccessFilter(ClassConstants.ACC_SYNTHETIC, 0,
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new PartialEvaluator(valueFactory, loadingInvocationUnit, false)))));
+ }
+ }
+
+ // Perform partial evaluation again, now loading any previously stored
+ // values for fields, method parameters, and method return values.
+ ValueFactory valueFactory = new IdentifiedValueFactory();
+
+ InvocationUnit loadingInvocationUnit =
+ new LoadingInvocationUnit(valueFactory,
+ fieldPropagationValue,
+ methodPropagationParameter,
+ methodPropagationReturnvalue);
+
+ if (codeSimplificationAdvanced)
+ {
+ // Simplify based on partial evaluation, propagating constant
+ // field values, method parameter values, and return values.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new EvaluationSimplifier(
+ new PartialEvaluator(valueFactory, loadingInvocationUnit, false),
+ codeSimplificationAdvancedCounter))));
+ }
+
+ if (codeRemovalAdvanced)
+ {
+ // Remove code based on partial evaluation, also removing unused
+ // parameters from method invocations, and making methods static
+ // if possible.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new EvaluationShrinker(
+ new PartialEvaluator(valueFactory, loadingInvocationUnit, !codeSimplificationAdvanced),
+ deletedCounter, addedCounter))));
+ }
+
+ if (methodRemovalParameter)
+ {
+ // Shrink the parameters in the method descriptors.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new OptimizationInfoMemberFilter(
+ new MethodDescriptorShrinker())));
+ }
+
+ if (methodMarkingStatic)
+ {
+ // Make all non-static methods that don't require the 'this'
+ // parameter static.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new OptimizationInfoMemberFilter(
+ new MemberAccessFilter(0, ClassConstants.ACC_STATIC,
+ new MethodStaticizer(methodMarkingStaticCounter)))));
+ }
+
+ if (methodRemovalParameter)
+ {
+ // Fix all references to class members.
+ // This operation also updates the stack sizes.
+ programClassPool.classesAccept(
+ new MemberReferenceFixer());
+
+ // Remove unused bootstrap method arguments.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(
+ new AllBootstrapMethodInfoVisitor(
+ new BootstrapMethodArgumentShrinker())));
+ }
+
+ if (methodRemovalParameter ||
+ methodMarkingPrivate ||
+ methodMarkingStatic)
+ {
+ // Remove all unused parameters from the byte code, shifting all
+ // remaining variables.
+ // This operation also updates the local variable frame sizes.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new ParameterShrinker(methodRemovalParameterCounter))));
+ }
+ else if (codeRemovalAdvanced)
+ {
+ // Just update the local variable frame sizes.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new StackSizeUpdater())));
+ }
+
+ if (methodRemovalParameter &&
+ methodRemovalParameterCounter.getCount() > 0)
+ {
+ // Tweak the descriptors of duplicate initializers, due to removed
+ // method parameters.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new DuplicateInitializerFixer(initializerFixCounter1)));
+
+ if (initializerFixCounter1.getCount() > 0)
+ {
+ // Fix all invocations of tweaked initializers.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new DuplicateInitializerInvocationFixer(addedCounter))));
+
+ // Fix all references to tweaked initializers.
+ programClassPool.classesAccept(new MemberReferenceFixer());
+ }
+ }
+
+ //// Specializing the class member descriptors seems to increase the
+ //// class file size, on average.
+ //// Specialize all class member descriptors.
+ //programClassPool.classesAccept(new AllMemberVisitor(
+ // new OptimizationInfoMemberFilter(
+ // new MemberDescriptorSpecializer())));
+ //
+ //// Fix all references to classes, for MemberDescriptorSpecializer.
+ //programClassPool.classesAccept(new AllMemberVisitor(
+ // new OptimizationInfoMemberFilter(
+ // new ClassReferenceFixer(true))));
+
+ // Mark all classes with package visible members.
+ // Mark all exception catches of methods.
+ // Count all method invocations.
+ // Mark super invocations and other access of methods.
+ StackSizeComputer stackSizeComputer = new StackSizeComputer();
+
+ programClassPool.classesAccept(
+ new MultiClassVisitor(
+ new ClassVisitor[]
+ {
+ // Mark classes.
+ new PackageVisibleMemberContainingClassMarker(),
+ new AllConstantVisitor(
+ new PackageVisibleMemberInvokingClassMarker()),
+
+ // Mark methods.
+ new AllMethodVisitor(
+ new OptimizationInfoMemberFilter(
+ new AllAttributeVisitor(
+ new MultiAttributeVisitor(
+ new AttributeVisitor[]
+ {
+ stackSizeComputer,
+ new CatchExceptionMarker(),
+ new AllInstructionVisitor(
+ new MultiInstructionVisitor(
+ new InstructionVisitor[]
+ {
+ new SuperInvocationMarker(),
+ new DynamicInvocationMarker(),
+ new BackwardBranchMarker(),
+ new AccessMethodMarker(),
+ new NonEmptyStackReturnMarker(stackSizeComputer),
+ })),
+ })))),
+
+ // Mark referenced classes and methods.
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new MultiAttributeVisitor(
+ new AttributeVisitor[]
+ {
+ new AllExceptionInfoVisitor(
+ new ExceptionHandlerConstantVisitor(
+ new ReferencedClassVisitor(
+ new CaughtClassMarker()))),
+
+ new AllInstructionVisitor(
+ new MultiInstructionVisitor(
+ new InstructionVisitor[]
+ {
+ new InstantiationClassMarker(),
+ new InstanceofClassMarker(),
+ new DotClassMarker(),
+ new MethodInvocationMarker()
+ })),
+ })))
+ }));
+
+ if (classMergingVertical)
+ {
+ // Merge subclasses up into their superclasses or
+ // merge interfaces down into their implementing classes.
+ programClassPool.classesAccept(
+ new VerticalClassMerger(configuration.allowAccessModification,
+ configuration.mergeInterfacesAggressively,
+ classMergingVerticalCounter));
+ }
+
+ if (classMergingHorizontal)
+ {
+ // Merge classes into their sibling classes.
+ programClassPool.classesAccept(
+ new HorizontalClassMerger(configuration.allowAccessModification,
+ configuration.mergeInterfacesAggressively,
+ classMergingHorizontalCounter));
+ }
+
+ if (classMergingVerticalCounter .getCount() > 0 ||
+ classMergingHorizontalCounter.getCount() > 0)
+ {
+ // Clean up inner class attributes to avoid loops.
+ programClassPool.classesAccept(new RetargetedInnerClassAttributeRemover());
+
+ // Update references to merged classes: first the referenced
+ // classes, then the various actual descriptors.
+ // Leave retargeted classes themselves unchanged and valid,
+ // in case they aren't shrunk later on.
+ programClassPool.classesAccept(new RetargetedClassFilter(null, new TargetClassChanger()));
+ programClassPool.classesAccept(new RetargetedClassFilter(null, new ClassReferenceFixer(true)));
+ programClassPool.classesAccept(new RetargetedClassFilter(null, new MemberReferenceFixer()));
+
+ if (configuration.allowAccessModification)
+ {
+ // Fix the access flags of referenced merged classes and their
+ // class members.
+ programClassPool.classesAccept(
+ new AccessFixer());
+ }
+
+ // Fix the access flags of the inner classes information.
+ programClassPool.classesAccept(
+ new AllAttributeVisitor(
+ new AllInnerClassesInfoVisitor(
+ new InnerClassesAccessFixer())));
+
+ // Tweak the descriptors of duplicate initializers, due to merged
+ // parameter classes.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new DuplicateInitializerFixer(initializerFixCounter2)));
+
+ if (initializerFixCounter2.getCount() > 0)
+ {
+ // Fix all invocations of tweaked initializers.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new DuplicateInitializerInvocationFixer(addedCounter))));
+
+ // Fix all references to tweaked initializers.
+ programClassPool.classesAccept(new MemberReferenceFixer());
+ }
+ }
+
+ if (methodInliningUnique)
+ {
+ // Inline methods that are only invoked once.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new MethodInliner(configuration.microEdition,
+ configuration.allowAccessModification,
+ true,
+ methodInliningUniqueCounter))));
+ }
+
+ if (methodInliningShort)
+ {
+ // Inline short methods.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new MethodInliner(configuration.microEdition,
+ configuration.allowAccessModification,
+ false,
+ methodInliningShortCounter))));
+ }
+
+ if (methodInliningTailrecursion)
+ {
+ // Simplify tail recursion calls.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new TailRecursionSimplifier(methodInliningTailrecursionCounter))));
+ }
+
+ if (fieldMarkingPrivate ||
+ methodMarkingPrivate)
+ {
+ // Mark all class members that can not be made private.
+ programClassPool.classesAccept(
+ new NonPrivateMemberMarker());
+ }
+
+ if (fieldMarkingPrivate)
+ {
+ // Make all non-private fields private, whereever possible.
+ programClassPool.classesAccept(
+ new ClassAccessFilter(0, ClassConstants.ACC_INTERFACE,
+ new AllFieldVisitor(
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE,
+ new MemberPrivatizer(fieldMarkingPrivateCounter)))));
+ }
+
+ if (methodMarkingPrivate)
+ {
+ // Make all non-private methods private, whereever possible.
+ programClassPool.classesAccept(
+ new ClassAccessFilter(0, ClassConstants.ACC_INTERFACE,
+ new AllMethodVisitor(
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE,
+ new MemberPrivatizer(methodMarkingPrivateCounter)))));
+ }
+
+ if ((methodInliningUniqueCounter .getCount() > 0 ||
+ methodInliningShortCounter .getCount() > 0 ||
+ methodInliningTailrecursionCounter.getCount() > 0) &&
+ configuration.allowAccessModification)
+ {
+ // Fix the access flags of referenced classes and class members,
+ // for MethodInliner.
+ programClassPool.classesAccept(
+ new AccessFixer());
+ }
+
+ if (methodRemovalParameterCounter.getCount() > 0 ||
+ classMergingVerticalCounter .getCount() > 0 ||
+ classMergingHorizontalCounter.getCount() > 0 ||
+ methodMarkingPrivateCounter .getCount() > 0 ||
+ methodInliningUniqueCounter .getCount() > 0 ||
+ methodInliningShortCounter .getCount() > 0)
+ {
+ // Fix invocations of interface methods, of methods that have become
+ // non-abstract or private, and of methods that have moved to a
+ // different package.
+ programClassPool.classesAccept(
+ new AllMemberVisitor(
+ new AllAttributeVisitor(
+ new MethodInvocationFixer())));
+ }
+
+ if (codeMerging)
+ {
+ // Share common blocks of code at branches.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new GotoCommonCodeReplacer(codeMergingCounter))));
+ }
+
+ // Create a branch target marker and a code attribute editor that can
+ // be reused for all code attributes.
+ BranchTargetFinder branchTargetFinder = new BranchTargetFinder();
+ CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
+
+ InstructionSequenceConstants sequences =
+ new InstructionSequenceConstants(programClassPool,
+ libraryClassPool);
+
+ List peepholeOptimizations = new ArrayList();
+ if (codeSimplificationVariable)
+ {
+ // Peephole optimizations involving local variables.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(sequences.CONSTANTS,
+ sequences.VARIABLE,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationVariableCounter));
+ }
+
+ if (codeSimplificationArithmetic)
+ {
+ // Peephole optimizations involving arithmetic operations.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(sequences.CONSTANTS,
+ sequences.ARITHMETIC,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationArithmeticCounter));
+ }
+
+ if (codeSimplificationCast)
+ {
+ // Peephole optimizations involving cast operations.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(sequences.CONSTANTS,
+ sequences.CAST,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationCastCounter));
+ }
+
+ if (codeSimplificationField)
+ {
+ // Peephole optimizations involving fields.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(sequences.CONSTANTS,
+ sequences.FIELD,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationFieldCounter));
+ }
+
+ if (codeSimplificationBranch)
+ {
+ // Peephole optimizations involving branches.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(sequences.CONSTANTS,
+ sequences.BRANCH,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationBranchCounter));
+
+ // Include optimization of branches to branches and returns.
+ peepholeOptimizations.add(
+ new GotoGotoReplacer(codeAttributeEditor, codeSimplificationBranchCounter));
+ peepholeOptimizations.add(
+ new GotoReturnReplacer(codeAttributeEditor, codeSimplificationBranchCounter));
+ }
+
+ if (codeSimplificationString)
+ {
+ // Peephole optimizations involving branches.
+ peepholeOptimizations.add(
+ new InstructionSequencesReplacer(sequences.CONSTANTS,
+ sequences.STRING,
+ branchTargetFinder, codeAttributeEditor, codeSimplificationStringCounter));
+ }
+
+ if (!peepholeOptimizations.isEmpty())
+ {
+ // Convert the list into an array.
+ InstructionVisitor[] peepholeOptimizationsArray =
+ new InstructionVisitor[peepholeOptimizations.size()];
+ peepholeOptimizations.toArray(peepholeOptimizationsArray);
+
+ // Perform the peephole optimisations.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new PeepholeOptimizer(branchTargetFinder, codeAttributeEditor,
+ new MultiInstructionVisitor(
+ peepholeOptimizationsArray)))));
+ }
+
+ if (codeRemovalException)
+ {
+ // Remove unnecessary exception handlers.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new UnreachableExceptionRemover(codeRemovalExceptionCounter))));
+ }
+
+ if (codeRemovalSimple)
+ {
+ // Remove unreachable code.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new UnreachableCodeRemover(deletedCounter))));
+ }
+
+ if (codeRemovalVariable)
+ {
+ // Remove all unused local variables.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new VariableShrinker(codeRemovalVariableCounter))));
+ }
+
+ if (codeAllocationVariable)
+ {
+ // Optimize the variables.
+ programClassPool.classesAccept(
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new VariableOptimizer(false, codeAllocationVariableCounter))));
+ }
+
+
+ // Remove unused constants.
+ programClassPool.classesAccept(
+ new ConstantPoolShrinker());
+
+ int classMarkingFinalCount = classMarkingFinalCounter .getCount();
+ int classUnboxingEnumCount = classUnboxingEnumCounter .getCount();
+ int classMergingVerticalCount = classMergingVerticalCounter .getCount();
+ int classMergingHorizontalCount = classMergingHorizontalCounter .getCount();
+ int fieldRemovalWriteonlyCount = fieldRemovalWriteonlyCounter .getCount();
+ int fieldMarkingPrivateCount = fieldMarkingPrivateCounter .getCount();
+ int fieldPropagationValueCount = fieldPropagationValueCounter .getCount();
+ int methodMarkingPrivateCount = methodMarkingPrivateCounter .getCount();
+ int methodMarkingStaticCount = methodMarkingStaticCounter .getCount();
+ int methodMarkingFinalCount = methodMarkingFinalCounter .getCount();
+ int methodRemovalParameterCount = methodRemovalParameterCounter .getCount() - methodMarkingStaticCounter.getCount() - initializerFixCounter1.getCount() - initializerFixCounter2.getCount();
+ int methodPropagationParameterCount = methodPropagationParameterCounter .getCount();
+ int methodPropagationReturnvalueCount = methodPropagationReturnvalueCounter.getCount();
+ int methodInliningShortCount = methodInliningShortCounter .getCount();
+ int methodInliningUniqueCount = methodInliningUniqueCounter .getCount();
+ int methodInliningTailrecursionCount = methodInliningTailrecursionCounter .getCount();
+ int codeMergingCount = codeMergingCounter .getCount();
+ int codeSimplificationVariableCount = codeSimplificationVariableCounter .getCount();
+ int codeSimplificationArithmeticCount = codeSimplificationArithmeticCounter.getCount();
+ int codeSimplificationCastCount = codeSimplificationCastCounter .getCount();
+ int codeSimplificationFieldCount = codeSimplificationFieldCounter .getCount();
+ int codeSimplificationBranchCount = codeSimplificationBranchCounter .getCount();
+ int codeSimplificationStringCount = codeSimplificationStringCounter .getCount();
+ int codeSimplificationAdvancedCount = codeSimplificationAdvancedCounter .getCount();
+ int codeRemovalCount = deletedCounter .getCount() - addedCounter.getCount();
+ int codeRemovalVariableCount = codeRemovalVariableCounter .getCount();
+ int codeRemovalExceptionCount = codeRemovalExceptionCounter .getCount();
+ int codeAllocationVariableCount = codeAllocationVariableCounter .getCount();
+
+ // Forget about constant fields, parameters, and return values, if they
+ // didn't lead to any useful optimizations. We want to avoid fruitless
+ // additional optimization passes.
+ if (codeSimplificationAdvancedCount == 0)
+ {
+ fieldPropagationValueCount = 0;
+ methodPropagationParameterCount = 0;
+ methodPropagationReturnvalueCount = 0;
+ }
+
+ if (configuration.verbose)
+ {
+ System.out.println(" Number of finalized classes: " + classMarkingFinalCount + disabled(classMarkingFinal));
+ System.out.println(" Number of unboxed enum classes: " + classUnboxingEnumCount + disabled(classUnboxingEnum));
+ System.out.println(" Number of vertically merged classes: " + classMergingVerticalCount + disabled(classMergingVertical));
+ System.out.println(" Number of horizontally merged classes: " + classMergingHorizontalCount + disabled(classMergingHorizontal));
+ System.out.println(" Number of removed write-only fields: " + fieldRemovalWriteonlyCount + disabled(fieldRemovalWriteonly));
+ System.out.println(" Number of privatized fields: " + fieldMarkingPrivateCount + disabled(fieldMarkingPrivate));
+ System.out.println(" Number of inlined constant fields: " + fieldPropagationValueCount + disabled(fieldPropagationValue));
+ System.out.println(" Number of privatized methods: " + methodMarkingPrivateCount + disabled(methodMarkingPrivate));
+ System.out.println(" Number of staticized methods: " + methodMarkingStaticCount + disabled(methodMarkingStatic));
+ System.out.println(" Number of finalized methods: " + methodMarkingFinalCount + disabled(methodMarkingFinal));
+ System.out.println(" Number of removed method parameters: " + methodRemovalParameterCount + disabled(methodRemovalParameter));
+ System.out.println(" Number of inlined constant parameters: " + methodPropagationParameterCount + disabled(methodPropagationParameter));
+ System.out.println(" Number of inlined constant return values: " + methodPropagationReturnvalueCount + disabled(methodPropagationReturnvalue));
+ System.out.println(" Number of inlined short method calls: " + methodInliningShortCount + disabled(methodInliningShort));
+ System.out.println(" Number of inlined unique method calls: " + methodInliningUniqueCount + disabled(methodInliningUnique));
+ System.out.println(" Number of inlined tail recursion calls: " + methodInliningTailrecursionCount + disabled(methodInliningTailrecursion));
+ System.out.println(" Number of merged code blocks: " + codeMergingCount + disabled(codeMerging));
+ System.out.println(" Number of variable peephole optimizations: " + codeSimplificationVariableCount + disabled(codeSimplificationVariable));
+ System.out.println(" Number of arithmetic peephole optimizations: " + codeSimplificationArithmeticCount + disabled(codeSimplificationArithmetic));
+ System.out.println(" Number of cast peephole optimizations: " + codeSimplificationCastCount + disabled(codeSimplificationCast));
+ System.out.println(" Number of field peephole optimizations: " + codeSimplificationFieldCount + disabled(codeSimplificationField));
+ System.out.println(" Number of branch peephole optimizations: " + codeSimplificationBranchCount + disabled(codeSimplificationBranch));
+ System.out.println(" Number of string peephole optimizations: " + codeSimplificationStringCount + disabled(codeSimplificationString));
+ System.out.println(" Number of simplified instructions: " + codeSimplificationAdvancedCount + disabled(codeSimplificationAdvanced));
+ System.out.println(" Number of removed instructions: " + codeRemovalCount + disabled(codeRemovalAdvanced));
+ System.out.println(" Number of removed local variables: " + codeRemovalVariableCount + disabled(codeRemovalVariable));
+ System.out.println(" Number of removed exception blocks: " + codeRemovalExceptionCount + disabled(codeRemovalException));
+ System.out.println(" Number of optimized local variable frames: " + codeAllocationVariableCount + disabled(codeAllocationVariable));
+ }
+
+ return classMarkingFinalCount > 0 ||
+ classUnboxingEnumCount > 0 ||
+ classMergingVerticalCount > 0 ||
+ classMergingHorizontalCount > 0 ||
+ fieldRemovalWriteonlyCount > 0 ||
+ fieldMarkingPrivateCount > 0 ||
+ methodMarkingPrivateCount > 0 ||
+ methodMarkingStaticCount > 0 ||
+ methodMarkingFinalCount > 0 ||
+ fieldPropagationValueCount > 0 ||
+ methodRemovalParameterCount > 0 ||
+ methodPropagationParameterCount > 0 ||
+ methodPropagationReturnvalueCount > 0 ||
+ methodInliningShortCount > 0 ||
+ methodInliningUniqueCount > 0 ||
+ methodInliningTailrecursionCount > 0 ||
+ codeMergingCount > 0 ||
+ codeSimplificationVariableCount > 0 ||
+ codeSimplificationArithmeticCount > 0 ||
+ codeSimplificationCastCount > 0 ||
+ codeSimplificationFieldCount > 0 ||
+ codeSimplificationBranchCount > 0 ||
+ codeSimplificationStringCount > 0 ||
+ codeSimplificationAdvancedCount > 0 ||
+ codeRemovalCount > 0 ||
+ codeRemovalVariableCount > 0 ||
+ codeRemovalExceptionCount > 0 ||
+ codeAllocationVariableCount > 0;
+ }
+
+
+ /**
+ * Returns a String indicating whether the given flag is enabled or
+ * disabled.
+ */
+ private String disabled(boolean flag)
+ {
+ return flag ? "" : " (disabled)";
+ }
+
+
+ /**
+ * Returns a String indicating whether the given flags are enabled or
+ * disabled.
+ */
+ private String disabled(boolean flag1, boolean flag2)
+ {
+ return flag1 && flag2 ? "" :
+ flag1 || flag2 ? " (partially disabled)" :
+ " (disabled)";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ParameterShrinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ParameterShrinker.java
new file mode 100644
index 0000000000..8d6ff621f0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/ParameterShrinker.java
@@ -0,0 +1,150 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.VariableRemapper;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.info.ParameterUsageMarker;
+
+/**
+ * This AttributeVisitor removes unused parameters from the code of the methods
+ * that it visits.
+ *
+ * @see ParameterUsageMarker
+ * @see MethodStaticizer
+ * @see MethodDescriptorShrinker
+ * @author Eric Lafortune
+ */
+public class ParameterShrinker
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("ps") != null;
+ //*/
+
+
+ private final MemberVisitor extraVariableMemberVisitor;
+
+ private final VariableRemapper variableRemapper = new VariableRemapper();
+
+
+ /**
+ * Creates a new ParameterShrinker.
+ */
+ public ParameterShrinker()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new ParameterShrinker with an extra visitor.
+ * @param extraVariableMemberVisitor an optional extra visitor for all
+ * removed parameters.
+ */
+ public ParameterShrinker(MemberVisitor extraVariableMemberVisitor)
+ {
+ this.extraVariableMemberVisitor = extraVariableMemberVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Get the original parameter size that was saved.
+ int oldParameterSize = ParameterUsageMarker.getParameterSize(method);
+
+ // Compute the new parameter size from the shrunk descriptor.
+ int newParameterSize =
+ ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz),
+ method.getAccessFlags());
+
+ if (oldParameterSize > newParameterSize)
+ {
+ // Get the total size of the local variable frame.
+ int maxLocals = codeAttribute.u2maxLocals;
+
+ if (DEBUG)
+ {
+ System.out.println("ParameterShrinker: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ System.out.println(" Old parameter size = " + oldParameterSize);
+ System.out.println(" New parameter size = " + newParameterSize);
+ System.out.println(" Max locals = " + maxLocals);
+ }
+
+ // Create a variable map.
+ int[] variableMap = new int[maxLocals];
+
+ // Move unused parameters right after the parameter block.
+ int usedParameterIndex = 0;
+ int unusedParameterIndex = newParameterSize;
+ for (int parameterIndex = 0; parameterIndex < oldParameterSize; parameterIndex++)
+ {
+ // Is the variable required as a parameter?
+ if (ParameterUsageMarker.isParameterUsed(method, parameterIndex))
+ {
+ // Keep the variable as a parameter.
+ variableMap[parameterIndex] = usedParameterIndex++;
+ }
+ else
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Deleting parameter #"+parameterIndex);
+ }
+
+ // Shift the variable to the unused parameter block,
+ // in case it is still used as a variable.
+ variableMap[parameterIndex] = unusedParameterIndex++;
+
+ // Visit the method, if required.
+ if (extraVariableMemberVisitor != null)
+ {
+ method.accept(clazz, extraVariableMemberVisitor);
+ }
+ }
+ }
+
+ // Fill out the remainder of the map.
+ for (int variableIndex = oldParameterSize; variableIndex < maxLocals; variableIndex++)
+ {
+ variableMap[variableIndex] = variableIndex;
+ }
+
+ // Set the map.
+ variableRemapper.setVariableMap(variableMap);
+
+ // Remap the variables.
+ variableRemapper.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/TailRecursionSimplifier.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/TailRecursionSimplifier.java
new file mode 100644
index 0000000000..3e664b3dfc
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/TailRecursionSimplifier.java
@@ -0,0 +1,355 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.CodeAttributeComposer;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+
+/**
+ * This MemberVisitor simplifies tail recursion calls in all methods that it
+ * visits.
+ *
+ * @author Eric Lafortune
+ */
+public class TailRecursionSimplifier
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ConstantVisitor,
+ ExceptionInfoVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = true;
+ //*/
+
+
+ private final InstructionVisitor extraTailRecursionVisitor;
+
+
+ private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
+ private final MyRecursionChecker recursionChecker = new MyRecursionChecker();
+
+ private Method targetMethod;
+ private boolean inlinedAny;
+
+
+
+ /**
+ * Creates a new TailRecursionSimplifier.
+ */
+ public TailRecursionSimplifier()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new TailRecursionSimplifier with an extra visitor.
+ * @param extraTailRecursionVisitor an optional extra visitor for all
+ * simplified tail recursions.
+ */
+ public TailRecursionSimplifier(InstructionVisitor extraTailRecursionVisitor)
+ {
+ this.extraTailRecursionVisitor = extraTailRecursionVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ int accessFlags = method.getAccessFlags();
+
+ if (// Only check the method if it is private, static, or final.
+ (accessFlags & (ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC |
+ ClassConstants.ACC_FINAL)) != 0 &&
+
+ // Only check the method if it is not synchronized, etc.
+ (accessFlags & (ClassConstants.ACC_SYNCHRONIZED |
+ ClassConstants.ACC_NATIVE |
+ ClassConstants.ACC_ABSTRACT)) == 0)
+ {
+// codeAttributeComposer.DEBUG = DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ targetMethod = method;
+ inlinedAny = false;
+ codeAttributeComposer.reset();
+
+ // The code may expand, due to expanding constant and variable
+ // instructions.
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
+
+ // Copy the instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
+
+ // Update the code attribute if any code has been inlined.
+ if (inlinedAny)
+ {
+ // Copy the exceptions.
+ codeAttribute.exceptionsAccept(clazz, method, this);
+
+ // Append a label just after the code.
+ codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
+
+ codeAttributeComposer.endCodeFragment();
+
+ codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ // Copy the instruction.
+ codeAttributeComposer.appendInstruction(offset, instruction);
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ // Is it a method invocation?
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ {
+ // Is it a recursive call?
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, recursionChecker);
+
+ if (recursionChecker.isRecursive())
+ {
+ // Is the next instruction a return?
+ int nextOffset =
+ offset + constantInstruction.length(offset);
+
+ Instruction nextInstruction =
+ InstructionFactory.create(codeAttribute.code, nextOffset);
+
+ switch (nextInstruction.opcode)
+ {
+ case InstructionConstants.OP_IRETURN:
+ case InstructionConstants.OP_LRETURN:
+ case InstructionConstants.OP_FRETURN:
+ case InstructionConstants.OP_DRETURN:
+ case InstructionConstants.OP_ARETURN:
+ case InstructionConstants.OP_RETURN:
+ {
+ // Isn't the recursive call inside a try/catch block?
+ codeAttribute.exceptionsAccept(clazz, method, offset, recursionChecker);
+
+ if (recursionChecker.isRecursive())
+ {
+ if (DEBUG)
+ {
+ System.out.println("TailRecursionSimplifier: ["+
+ clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"], inlining "+constantInstruction.toString(offset));
+ }
+
+ // Append a label.
+ codeAttributeComposer.appendLabel(offset);
+
+ storeParameters(clazz, method);
+
+ // Branch back to the start of the method.
+ int gotoOffset = offset + 1;
+ codeAttributeComposer.appendInstruction(gotoOffset,
+ new BranchInstruction(InstructionConstants.OP_GOTO, -gotoOffset));
+
+ // The original return instruction will be
+ // removed elsewhere, if possible.
+
+ // Remember that the code has changed.
+ inlinedAny = true;
+
+ if (extraTailRecursionVisitor != null)
+ {
+ extraTailRecursionVisitor.visitConstantInstruction(clazz, method, codeAttribute, offset, constantInstruction);
+ }
+
+ // The invocation itself is no longer necessary.
+ return;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ }
+
+ // Copy the instruction.
+ codeAttributeComposer.appendInstruction(offset, constantInstruction);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ codeAttributeComposer.appendException(new ExceptionInfo(exceptionInfo.u2startPC,
+ exceptionInfo.u2endPC,
+ exceptionInfo.u2handlerPC,
+ exceptionInfo.u2catchType));
+ }
+
+
+ /**
+ * This ConstantVisitor and ExceptionInfoVisitor returns whether a method
+ * invocation can be treated as tail-recursive.
+ */
+ private class MyRecursionChecker
+ extends SimplifiedVisitor
+ implements ConstantVisitor,
+ ExceptionInfoVisitor
+ {
+ private boolean recursive;
+
+
+ /**
+ * Returns whether the method invocation can be treated as
+ * tail-recursive.
+ */
+ public boolean isRecursive()
+ {
+ return recursive;
+ }
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant methodrefConstant)
+ {
+ recursive = targetMethod.equals(methodrefConstant.referencedMember);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ recursive = false;
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Appends instructions to pop the parameters for the given method, storing
+ * them in new local variables.
+ */
+ private void storeParameters(Clazz clazz, Method method)
+ {
+ String descriptor = method.getDescriptor(clazz);
+
+ boolean isStatic =
+ (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0;
+
+ // Count the number of parameters, taking into account their categories.
+ int parameterSize = ClassUtil.internalMethodParameterSize(descriptor);
+ int parameterOffset = isStatic ? 0 : 1;
+
+ // Store the parameter types.
+ String[] parameterTypes = new String[parameterSize];
+
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(descriptor);
+
+ for (int parameterIndex = 0; parameterIndex < parameterSize; parameterIndex++)
+ {
+ String parameterType = internalTypeEnumeration.nextType();
+ parameterTypes[parameterIndex] = parameterType;
+ if (ClassUtil.internalTypeSize(parameterType) == 2)
+ {
+ parameterIndex++;
+ }
+ }
+
+ codeAttributeComposer.beginCodeFragment(parameterSize + 1);
+
+ // Go over the parameter types backward, storing the stack entries
+ // in their corresponding variables.
+ for (int parameterIndex = parameterSize-1; parameterIndex >= 0; parameterIndex--)
+ {
+ String parameterType = parameterTypes[parameterIndex];
+ if (parameterType != null)
+ {
+ byte opcode;
+ switch (parameterType.charAt(0))
+ {
+ case ClassConstants.TYPE_BOOLEAN:
+ case ClassConstants.TYPE_BYTE:
+ case ClassConstants.TYPE_CHAR:
+ case ClassConstants.TYPE_SHORT:
+ case ClassConstants.TYPE_INT:
+ opcode = InstructionConstants.OP_ISTORE;
+ break;
+
+ case ClassConstants.TYPE_LONG:
+ opcode = InstructionConstants.OP_LSTORE;
+ break;
+
+ case ClassConstants.TYPE_FLOAT:
+ opcode = InstructionConstants.OP_FSTORE;
+ break;
+
+ case ClassConstants.TYPE_DOUBLE:
+ opcode = InstructionConstants.OP_DSTORE;
+ break;
+
+ default:
+ opcode = InstructionConstants.OP_ASTORE;
+ break;
+ }
+
+ codeAttributeComposer.appendInstruction(parameterSize-parameterIndex-1,
+ new VariableInstruction(opcode, parameterOffset + parameterIndex));
+ }
+ }
+
+ // Put the 'this' reference in variable 0.
+ if (!isStatic)
+ {
+ codeAttributeComposer.appendInstruction(parameterSize,
+ new VariableInstruction(InstructionConstants.OP_ASTORE, 0));
+ }
+
+ codeAttributeComposer.endCodeFragment();
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/WriteOnlyFieldFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/WriteOnlyFieldFilter.java
new file mode 100644
index 0000000000..b6c00b9d8d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/WriteOnlyFieldFilter.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.info.ReadWriteFieldMarker;
+
+/**
+ * This <code>MemberVisitor</code> delegates its visits to program fields to
+ * other given <code>MemberVisitor</code> instances, but only when the visited
+ * field has been marked as write-only.
+ *
+ * @see ReadWriteFieldMarker
+ * @author Eric Lafortune
+ */
+public class WriteOnlyFieldFilter
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final MemberVisitor writeOnlyFieldVisitor;
+
+
+ /**
+ * Creates a new WriteOnlyFieldFilter.
+ * @param writeOnlyFieldVisitor the <code>MemberVisitor</code> to which
+ * visits to write-only fields will be delegated.
+ */
+ public WriteOnlyFieldFilter(MemberVisitor writeOnlyFieldVisitor)
+ {
+ this.writeOnlyFieldVisitor = writeOnlyFieldVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+
+ if (ReadWriteFieldMarker.isWritten(programField) &&
+ !ReadWriteFieldMarker.isRead(programField))
+ {
+ writeOnlyFieldVisitor.visitProgramField(programClass, programField);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/EvaluationShrinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/EvaluationShrinker.java
new file mode 100644
index 0000000000..c54b37c469
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/EvaluationShrinker.java
@@ -0,0 +1,2370 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.RefConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+import proguard.evaluation.TracedStack;
+import proguard.evaluation.value.*;
+import proguard.optimize.info.*;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor simplifies the code attributes that it visits, based
+ * on partial evaluation.
+ *
+ * @author Eric Lafortune
+ */
+public class EvaluationShrinker
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ ExceptionInfoVisitor
+{
+ //*
+ private static final boolean DEBUG_RESULTS = false;
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("es") != null;
+ private static boolean DEBUG_RESULTS = DEBUG;
+ //*/
+
+ private static final int UNSUPPORTED = -1;
+ private static final int NOP = InstructionConstants.OP_NOP & 0xff;
+ private static final int POP = InstructionConstants.OP_POP & 0xff;
+ private static final int POP2 = InstructionConstants.OP_POP2 & 0xff;
+ private static final int DUP = InstructionConstants.OP_DUP & 0xff;
+ private static final int DUP_X1 = InstructionConstants.OP_DUP_X1 & 0xff;
+ private static final int DUP_X2 = InstructionConstants.OP_DUP_X2 & 0xff;
+ private static final int DUP2 = InstructionConstants.OP_DUP2 & 0xff;
+ private static final int DUP2_X1 = InstructionConstants.OP_DUP2_X1 & 0xff;
+ private static final int DUP2_X2 = InstructionConstants.OP_DUP2_X2 & 0xff;
+ private static final int SWAP = InstructionConstants.OP_SWAP & 0xff;
+ private static final int MOV_X2 = DUP_X2 | (POP << 8);
+ private static final int MOV2_X1 = DUP2_X1 | (POP2 << 8);
+ private static final int MOV2_X2 = DUP2_X2 | (POP2 << 8);
+ private static final int POP_X1 = SWAP | (POP << 8);
+ private static final int POP_X2 = DUP2_X1 | (POP2 << 8) | (POP << 16);
+ private static final int POP_X3 = UNSUPPORTED;
+ private static final int POP2_X1 = DUP_X2 | (POP << 8) | (POP2 << 16);
+ private static final int POP2_X2 = DUP2_X2 | (POP2 << 8) | (POP2 << 16);
+ private static final int POP3 = POP2 | (POP << 8);
+ private static final int POP4 = POP2 | (POP2 << 8);
+ private static final int POP_DUP = POP | (DUP << 8);
+ private static final int POP_SWAP_POP = POP | (SWAP << 8) | (POP << 16);
+ private static final int POP2_SWAP_POP = POP2 | (SWAP << 8) | (POP << 16);
+ private static final int SWAP_DUP_X1 = SWAP | (DUP_X1 << 8);
+ private static final int SWAP_DUP_X1_SWAP = SWAP | (DUP_X1 << 8) | (SWAP << 16);
+ private static final int SWAP_POP_DUP = SWAP | (POP << 8) | (DUP << 16);
+ private static final int SWAP_POP_DUP_X1 = SWAP | (POP << 8) | (DUP_X1 << 16);
+ private static final int DUP_X2_POP2 = DUP_X2 | (POP2 << 8);
+ private static final int DUP2_X1_POP3 = DUP2_X1 | (POP2 << 8) | (POP << 16);
+ private static final int DUP2_X2_POP3 = DUP2_X2 | (POP2 << 8) | (POP << 16);
+ private static final int DUP2_X2_SWAP_POP = DUP2_X2 | (SWAP << 8) | (POP << 16);
+
+
+ private final InstructionVisitor extraDeletedInstructionVisitor;
+ private final InstructionVisitor extraAddedInstructionVisitor;
+
+ private final PartialEvaluator partialEvaluator;
+ private final PartialEvaluator simplePartialEvaluator = new PartialEvaluator();
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true, true);
+ private final MyUnusedParameterSimplifier unusedParameterSimplifier = new MyUnusedParameterSimplifier();
+ private final MyProducerMarker producerMarker = new MyProducerMarker();
+ private final MyVariableInitializationMarker variableInitializationMarker = new MyVariableInitializationMarker();
+ private final MyLocalStackConsistencyFixer localStackConsistencyFixer = new MyLocalStackConsistencyFixer();
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false, false);
+
+ private boolean[][] stacksNecessaryAfter = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
+ private boolean[][] stacksSimplifiedBefore = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
+ private boolean[] instructionsNecessary = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
+
+ private int maxMarkedOffset;
+
+
+ /**
+ * Creates a new EvaluationShrinker.
+ */
+ public EvaluationShrinker()
+ {
+ this(new PartialEvaluator(), null, null);
+ }
+
+
+ /**
+ * Creates a new EvaluationShrinker.
+ * @param partialEvaluator the partial evaluator that will
+ * execute the code and provide
+ * information about the results.
+ * @param extraDeletedInstructionVisitor an optional extra visitor for all
+ * deleted instructions.
+ * @param extraAddedInstructionVisitor an optional extra visitor for all
+ * added instructions.
+ */
+ public EvaluationShrinker(PartialEvaluator partialEvaluator,
+ InstructionVisitor extraDeletedInstructionVisitor,
+ InstructionVisitor extraAddedInstructionVisitor)
+ {
+ this.partialEvaluator = partialEvaluator;
+ this.extraDeletedInstructionVisitor = extraDeletedInstructionVisitor;
+ this.extraAddedInstructionVisitor = extraAddedInstructionVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG = DEBUG_RESULTS =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ // TODO: Remove this when the evaluation shrinker has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while shrinking instructions after partial evaluation:");
+ System.err.println(" Class = ["+clazz.getName()+"]");
+ System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+ System.err.println("Not optimizing this method");
+
+ if (DEBUG)
+ {
+ method.accept(clazz, new ClassPrinter());
+
+ throw ex;
+ }
+ }
+ }
+
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (DEBUG_RESULTS)
+ {
+ System.out.println();
+ System.out.println("EvaluationShrinker ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ }
+
+ // Initialize the necessary array.
+ initializeNecessary(codeAttribute);
+
+ // Evaluate the method.
+ partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Evaluate the method the way the JVM verifier would do it.
+ simplePartialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
+ int codeLength = codeAttribute.u4codeLength;
+
+ // Reset the code changes.
+ codeAttributeEditor.reset(codeLength);
+
+ // Mark any unused method parameters on the stack.
+ if (DEBUG) System.out.println("Simplifying method invocations:");
+
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (partialEvaluator.isTraced(offset))
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+
+ instruction.accept(clazz, method, codeAttribute, offset, unusedParameterSimplifier);
+ }
+ }
+
+ // Mark all essential instructions that have been encountered as used.
+ if (DEBUG) System.out.println("Initializing necessary instructions:");
+
+ maxMarkedOffset = -1;
+
+ // The invocation of the "super" or "this" <init> method inside a
+ // constructor is always necessary.
+ int superInitializationOffset = partialEvaluator.superInitializationOffset();
+ if (superInitializationOffset != PartialEvaluator.NONE)
+ {
+ if (DEBUG) System.out.print("(super.<init>)");
+
+ markInstruction(superInitializationOffset);
+ }
+
+ // Also mark infinite loops and instructions that cause side effects.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (partialEvaluator.isTraced(offset))
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+
+ // Mark that the instruction is necessary if it is an infinite loop.
+ if (instruction.opcode == InstructionConstants.OP_GOTO &&
+ ((BranchInstruction)instruction).branchOffset == 0)
+ {
+ if (DEBUG) System.out.print("(infinite loop)");
+ markInstruction(offset);
+ }
+
+ // Mark that the instruction is necessary if it has side effects.
+ else if (sideEffectInstructionChecker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ instruction))
+ {
+ markInstruction(offset);
+ }
+ }
+ }
+ if (DEBUG) System.out.println();
+
+
+ // Globally mark instructions and their produced variables and stack
+ // entries on which necessary instructions depend.
+ // Instead of doing this recursively, we loop across all instructions,
+ // starting at the highest previously unmarked instruction that has
+ // been been marked.
+ if (DEBUG) System.out.println("Marking necessary instructions:");
+
+ while (maxMarkedOffset >= 0)
+ {
+ int offset = maxMarkedOffset;
+
+ maxMarkedOffset = offset - 1;
+
+ if (partialEvaluator.isTraced(offset))
+ {
+ if (isInstructionNecessary(offset))
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+
+ instruction.accept(clazz, method, codeAttribute, offset, producerMarker);
+ }
+
+ // Check if this instruction is a branch origin from a
+ // branch that straddles some marked code (forward range
+ // for a forward branch).
+ markStraddlingBranches(offset,
+ partialEvaluator.branchTargets(offset),
+ true,
+ false);
+
+ // Check if this instruction is a branch target from a
+ // branch that straddles some marked code (forward range
+ // for backward branches).
+ markStraddlingBranches(offset,
+ partialEvaluator.branchOrigins(offset),
+ false,
+ false);
+ }
+
+ if (DEBUG)
+ {
+ if (maxMarkedOffset > offset)
+ {
+ System.out.println(" -> "+maxMarkedOffset);
+ }
+ }
+ }
+ if (DEBUG) System.out.println();
+
+
+ // Mark variable initializations, even if they aren't strictly necessary.
+ // The virtual machine's verification step is not smart enough to see
+ // this, and may complain otherwise.
+ if (DEBUG) System.out.println("Marking variable initializations:");
+
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (isInstructionNecessary(offset))
+ {
+ // Mark initializations of the required instruction.
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+
+ instruction.accept(clazz, method, codeAttribute, offset, variableInitializationMarker);
+ }
+ }
+ if (DEBUG) System.out.println();
+
+
+ // Make sure the stacks are globally consistent, at branch targets.
+ // The different branch origins have to push the same stack entries.
+ if (DEBUG) System.out.println("Fixing global stack consistency:");
+
+ do
+ {
+ maxMarkedOffset = -1;
+
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ // Is this offset a branch target, i.e. does it have branch
+ // origins?
+ if (partialEvaluator.branchOrigins(offset) != null)
+ {
+ // Check all stack elements.
+ TracedStack tracedStack =
+ partialEvaluator.getStackBefore(offset);
+
+ int stackSize = tracedStack.size();
+ for (int stackIndex = 0; stackIndex < stackSize; stackIndex++)
+ {
+ // Mark all produced stack entries if one of them is
+ // marked.
+ consistentlyMarkProducedStackEntries(offset, stackIndex);
+ }
+ }
+ }
+ }
+ while (maxMarkedOffset >= 0);
+
+ if (DEBUG) System.out.println();
+
+
+ // Locally fix instructions, in order to keep the stack consistent.
+ if (DEBUG) System.out.println("Fixing local stack consistency:");
+
+ maxMarkedOffset = -1;
+
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (partialEvaluator.isTraced(offset))
+ {
+ // Fix instructions.
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+
+ instruction.accept(clazz, method, codeAttribute, offset, localStackConsistencyFixer);
+ }
+ }
+
+ // Mark straddling branches one last time, e.g. to branch over a
+ // an exception handler that pops the pushed exception.
+ if (DEBUG) System.out.println("Marking straddling branches:");
+
+ while (maxMarkedOffset >= 0)
+ {
+ maxMarkedOffset = -1;
+
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (partialEvaluator.isTraced(offset))
+ {
+ // Check if this instruction is a unconditional forward
+ // branch that straddles some marked code (forward range).
+ markStraddlingBranches(offset,
+ partialEvaluator.branchTargets(offset),
+ true,
+ true);
+ }
+ }
+ }
+
+ if (DEBUG) System.out.println();
+
+
+ // Replace traced but unmarked backward branches by infinite loops.
+ // The virtual machine's verification step is not smart enough to see
+ // the code isn't reachable, and may complain otherwise.
+ // Any clearly unreachable code will still be removed elsewhere.
+ if (DEBUG) System.out.println("Fixing infinite loops:");
+
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ // Is it a traced but unmarked backward branch, without an unmarked
+ // straddling forward branch? Note that this is still a heuristic.
+ if (partialEvaluator.isTraced(offset) &&
+ !isInstructionNecessary(offset) &&
+ isAllSmallerThanOrEqual(partialEvaluator.branchTargets(offset),
+ offset) &&
+ !isAnyUnnecessaryInstructionBranchingOver(lastNecessaryInstructionOffset(offset),
+ offset))
+ {
+ replaceByInfiniteLoop(clazz, offset);
+ }
+ }
+ if (DEBUG) System.out.println();
+
+
+ // Insert infinite loops after jumps to subroutines that don't return.
+ // The virtual machine's verification step is not smart enough to see
+ // the code isn't reachable, and may complain otherwise.
+ if (DEBUG) System.out.println("Fixing non-returning subroutines:");
+
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ // Is it a traced but unmarked backward branch, without an unmarked
+ // straddling forward branch? Note that this is still a heuristic.
+ if (isInstructionNecessary(offset) &&
+ partialEvaluator.isSubroutineInvocation(offset))
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+
+ int nextOffset = offset + instruction.length(offset);
+ if (!isInstructionNecessary(nextOffset))
+ {
+ replaceByInfiniteLoop(clazz, nextOffset);
+ }
+ }
+ }
+ if (DEBUG) System.out.println();
+
+
+ // Delete all instructions that are not used.
+ int offset = 0;
+ do
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+ if (!isInstructionNecessary(offset))
+ {
+ codeAttributeEditor.clearModifications(offset);
+ codeAttributeEditor.deleteInstruction(offset);
+
+ // Visit the instruction, if required.
+ if (extraDeletedInstructionVisitor != null)
+ {
+ instruction.accept(clazz, method, codeAttribute, offset, extraDeletedInstructionVisitor);
+ }
+ }
+
+ offset += instruction.length(offset);
+ }
+ while (offset < codeLength);
+
+ if (DEBUG_RESULTS)
+ {
+ System.out.println("Simplification results:");
+
+ offset = 0;
+ do
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+ System.out.println((isInstructionNecessary(offset) ? " + " : " - ")+instruction.toString(offset));
+
+ if (partialEvaluator.isTraced(offset))
+ {
+ int initializationOffset = partialEvaluator.initializationOffset(offset);
+ if (initializationOffset != PartialEvaluator.NONE)
+ {
+ System.out.println(" is to be initialized at ["+initializationOffset+"]");
+ }
+
+ InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset);
+ if (branchTargets != null)
+ {
+ System.out.println(" has overall been branching to "+branchTargets);
+ }
+
+ boolean deleted = codeAttributeEditor.deleted[offset];
+ if (isInstructionNecessary(offset) && deleted)
+ {
+ System.out.println(" is deleted");
+ }
+
+ Instruction preInsertion = codeAttributeEditor.preInsertions[offset];
+ if (preInsertion != null)
+ {
+ System.out.println(" is preceded by: "+preInsertion);
+ }
+
+ Instruction replacement = codeAttributeEditor.replacements[offset];
+ if (replacement != null)
+ {
+ System.out.println(" is replaced by: "+replacement);
+ }
+
+ Instruction postInsertion = codeAttributeEditor.postInsertions[offset];
+ if (postInsertion != null)
+ {
+ System.out.println(" is followed by: "+postInsertion);
+ }
+ }
+
+ offset += instruction.length(offset);
+ }
+ while (offset < codeLength);
+ }
+
+ // Clear exception handlers that are not necessary.
+ codeAttribute.exceptionsAccept(clazz, method, this);
+
+ // Apply all accumulated changes to the code.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ /**
+ * This MemberVisitor marks stack entries that aren't necessary because
+ * parameters aren't used in the methods that are visited.
+ */
+ private class MyUnusedParameterSimplifier
+ extends SimplifiedVisitor
+ implements InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor
+ {
+ private int invocationOffset;
+ private ConstantInstruction invocationInstruction;
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ this.invocationOffset = offset;
+ this.invocationInstruction = constantInstruction;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ refConstant.referencedMemberAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Get the total size of the parameters.
+ int parameterSize = ParameterUsageMarker.getParameterSize(programMethod);
+
+ // Make the method invocation static, if possible.
+ if ((programMethod.getAccessFlags() & ClassConstants.ACC_STATIC) == 0 &&
+ !ParameterUsageMarker.isParameterUsed(programMethod, 0))
+ {
+ replaceByStaticInvocation(programClass,
+ invocationOffset,
+ invocationInstruction);
+ }
+
+ // Remove unused parameters.
+ for (int index = 0; index < parameterSize; index++)
+ {
+ if (!ParameterUsageMarker.isParameterUsed(programMethod, index))
+ {
+ TracedStack stack =
+ partialEvaluator.getStackBefore(invocationOffset);
+
+ int stackIndex = stack.size() - parameterSize + index;
+
+ if (DEBUG)
+ {
+ System.out.println(" ["+invocationOffset+"] Ignoring parameter #"+index+" of "+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] (stack entry #"+stackIndex+" ["+stack.getBottom(stackIndex)+"])");
+ System.out.println(" Full stack: "+stack);
+ }
+
+ markStackSimplificationBefore(invocationOffset, stackIndex);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * This InstructionVisitor marks the producing instructions and produced
+ * variables and stack entries of the instructions that it visits.
+ * Simplified method arguments are ignored.
+ */
+ private class MyProducerMarker
+ extends SimplifiedVisitor
+ implements InstructionVisitor
+ {
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ markStackProducers(clazz, offset, instruction);
+ }
+
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ switch (simpleInstruction.opcode)
+ {
+ case InstructionConstants.OP_DUP:
+ conditionallyMarkStackEntryProducers(offset, 0, 0);
+ conditionallyMarkStackEntryProducers(offset, 1, 0);
+ break;
+ case InstructionConstants.OP_DUP_X1:
+ conditionallyMarkStackEntryProducers(offset, 0, 0);
+ conditionallyMarkStackEntryProducers(offset, 1, 1);
+ conditionallyMarkStackEntryProducers(offset, 2, 0);
+ break;
+ case InstructionConstants.OP_DUP_X2:
+ conditionallyMarkStackEntryProducers(offset, 0, 0);
+ conditionallyMarkStackEntryProducers(offset, 1, 1);
+ conditionallyMarkStackEntryProducers(offset, 2, 2);
+ conditionallyMarkStackEntryProducers(offset, 3, 0);
+ break;
+ case InstructionConstants.OP_DUP2:
+ conditionallyMarkStackEntryProducers(offset, 0, 0);
+ conditionallyMarkStackEntryProducers(offset, 1, 1);
+ conditionallyMarkStackEntryProducers(offset, 2, 0);
+ conditionallyMarkStackEntryProducers(offset, 3, 1);
+ break;
+ case InstructionConstants.OP_DUP2_X1:
+ conditionallyMarkStackEntryProducers(offset, 0, 0);
+ conditionallyMarkStackEntryProducers(offset, 1, 1);
+ conditionallyMarkStackEntryProducers(offset, 2, 2);
+ conditionallyMarkStackEntryProducers(offset, 3, 0);
+ conditionallyMarkStackEntryProducers(offset, 4, 1);
+ break;
+ case InstructionConstants.OP_DUP2_X2:
+ conditionallyMarkStackEntryProducers(offset, 0, 0);
+ conditionallyMarkStackEntryProducers(offset, 1, 1);
+ conditionallyMarkStackEntryProducers(offset, 2, 2);
+ conditionallyMarkStackEntryProducers(offset, 3, 3);
+ conditionallyMarkStackEntryProducers(offset, 4, 0);
+ conditionallyMarkStackEntryProducers(offset, 5, 1);
+ break;
+ case InstructionConstants.OP_SWAP:
+ conditionallyMarkStackEntryProducers(offset, 0, 1);
+ conditionallyMarkStackEntryProducers(offset, 1, 0);
+ break;
+ default:
+ markStackProducers(clazz, offset, simpleInstruction);
+ break;
+ }
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ // Is the variable being loaded or incremented?
+ if (variableInstruction.isLoad())
+ {
+ markVariableProducers(offset, variableInstruction.variableIndex);
+ }
+ else
+ {
+ markStackProducers(clazz, offset, variableInstruction);
+ }
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ // Mark the initializer invocation, if this is a 'new' instruction.
+ if (constantInstruction.opcode == InstructionConstants.OP_NEW)
+ {
+ markInitialization(offset);
+ }
+
+ markStackProducers(clazz, offset, constantInstruction);
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ // Explicitly mark the produced stack entry of a 'jsr' instruction,
+ // because the consuming 'astore' instruction of the subroutine is
+ // cleared every time it is traced.
+ if (branchInstruction.opcode == InstructionConstants.OP_JSR ||
+ branchInstruction.opcode == InstructionConstants.OP_JSR_W)
+ {
+ markStackEntryAfter(offset, 0);
+ }
+ else
+ {
+ markStackProducers(clazz, offset, branchInstruction);
+ }
+ }
+ }
+
+
+ /**
+ * This InstructionVisitor marks variable initializations that are
+ * necessary to appease the JVM.
+ */
+ private class MyVariableInitializationMarker
+ extends SimplifiedVisitor
+ implements InstructionVisitor
+ {
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ // Is the variable being loaded or incremented?
+ if (variableInstruction.isLoad())
+ {
+ // Mark any variable initializations for this variable load that
+ // are required according to the JVM.
+ markVariableInitializersBefore(offset, variableInstruction.variableIndex);
+ }
+ }
+ }
+
+
+ /**
+ * This InstructionVisitor fixes instructions locally, popping any unused
+ * produced stack entries after marked instructions, and popping produced
+ * stack entries and pushing missing stack entries instead of unmarked
+ * instructions.
+ */
+ private class MyLocalStackConsistencyFixer
+ extends SimplifiedVisitor
+ implements InstructionVisitor
+ {
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ // Has the instruction been marked?
+ if (isInstructionNecessary(offset))
+ {
+ // The instruction has already been marked as necessary.
+
+ // Check all stack entries that are popped.
+ // Unusual case: an exception handler with an exception that is
+ // no longer consumed directly by a method.
+ // Typical case: a freshly marked variable initialization that
+ // requires some value on the stack.
+ int popCount = instruction.stackPopCount(clazz);
+ if (popCount > 0)
+ {
+ TracedStack tracedStack =
+ partialEvaluator.getStackBefore(offset);
+
+ int stackSize = tracedStack.size();
+
+ int requiredPopCount = 0;
+ int requiredPushCount = 0;
+ for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
+ {
+ boolean stackSimplifiedBefore =
+ isStackSimplifiedBefore(offset, stackIndex);
+ boolean stackEntryPresentBefore =
+ isStackEntryPresentBefore(offset, stackIndex);
+
+ if (stackSimplifiedBefore)
+ {
+ // Is this stack entry pushed by any producer
+ // (maybe an exception in an exception handler)?
+ if (stackEntryPresentBefore)
+ {
+ // Remember to pop it.
+ requiredPopCount++;
+ }
+ }
+ else
+ {
+ // Is this stack entry pushed by any producer
+ // (because it is required by other consumers)?
+ if (!stackEntryPresentBefore)
+ {
+ // Remember to push it.
+ requiredPushCount++;
+ }
+ }
+ }
+
+ // Pop some unnecessary stack entries.
+ if (requiredPopCount > 0)
+ {
+ insertPopInstructions(offset,
+ false,
+ true,
+ instruction,
+ popCount);
+ }
+
+ // Push some necessary stack entries.
+ if (requiredPushCount > 0)
+ {
+ if (requiredPushCount > (instruction.isCategory2() ? 2 : 1))
+ {
+ throw new IllegalArgumentException("Unsupported stack size increment ["+requiredPushCount+"] at ["+offset+"]");
+ }
+
+ insertPushInstructions(offset,
+ false,
+ true,
+ instruction,
+ tracedStack.getTop(0).computationalType());
+ }
+ }
+
+ // Check all stack entries that are pushed.
+ // Typical case: a return value that wasn't really required and
+ // that should be popped.
+ int pushCount = instruction.stackPushCount(clazz);
+ if (pushCount > 0)
+ {
+ TracedStack tracedStack =
+ partialEvaluator.getStackAfter(offset);
+
+ int stackSize = tracedStack.size();
+
+ int requiredPopCount = 0;
+ for (int stackIndex = stackSize - pushCount; stackIndex < stackSize; stackIndex++)
+ {
+ // Is the stack entry required by consumers?
+ if (!isStackEntryNecessaryAfter(offset, stackIndex))
+ {
+ // Remember to pop it.
+ requiredPopCount++;
+ }
+ }
+
+ // Pop the unnecessary stack entries.
+ if (requiredPopCount > 0)
+ {
+ insertPopInstructions(offset,
+ false,
+ false,
+ instruction,
+ requiredPopCount);
+ }
+ }
+ }
+ else
+ {
+ // The instruction has not been marked as necessary yet.
+
+ // Check all stack entries that would be popped.
+ // Typical case: a stack value that is required elsewhere and
+ // that still has to be popped.
+ int popCount = instruction.stackPopCount(clazz);
+ if (popCount > 0)
+ {
+ TracedStack tracedStack =
+ partialEvaluator.getStackBefore(offset);
+
+ int stackSize = tracedStack.size();
+
+ int expectedPopCount = 0;
+ for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
+ {
+ // Is this stack entry pushed by any producer
+ // (because it is required by other consumers)?
+ if (isStackEntryPresentBefore(offset, stackIndex))
+ {
+ // Remember to pop it.
+ expectedPopCount++;
+ }
+ }
+
+ // Pop the unnecessary stack entries.
+ if (expectedPopCount > 0)
+ {
+ insertPopInstructions(offset,
+ true,
+ false,
+ instruction,
+ expectedPopCount);
+ }
+ }
+
+ // Check all stack entries that would be pushed.
+ // Typical case: never.
+ int pushCount = instruction.stackPushCount(clazz);
+ if (pushCount > 0)
+ {
+ TracedStack tracedStack =
+ partialEvaluator.getStackAfter(offset);
+
+ int stackSize = tracedStack.size();
+
+ int expectedPushCount = 0;
+ for (int stackIndex = stackSize - pushCount; stackIndex < stackSize; stackIndex++)
+ {
+ // Is the stack entry required by consumers?
+ if (isStackEntryNecessaryAfter(offset, stackIndex))
+ {
+ // Remember to push it.
+ expectedPushCount++;
+ }
+ }
+
+ // Push some necessary stack entries.
+ if (expectedPushCount > 0)
+ {
+ insertPushInstructions(offset,
+ true,
+ false,
+ instruction,
+ tracedStack.getTop(0).computationalType());
+ }
+ }
+ }
+ }
+
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ if (isInstructionNecessary(offset) &&
+ isDupOrSwap(simpleInstruction))
+ {
+ int stackSizeBefore = partialEvaluator.getStackBefore(offset).size();
+
+ int topBefore = stackSizeBefore - 1;
+ int topAfter = partialEvaluator.getStackAfter(offset).size() - 1;
+
+ byte oldOpcode = simpleInstruction.opcode;
+
+ // Simplify the dup/swap instruction if possible.
+ int newOpcodes = fixDupSwap(offset, oldOpcode, topBefore, topAfter);
+
+ // Replace it.
+ insertInstructions(offset, true, false, simpleInstruction, newOpcodes);
+ }
+ else
+ {
+ visitAnyInstruction(clazz, method, codeAttribute, offset, simpleInstruction);
+ }
+ }
+
+
+ /**
+ * Returns a dup/swap opcode that is corrected for the stack entries
+ * that are present before the instruction and necessary after the
+ * instruction. The returned integer opcode may contain multiple byte
+ * opcodes (least significant byte first).
+ * @param instructionOffset the offset of the dup/swap instruction.
+ * @param dupSwapOpcode the original dup/swap opcode.
+ * @param topBefore the index of the top stack entry before
+ * the instruction (counting from the bottom).
+ * @param topAfter the index of the top stack entry after
+ * the instruction (counting from the bottom).
+ * @return the corrected opcode.
+ */
+ private int fixDupSwap(int instructionOffset,
+ byte dupSwapOpcode,
+ int topBefore,
+ int topAfter)
+ {
+ switch (dupSwapOpcode)
+ {
+ case InstructionConstants.OP_DUP: return fixedDup (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP_X1: return fixedDup_x1 (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP_X2: return fixedDup_x2 (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP2: return fixedDup2 (instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP2_X1: return fixedDup2_x1(instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_DUP2_X2: return fixedDup2_x2(instructionOffset, topBefore, topAfter);
+ case InstructionConstants.OP_SWAP: return fixedSwap (instructionOffset, topBefore, topAfter);
+ default: throw new IllegalArgumentException("Not a dup/swap opcode ["+dupSwapOpcode+"]");
+ }
+ }
+
+
+ private int fixedDup(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary0 ?
+ stackEntryNecessary1 ? DUP : // ...O -> ...OO
+ NOP : // ...O -> ...O
+ stackEntryNecessary1 ? NOP : // ...O -> ...O
+ stackEntryPresent0 ? POP : // ...O -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup_x1(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 2);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...XO -> ...OXO
+ SWAP : // ...XO -> ...OX
+ // !stackEntryNecessary2
+ stackEntryNecessary0 ? NOP : // ...XO -> ...XO
+ stackEntryPresent0 ? POP : // ...XO -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...XO -> ...OO
+ POP_X1 : // ...XO -> ...O
+ // !stackEntryNecessary2
+ stackEntryNecessary0 ? POP_X1 : // ...XO -> ...O
+ stackEntryPresent0 ? POP2 : // ...XO -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent1
+ stackEntryNecessary2 ?
+ stackEntryNecessary0 ? DUP : // ...O -> ...OO
+ NOP : // ...O -> ...O
+ // !stackEntryNecessary2
+ stackEntryNecessary0 ? NOP : // ...O -> ...O
+ stackEntryPresent0 ? POP : // ...O -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup_x2(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1);
+ boolean stackEntryPresent2 = isStackEntryPresentBefore(instructionOffset, topBefore - 2);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 2);
+ boolean stackEntryNecessary3 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 3);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP_X2 : // ...XYO -> ...OXYO
+ MOV_X2 : // ...XYO -> ...OXY
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...XYO -> ...XYO
+ stackEntryPresent0 ? POP : // ...XYO -> ...XY
+ NOP : // ...XY -> ...XY
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ // stackEntryNecessary0 ? UNSUPPORTED : // ...XYO -> ...OYO
+ UNSUPPORTED : // ...XYO -> ...OY
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X2 : // ...XYO -> ...YO
+ stackEntryPresent0 ? POP_SWAP_POP : // ...XYO -> ...Y
+ POP_X1 : // ...XY -> ...Y
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...YO -> ...OYO
+ SWAP : // ...YO -> ...OY
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...YO -> ...YO
+ stackEntryPresent0 ? POP : // ...YO -> ...Y
+ NOP : // ...Y -> ...Y
+ stackEntryPresent1 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP_X1 : // ...XYO -> ...OXO
+ DUP_X2_POP2 : // ...XYO -> ...OX
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X1 : // ...XYO -> ...XO
+ stackEntryPresent0 ? POP2 : // ...XYO -> ...X
+ POP : // ...XY -> ...X
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? UNSUPPORTED : // ...XYO -> ...OO
+ POP2_X1 : // ...XYO -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP2_X1 : // ...XYO -> ...O
+ stackEntryPresent0 ? POP3 : // ...XYO -> ...
+ POP2 : // ...XY -> ...
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...YO -> ...OO
+ POP_X1 : // ...YO -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X1 : // ...YO -> ...O
+ stackEntryPresent0 ? POP2 : // ...YO -> ...
+ POP : // ...Y -> ...
+ // !stackEntryPresent1
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...XO -> ...OXO
+ SWAP : // ...XO -> ...OX
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...XO -> ...XO
+ stackEntryPresent0 ? POP : // ...XO -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...XO -> ...OO
+ POP_X1 : // ...XO -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? POP_X1 : // ...XO -> ...O
+ stackEntryPresent0 ? POP2 : // ...XO -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntryNecessary0 ? DUP : // ...O -> ...OO
+ NOP : // ...O -> ...O
+ // !stackEntryNecessary3
+ stackEntryNecessary0 ? NOP : // ...O -> ...O
+ stackEntryPresent0 ? POP : // ...O -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup2(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0);
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1);
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0);
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 2);
+ boolean stackEntryNecessary3 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 3);
+
+ return
+ stackEntryNecessary3 ?
+ stackEntryNecessary2 ?
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? DUP2 : // ...AB -> ...ABAB
+ SWAP_DUP_X1 : // ...AB -> ...ABA
+ // !stackEntryNecessary1
+ stackEntryNecessary0 ? DUP : // ...AB -> ...ABB
+ NOP : // ...AB -> ...AB
+ // !stackEntryNecessary2
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? SWAP_DUP_X1_SWAP : // ...AB -> ...AAB
+ stackEntryPresent0 ? POP_DUP : // ...AB -> ...AA
+ DUP : // ...A -> ...AA
+ // !stackEntryNecessary1
+ stackEntryNecessary0 ? NOP : // ...AB -> ...AB
+ stackEntryPresent0 ? POP : // ...AB -> ...A
+ NOP : // ...A -> ...A
+ // !stackEntryNecessary3
+ stackEntryNecessary2 ?
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? DUP_X1 : // ...AB -> ...BAB
+ SWAP : // ...AB -> ...BA
+ stackEntryPresent1 ?
+ stackEntryNecessary0 ? SWAP_POP_DUP : // ...AB -> ...BB
+ POP_X1 : // ...AB -> ...B
+ // !stackEntryPresent1
+ stackEntryNecessary0 ? POP : // ...B -> ...BB
+ NOP : // ...B -> ...B
+ // !stackEntryNecessary2
+ stackEntryNecessary1 ?
+ stackEntryNecessary0 ? NOP : // ...AB -> ...AB
+ stackEntryPresent0 ? POP : // ...AB -> ...A
+ NOP : // ...A -> ...A
+ stackEntryPresent1 ?
+ stackEntryNecessary0 ? POP_X1 : // ...AB -> ...B
+ stackEntryPresent0 ? POP2 : // ...AB -> ...
+ POP : // ...A -> ...
+ // !stackEntryPresent1
+ stackEntryNecessary0 ? NOP : // ...B -> ...B
+ stackEntryPresent0 ? POP : // ...B -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup2_x1(int instructionOffset, int topBefore, int topAfter)
+ {
+ // We're currently assuming the value to be duplicated
+ // is a long or a double, taking up two slots, or at
+ // least consistent.
+ boolean stackEntriesPresent01 = isStackEntriesPresentBefore(instructionOffset, topBefore - 0, topBefore - 1);
+ boolean stackEntryPresent2 = isStackEntryPresentBefore( instructionOffset, topBefore - 2);
+
+ boolean stackEntriesNecessary01 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 0, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter( instructionOffset, topAfter - 2);
+ boolean stackEntriesNecessary34 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 3, topAfter - 4);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary2 ?
+ stackEntriesNecessary34 ?
+ stackEntriesNecessary01 ? DUP2_X1 : // ...XAB -> ...ABXAB
+ MOV2_X1 : // ...XAB -> ...ABX
+ // !stackEntriesNecessary34
+ stackEntriesNecessary01 ? NOP : // ...XAB -> ...XAB
+ stackEntriesPresent01 ? POP2 : // ...XAB -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent2 ?
+ stackEntriesNecessary34 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XAB -> ...ABAB
+ POP_X2 : // ...XAB -> ...AB
+ // !stackEntriesNecessary34
+ stackEntriesNecessary01 ? DUP2_X1_POP3 : // ...XAB -> ...AB
+ stackEntriesPresent01 ? POP3 : // ...XAB -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent2
+ stackEntriesNecessary34 ?
+ stackEntriesNecessary01 ? DUP2 : // ...AB -> ...ABAB
+ NOP : // ...AB -> ...AB
+ // !stackEntriesNecessary34
+ stackEntriesNecessary01 ? NOP : // ...AB -> ...AB
+ stackEntriesPresent01 ? POP2 : // ...AB -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedDup2_x2(int instructionOffset, int topBefore, int topAfter)
+ {
+ // We're currently assuming the value to be duplicated
+ // is a long or a double, taking up two slots, or at
+ // least consistent.
+ boolean stackEntriesPresent01 = isStackEntriesPresentBefore(instructionOffset, topBefore - 0, topBefore - 1);
+ boolean stackEntryPresent2 = isStackEntryPresentBefore( instructionOffset, topBefore - 2);
+ boolean stackEntryPresent3 = isStackEntryPresentBefore( instructionOffset, topBefore - 3);
+
+ boolean stackEntriesNecessary01 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 0, topAfter - 1);
+ boolean stackEntryNecessary2 = isStackEntryNecessaryAfter( instructionOffset, topAfter - 2);
+ boolean stackEntryNecessary3 = isStackEntryNecessaryAfter( instructionOffset, topAfter - 3);
+ boolean stackEntriesNecessary45 = isStackEntriesNecessaryAfter(instructionOffset, topAfter - 4, topAfter - 5);
+
+ // Figure out which stack entries should be moved,
+ // copied, or removed.
+ return
+ stackEntryNecessary2 ?
+ stackEntryNecessary3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2_X2 : // ...XYAB -> ...ABXYAB
+ MOV2_X2 : // ...XYAB -> ...ABXY
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...XYAB -> ...XYAB
+ stackEntriesPresent01 ? POP2 : // ...XYAB -> ...XY
+ NOP : // ...XY -> ...XY
+ stackEntryPresent3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XYAB -> ...ABYAB
+ DUP2_X2_SWAP_POP : // ...XYAB -> ...ABY
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X3 : // ...XYAB -> ...YAB
+ stackEntriesPresent01 ? POP2_SWAP_POP : // ...XYAB -> ...Y
+ POP_X1 : // ...XY -> ...Y
+ // !stackEntryPresent3
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2_X1 : // ...YAB -> ...ABYAB
+ MOV2_X1 : // ...YAB -> ...ABY
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...YAB -> ...YAB
+ stackEntriesPresent01 ? POP2 : // ...YAB -> ...Y
+ NOP : // ...Y -> ...Y
+ stackEntryPresent2 ?
+ stackEntryNecessary3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XYAB -> ...ABXAB
+ DUP2_X2_POP3 : // ...XYAB -> ...ABX
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X2 : // ...XYAB -> ...XAB
+ stackEntriesPresent01 ? POP3 : // ...XYAB -> ...X
+ POP : // ...XY -> ...X
+ stackEntryPresent3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XYAB -> ...ABAB
+ POP2_X2 : // ...XYAB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP2_X2 : // ...XYAB -> ...AB
+ stackEntriesPresent01 ? POP4 : // ...XYAB -> ...
+ POP2 : // ...XY -> ...
+ // !stackEntryPresent3
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...YAB -> ...ABAB
+ POP_X2 : // ...YAB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X2 : // ...YAB -> ...AB
+ stackEntriesPresent01 ? POP3 : // ...YAB -> ...
+ POP : // ...Y -> ...
+ // !stackEntryPresent2
+ stackEntryNecessary3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2_X1 : // ...XAB -> ...ABXAB
+ MOV2_X1 : // ...XAB -> ...ABX
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...XAB -> ...XAB
+ stackEntriesPresent01 ? POP2 : // ...XAB -> ...X
+ NOP : // ...X -> ...X
+ stackEntryPresent3 ?
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? UNSUPPORTED : // ...XAB -> ...ABAB
+ POP_X2 : // ...XAB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? POP_X2 : // ...XAB -> ...AB
+ stackEntriesPresent01 ? POP3 : // ...XAB -> ...
+ POP : // ...X -> ...
+ // !stackEntryPresent3
+ stackEntriesNecessary45 ?
+ stackEntriesNecessary01 ? DUP2 : // ...AB -> ...ABAB
+ NOP : // ...AB -> ...AB
+ // !stackEntriesNecessary45
+ stackEntriesNecessary01 ? NOP : // ...AB -> ...AB
+ stackEntriesPresent01 ? POP2 : // ...AB -> ...
+ NOP; // ... -> ...
+ }
+
+
+ private int fixedSwap(int instructionOffset, int topBefore, int topAfter)
+ {
+ boolean stackEntryPresent0 = isStackEntryPresentBefore(instructionOffset, topBefore - 0); // B
+ boolean stackEntryPresent1 = isStackEntryPresentBefore(instructionOffset, topBefore - 1); // A
+
+ boolean stackEntryNecessary0 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 0); // A
+ boolean stackEntryNecessary1 = isStackEntryNecessaryAfter(instructionOffset, topAfter - 1); // B
+
+ // Figure out which stack entries should be moved
+ // or removed.
+ return
+ stackEntryNecessary0 ?
+ stackEntryNecessary1 ? SWAP : // ...AB -> ...BA
+
+ stackEntryPresent0 ? POP : // ...AB -> ...A
+ NOP : // ...A -> ...A
+ stackEntryNecessary1 ?
+ stackEntryPresent1 ? POP_X1 : // ...AB -> ...B
+ NOP : // ...B -> ...B
+ stackEntryPresent1 ?
+ stackEntryPresent0 ? POP2 : // ...AB -> ...
+ POP : // ...B -> ...
+
+ stackEntryPresent0 ? POP : // ...A -> ...
+ NOP; // ... -> ...
+ }
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ // Is the catch handler necessary?
+ if (!partialEvaluator.isTraced(exceptionInfo.u2handlerPC))
+ {
+ // Make the code block empty, so the code editor can remove it.
+ exceptionInfo.u2endPC = exceptionInfo.u2startPC;
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the producing instructions of the variable consumer at the given
+ * offset.
+ * @param consumerOffset the offset of the variable consumer.
+ * @param variableIndex the index of the variable that is loaded.
+ */
+ private void markVariableProducers(int consumerOffset,
+ int variableIndex)
+ {
+ InstructionOffsetValue producerOffsets =
+ partialEvaluator.getVariablesBefore(consumerOffset).getProducerValue(variableIndex).instructionOffsetValue();
+
+ if (producerOffsets != null)
+ {
+ int offsetCount = producerOffsets.instructionOffsetCount();
+ for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
+ {
+ // Make sure the variable and the instruction are marked
+ // at the producing offset.
+ int offset = producerOffsets.instructionOffset(offsetIndex);
+
+ markInstruction(offset);
+ }
+ }
+ }
+
+
+ /**
+ * Ensures that the given variable is initialized before the specified
+ * consumer of that variable, in the JVM's view.
+ * @param consumerOffset the instruction offset before which the variable
+ * needs to be initialized.
+ * @param variableIndex the index of the variable.
+ */
+ private void markVariableInitializersBefore(int consumerOffset,
+ int variableIndex)
+ {
+ // Make sure the variable is initialized after all producers.
+ // Use the simple evaluator, to get the JVM's view of what is
+ // initialized.
+ InstructionOffsetValue producerOffsets =
+ simplePartialEvaluator.getVariablesBefore(consumerOffset).getProducerValue(variableIndex).instructionOffsetValue();
+
+ int offsetCount = producerOffsets.instructionOffsetCount();
+ for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
+ {
+ // Avoid infinite loops by only looking at producers before
+ // the consumer. Only consider traced producers.
+ int producerOffset =
+ producerOffsets.instructionOffset(offsetIndex);
+ if (producerOffset >= 0 &&
+ producerOffset < consumerOffset &&
+ partialEvaluator.isTraced(producerOffset))
+ {
+ markVariableInitializersAfter(producerOffset, variableIndex);
+ }
+ }
+ }
+
+
+ /**
+ * Ensures that the given variable is initialized after the specified
+ * producer of that variable, in the JVM's view.
+ * @param producerOffset the instruction offset after which the variable
+ * needs to be initialized.
+ * @param variableIndex the index of the variable.
+ */
+ private void markVariableInitializersAfter(int producerOffset,
+ int variableIndex)
+ {
+ // No problem if the producer has already been marked.
+ if (!isInstructionNecessary(producerOffset))
+ {
+ // Is the unmarked producer a variable initialization?
+ if (isVariableInitialization(producerOffset, variableIndex))
+ {
+ // Mark the producer.
+ if (DEBUG) System.out.print(" Marking initialization of v"+variableIndex+" at ");
+
+ markInstruction(producerOffset);
+
+ if (DEBUG) System.out.println();
+ }
+ else
+ {
+ // Don't mark the producer, but recursively look at the
+ // preceding producers of the same variable. Their values
+ // will fall through, replacing this producer.
+ markVariableInitializersBefore(producerOffset, variableIndex);
+ }
+ }
+ }
+
+
+ /**
+ * Marks the stack entries and their producing instructions of the
+ * consumer at the given offset.
+ * @param clazz the containing class.
+ * @param consumerOffset the offset of the consumer.
+ * @param consumer the consumer of the stack entries.
+ */
+ private void markStackProducers(Clazz clazz,
+ int consumerOffset,
+ Instruction consumer)
+ {
+ TracedStack tracedStack =
+ partialEvaluator.getStackBefore(consumerOffset);
+
+ int stackSize = tracedStack.size();
+
+ // Mark the producers of the popped values.
+ int popCount = consumer.stackPopCount(clazz);
+ for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
+ {
+ markStackEntryProducers(consumerOffset, stackIndex);
+ }
+ }
+
+
+ /**
+ * Marks the stack entry and the corresponding producing instructions
+ * of the consumer at the given offset, if the stack entry of the
+ * consumer is marked.
+ * @param consumerOffset the offset of the consumer.
+ * @param consumerTopStackIndex the index of the stack entry to be checked
+ * (counting from the top).
+ * @param producerTopStackIndex the index of the stack entry to be marked
+ * (counting from the top).
+ */
+ private void conditionallyMarkStackEntryProducers(int consumerOffset,
+ int consumerTopStackIndex,
+ int producerTopStackIndex)
+ {
+ int consumerBottomStackIndex = partialEvaluator.getStackAfter(consumerOffset).size() - consumerTopStackIndex - 1;
+
+ if (isStackEntryNecessaryAfter(consumerOffset, consumerBottomStackIndex))
+ {
+ int producerBottomStackIndex = partialEvaluator.getStackBefore(consumerOffset).size() - producerTopStackIndex - 1;
+
+ markStackEntryProducers(consumerOffset, producerBottomStackIndex);
+ }
+ }
+
+
+ /**
+ * Marks the stack entry and the corresponding producing instructions of
+ * the consumer at the given offset, if it hasn't been simplified away.
+ * @param consumerOffset the offset of the consumer.
+ * @param stackIndex the index of the stack entry to be marked
+ * (counting from the bottom).
+ */
+ private void markStackEntryProducers(int consumerOffset,
+ int stackIndex)
+ {
+ if (!isStackSimplifiedBefore(consumerOffset, stackIndex))
+ {
+ // Mark all produced stack entries and their producing
+ // instructions.
+ markStackEntryProducers(partialEvaluator.getStackBefore(consumerOffset).getBottomProducerValue(stackIndex).instructionOffsetValue(),
+ stackIndex,
+ true,
+ true);
+ }
+ }
+
+
+ /**
+ * Marks the stack entry of the consumer at the given offset, if
+ * it has been marked at any of its producers.
+ * @param consumerOffset the offset of the consumer.
+ * @param stackIndex the index of the stack entry to be marked
+ * (counting from the bottom).
+ */
+ private void consistentlyMarkProducedStackEntries(int consumerOffset,
+ int stackIndex)
+ {
+ // Is this stack entry pushed by any producer (maybe an exception in
+ // an exception handler or because it is required by other consumers)?
+ if (isStackEntryPresentBefore(consumerOffset, stackIndex))
+ {
+ // Mark all produced stack entries (but not their producing
+ // instructions).
+ markStackEntryProducers(partialEvaluator.getStackBefore(consumerOffset).getBottomProducerValue(stackIndex).instructionOffsetValue(),
+ stackIndex,
+ false,
+ true);
+ }
+ }
+
+
+ /**
+ * Marks the stack entries and/or their producing instructions at the
+ * given offsets.
+ * @param producerOffsets the offsets of the producers to be
+ * marked.
+ * @param stackIndex the index of the stack entry to be
+ * marked (counting from the bottom).
+ * @param markProducingInstructions specifies whether to mark the
+ * producing instructions.
+ * @param markProducedStackEntries specifies whether to mark the
+ * produced stack entries.
+ */
+ private void markStackEntryProducers(InstructionOffsetValue producerOffsets,
+ int stackIndex,
+ boolean markProducingInstructions,
+ boolean markProducedStackEntries)
+ {
+ if (producerOffsets != null)
+ {
+ int offsetCount = producerOffsets.instructionOffsetCount();
+ for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
+ {
+ // Make sure the stack entry and the instruction are marked
+ // at the producing offset.
+ int offset = producerOffsets.instructionOffset(offsetIndex);
+
+ // Mark the producing instruction, if specified.
+ if (markProducingInstructions)
+ {
+ markInstruction(offset);
+ }
+
+ // Mark the produced stack entry, if specified.
+ if (markProducedStackEntries)
+ {
+ markStackEntryAfter(offset, stackIndex);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Marks the stack entry and its initializing instruction
+ * ('invokespecial *.<init>') for the given 'new' instruction offset.
+ * @param newInstructionOffset the offset of the 'new' instruction.
+ */
+ private void markInitialization(int newInstructionOffset)
+ {
+ int initializationOffset =
+ partialEvaluator.initializationOffset(newInstructionOffset);
+
+ TracedStack tracedStack =
+ partialEvaluator.getStackAfter(newInstructionOffset);
+
+ markStackEntryAfter(initializationOffset, tracedStack.size() - 1);
+ markInstruction(initializationOffset);
+ }
+
+
+ /**
+ * Marks the branch instructions of straddling branches, if they straddle
+ * some that has been marked between a given offset and the branch offset
+ * (forward).
+ * @param instructionOffset the offset of the branch origin or branch target.
+ * @param branchOffsets the offsets of the straddling branch targets
+ * or branch origins.
+ * @param isBranchTargets <code>true</code> if the above offsets are
+ * branch targets, <code>false</code> if they
+ * are branch origins.
+ */
+ private void markStraddlingBranches(int instructionOffset,
+ InstructionOffsetValue branchOffsets,
+ boolean isBranchTargets,
+ boolean onlyUnconditionalBranches)
+ {
+ if (branchOffsets != null)
+ {
+ // Loop over all branch offsets.
+ int branchCount = branchOffsets.instructionOffsetCount();
+ if (!onlyUnconditionalBranches || branchCount == 1)
+ {
+ for (int branchIndex = 0; branchIndex < branchCount; branchIndex++)
+ {
+ // Mark the branch if it is straddling forward any necessary
+ // instructions.
+ int branchOffset = branchOffsets.instructionOffset(branchIndex);
+
+ // Correctly pass the instruction range to be checked, and
+ // the branch origin and branch target.
+ markStraddlingBranch(instructionOffset,
+ branchOffset,
+ isBranchTargets ? instructionOffset : branchOffset,
+ isBranchTargets ? branchOffset : instructionOffset);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Marks the specified branch instruction, if the any instruction in the
+ * specified block of instructions has been marked as necessary.
+ * @param instructionOffsetStart the start offset of the instructions to
+ * check.
+ * @param instructionOffsetEnd the end offset of the instructions to
+ * check.
+ * @param branchOrigin the branch origin offset.
+ * @param branchTarget the branch target offset.
+ */
+ private void markStraddlingBranch(int instructionOffsetStart,
+ int instructionOffsetEnd,
+ int branchOrigin,
+ int branchTarget)
+ {
+ if (!isInstructionNecessary(branchOrigin) &&
+ isAnyInstructionNecessary(instructionOffsetStart, instructionOffsetEnd))
+ {
+ if (DEBUG) System.out.print("["+branchOrigin+"->"+branchTarget+"]");
+
+ // Mark the branch instruction.
+ markInstruction(branchOrigin);
+ }
+ }
+
+
+ /**
+ * Pushes a specified type of stack entry before or at the given offset.
+ * The instruction is marked as necessary.
+ */
+ private void insertPushInstructions(int offset,
+ boolean replace,
+ boolean before,
+ Instruction oldInstruction,
+ int computationalType)
+ {
+ // Replace or insert the push instruction.
+ insertInstructions(offset,
+ replace,
+ before,
+ oldInstruction,
+ pushOpcode(computationalType));
+ }
+
+
+ /**
+ * Returns the opcode of a push instruction corresponding to the given
+ * computational type.
+ * @param computationalType the computational type to be pushed on the stack.
+ */
+ private byte pushOpcode(int computationalType)
+ {
+ switch (computationalType)
+ {
+ case Value.TYPE_INTEGER: return InstructionConstants.OP_ICONST_0;
+ case Value.TYPE_LONG: return InstructionConstants.OP_LCONST_0;
+ case Value.TYPE_FLOAT: return InstructionConstants.OP_FCONST_0;
+ case Value.TYPE_DOUBLE: return InstructionConstants.OP_DCONST_0;
+ case Value.TYPE_REFERENCE:
+ case Value.TYPE_INSTRUCTION_OFFSET: return InstructionConstants.OP_ACONST_NULL;
+ }
+
+ throw new IllegalArgumentException("No push opcode for computational type ["+computationalType+"]");
+ }
+
+
+ /**
+ * Pops the given number of stack entries at or after the given offset.
+ * The instructions are marked as necessary.
+ */
+ private void insertPopInstructions(int offset,
+ boolean replace,
+ boolean before,
+ Instruction oldInstruction,
+ int popCount)
+ {
+ // Collect the pop opcodes.
+ int popOpcodes = popCount % 2 == 1 ? InstructionConstants.OP_POP : 0;
+
+ for (int counter = 1; counter < popCount; counter += 2)
+ {
+ popOpcodes = (popOpcodes << 8) | InstructionConstants.OP_POP2;
+ }
+
+ // Replace or insert them.
+ insertInstructions(offset,
+ replace,
+ before,
+ oldInstruction,
+ popOpcodes);
+ }
+
+
+ /**
+ * Inserts or replaces the given instructions at the given offset.
+ */
+ private void insertInstructions(int offset,
+ boolean replace,
+ boolean before,
+ Instruction oldInstruction,
+ int newOpcodes)
+ {
+ // Is it a suitable (extended) opcode?
+ if (newOpcodes == UNSUPPORTED)
+ {
+ // We can't easily emulate some constructs.
+ throw new UnsupportedOperationException("Can't handle "+oldInstruction.toString(offset));
+ }
+
+ // Mark this instruction.
+ markInstruction(offset);
+
+ // Is it a single new instruction?
+ if ((newOpcodes & ~0xff) == 0)
+ {
+ // Insert or replace the single instruction.
+ insertInstruction(offset,
+ replace,
+ before,
+ oldInstruction,
+ new SimpleInstruction((byte)newOpcodes));
+ }
+ else
+ {
+ // Count the number of instructions.
+ int count = 0;
+ for (int opcodes = newOpcodes; opcodes != 0; opcodes >>>= 8)
+ {
+ count++;
+ }
+
+ Instruction[] newInstructions = new Instruction[count];
+
+ // Collect the instructions.
+ count = 0;
+ for (int opcodes = newOpcodes; opcodes != 0; opcodes >>>= 8)
+ {
+ newInstructions[count++] = new SimpleInstruction((byte)opcodes);
+ }
+
+ // Replace or insert them.
+ insertInstructions(offset,
+ replace,
+ before,
+ oldInstruction,
+ newInstructions);
+ }
+ }
+
+
+ /**
+ * Inserts or replaces the given instruction at the given offset.
+ */
+ private void insertInstruction(int offset,
+ boolean replace,
+ boolean before,
+ Instruction oldInstruction,
+ Instruction newInstruction)
+ {
+ if (replace)
+ {
+ if (newInstruction.opcode == InstructionConstants.OP_NOP)
+ {
+ if (DEBUG) System.out.println(" Deleting marked instruction "+oldInstruction.toString(offset));
+
+ // Delete the instruction.
+ codeAttributeEditor.deleteInstruction(offset);
+
+ if (extraDeletedInstructionVisitor != null)
+ {
+ extraDeletedInstructionVisitor.visitSimpleInstruction(null, null, null, offset, null);
+ }
+ }
+ else if (newInstruction.opcode == oldInstruction.opcode)
+ {
+ if (DEBUG) System.out.println(" Marking unchanged instruction "+oldInstruction.toString(offset));
+
+ // Leave the instruction unchanged.
+ codeAttributeEditor.undeleteInstruction(offset);
+ }
+ else
+ {
+ if (DEBUG) System.out.println(" Replacing instruction "+oldInstruction.toString(offset)+" by "+newInstruction.toString());
+
+ codeAttributeEditor.replaceInstruction(offset, newInstruction);
+ }
+ }
+ else
+ {
+ if (before)
+ {
+ if (DEBUG) System.out.println(" Inserting instruction before "+oldInstruction.toString(offset)+": "+newInstruction.toString());
+
+ codeAttributeEditor.insertBeforeInstruction(offset, newInstruction);
+ }
+ else
+ {
+ if (DEBUG) System.out.println(" Inserting instruction after "+oldInstruction.toString(offset)+": "+newInstruction.toString());
+
+ codeAttributeEditor.insertAfterInstruction(offset, newInstruction);
+ }
+
+ if (extraAddedInstructionVisitor != null)
+ {
+ newInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
+ }
+ }
+ }
+
+
+ /**
+ * Inserts or replaces the given instructions at the given offset.
+ */
+ private void insertInstructions(int offset,
+ boolean replace,
+ boolean before,
+ Instruction oldInstruction,
+ Instruction[] newInstructions)
+ {
+ if (replace)
+ {
+ if (DEBUG) System.out.print(" Replacing instruction "+oldInstruction.toString(offset)+" by");
+
+ codeAttributeEditor.replaceInstruction(offset, newInstructions);
+
+ if (extraDeletedInstructionVisitor != null)
+ {
+ extraDeletedInstructionVisitor.visitSimpleInstruction(null, null, null, offset, null);
+ }
+ }
+ else
+ {
+ if (before)
+ {
+ if (DEBUG) System.out.print(" Inserting before instruction "+oldInstruction.toString(offset)+":");
+
+ codeAttributeEditor.insertBeforeInstruction(offset, newInstructions);
+ }
+ else
+ {
+ if (DEBUG) System.out.print(" Inserting after instruction "+oldInstruction.toString(offset)+":");
+
+ codeAttributeEditor.insertAfterInstruction(offset, newInstructions);
+ }
+ }
+
+
+ if (extraAddedInstructionVisitor != null)
+ {
+ for (int index = 0; index < newInstructions.length; index++)
+ {
+ newInstructions[index].accept(null, null, null, offset, extraAddedInstructionVisitor);
+ }
+ }
+
+ if (DEBUG)
+ {
+ for (int index = 0; index < newInstructions.length; index++)
+ {
+ System.out.print(" "+newInstructions[index].toString());
+ }
+ System.out.println();
+ }
+ }
+
+
+ /**
+ * Replaces the instruction at a given offset by a static invocation.
+ */
+ private void replaceByStaticInvocation(Clazz clazz,
+ int offset,
+ ConstantInstruction constantInstruction)
+ {
+ // Remember the replacement instruction.
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC,
+ constantInstruction.constantIndex);
+
+ if (DEBUG) System.out.println(" Replacing by static invocation "+constantInstruction.toString(offset)+" -> "+replacementInstruction.toString());
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
+ }
+
+
+ /**
+ * Replaces the given instruction by an infinite loop.
+ */
+ private void replaceByInfiniteLoop(Clazz clazz,
+ int offset)
+ {
+ if (DEBUG) System.out.println(" Inserting infinite loop at ["+offset+"]");
+
+ // Mark the instruction.
+ markInstruction(offset);
+
+ // Replace the instruction by an infinite loop.
+ Instruction replacementInstruction =
+ new BranchInstruction(InstructionConstants.OP_GOTO, 0);
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the given instruction is a dup or swap instruction
+ * (dup, dup_x1, dup_x2, dup2, dup2_x1, dup2_x2, swap).
+ */
+ private boolean isDupOrSwap(Instruction instruction)
+ {
+ return instruction.opcode >= InstructionConstants.OP_DUP &&
+ instruction.opcode <= InstructionConstants.OP_SWAP;
+ }
+
+
+ /**
+ * Returns whether the given instruction is a pop instruction
+ * (pop, pop2).
+ */
+ private boolean isPop(Instruction instruction)
+ {
+ return instruction.opcode == InstructionConstants.OP_POP ||
+ instruction.opcode == InstructionConstants.OP_POP2;
+ }
+
+
+ /**
+ * Returns whether any traced but unnecessary instruction between the two
+ * given offsets is branching over the second given offset.
+ */
+ private boolean isAnyUnnecessaryInstructionBranchingOver(int instructionOffset1,
+ int instructionOffset2)
+ {
+ for (int offset = instructionOffset1; offset < instructionOffset2; offset++)
+ {
+ // Is it a traced but unmarked straddling branch?
+ if (partialEvaluator.isTraced(offset) &&
+ !isInstructionNecessary(offset) &&
+ isAnyLargerThan(partialEvaluator.branchTargets(offset),
+ instructionOffset2))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns whether all of the given instruction offsets (at least one)
+ * are smaller than or equal to the given offset.
+ */
+ private boolean isAllSmallerThanOrEqual(InstructionOffsetValue instructionOffsets,
+ int instructionOffset)
+ {
+ if (instructionOffsets != null)
+ {
+ // Loop over all instruction offsets.
+ int branchCount = instructionOffsets.instructionOffsetCount();
+ if (branchCount > 0)
+ {
+ for (int branchIndex = 0; branchIndex < branchCount; branchIndex++)
+ {
+ // Is the offset larger than the reference offset?
+ if (instructionOffsets.instructionOffset(branchIndex) > instructionOffset)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns whether any of the given instruction offsets (at least one)
+ * is larger than the given offset.
+ */
+ private boolean isAnyLargerThan(InstructionOffsetValue instructionOffsets,
+ int instructionOffset)
+ {
+ if (instructionOffsets != null)
+ {
+ // Loop over all instruction offsets.
+ int branchCount = instructionOffsets.instructionOffsetCount();
+ if (branchCount > 0)
+ {
+ for (int branchIndex = 0; branchIndex < branchCount; branchIndex++)
+ {
+ // Is the offset larger than the reference offset?
+ if (instructionOffsets.instructionOffset(branchIndex) > instructionOffset)
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Initializes the necessary data structure.
+ */
+ private void initializeNecessary(CodeAttribute codeAttribute)
+ {
+ int codeLength = codeAttribute.u4codeLength;
+ int maxLocals = codeAttribute.u2maxLocals;
+ int maxStack = codeAttribute.u2maxStack;
+
+ // Create new arrays for storing information at each instruction offset.
+ if (stacksNecessaryAfter.length < codeLength ||
+ stacksNecessaryAfter[0].length < maxStack)
+ {
+ stacksNecessaryAfter = new boolean[codeLength][maxStack];
+ }
+ else
+ {
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ Arrays.fill(stacksNecessaryAfter[offset], 0, maxStack, false);
+ }
+ }
+
+ if (stacksSimplifiedBefore.length < codeLength ||
+ stacksSimplifiedBefore[0].length < maxStack)
+ {
+ stacksSimplifiedBefore = new boolean[codeLength][maxStack];
+ }
+ else
+ {
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ Arrays.fill(stacksSimplifiedBefore[offset], 0, maxStack, false);
+ }
+ }
+
+ if (instructionsNecessary.length < codeLength)
+ {
+ instructionsNecessary = new boolean[codeLength];
+ }
+ else
+ {
+ Arrays.fill(instructionsNecessary, 0, codeLength, false);
+ }
+ }
+
+
+ /**
+ * Returns whether the specified variable is initialized at the specified
+ * offset.
+ */
+ private boolean isVariableInitialization(int instructionOffset,
+ int variableIndex)
+ {
+ // Wasn't the variable set yet?
+ Value valueBefore = simplePartialEvaluator.getVariablesBefore(instructionOffset).getValue(variableIndex);
+ if (valueBefore == null)
+ {
+ return true;
+ }
+
+ // Is the computational type different now?
+ Value valueAfter = simplePartialEvaluator.getVariablesAfter(instructionOffset).getValue(variableIndex);
+ if (valueAfter.computationalType() != valueBefore.computationalType())
+ {
+ return true;
+ }
+
+ // Is the reference type different now?
+ if (valueAfter.computationalType() == Value.TYPE_REFERENCE &&
+ (valueAfter.referenceValue().isNull() == Value.ALWAYS ||
+ !valueAfter.referenceValue().getType().equals(valueBefore.referenceValue().getType())))
+ {
+ return true;
+ }
+
+ // Was the producer an argument (which may be removed)?
+ Value producersBefore = simplePartialEvaluator.getVariablesBefore(instructionOffset).getProducerValue(variableIndex);
+ return producersBefore.instructionOffsetValue().instructionOffsetCount() == 1 &&
+ producersBefore.instructionOffsetValue().instructionOffset(0) == PartialEvaluator.AT_METHOD_ENTRY;
+ }
+
+
+ /**
+ * Marks the stack entry after the given offset.
+ * @param instructionOffset the offset of the stack entry to be marked.
+ * @param stackIndex the index of the stack entry to be marked
+ * (counting from the bottom).
+ */
+ private void markStackEntryAfter(int instructionOffset,
+ int stackIndex)
+ {
+ if (!isStackEntryNecessaryAfter(instructionOffset, stackIndex))
+ {
+ if (DEBUG) System.out.print("["+instructionOffset+".s"+stackIndex+"],");
+
+ stacksNecessaryAfter[instructionOffset][stackIndex] = true;
+
+ if (maxMarkedOffset < instructionOffset)
+ {
+ maxMarkedOffset = instructionOffset;
+ }
+ }
+ }
+
+
+
+ /**
+ * Returns whether the stack specified entries before the given offset are
+ * present.
+ */
+ private boolean isStackEntriesPresentBefore(int instructionOffset,
+ int stackIndex1,
+ int stackIndex2)
+ {
+ boolean present1 = isStackEntryPresentBefore(instructionOffset, stackIndex1);
+ boolean present2 = isStackEntryPresentBefore(instructionOffset, stackIndex2);
+
+// if (present1 ^ present2)
+// {
+// throw new UnsupportedOperationException("Can't handle partial use of dup2 instructions");
+// }
+
+ return present1 || present2;
+ }
+
+
+ /**
+ * Returns whether the specified stack entry before the given offset is
+ * present.
+ * @param instructionOffset the offset of the stack entry to be checked.
+ * @param stackIndex the index of the stack entry to be checked
+ * (counting from the bottom).
+ */
+ private boolean isStackEntryPresentBefore(int instructionOffset,
+ int stackIndex)
+ {
+ TracedStack tracedStack =
+ partialEvaluator.getStackBefore(instructionOffset);
+
+ InstructionOffsetValue producerOffsets =
+ tracedStack.getBottomProducerValue(stackIndex).instructionOffsetValue();
+
+ return isAnyStackEntryNecessaryAfter(producerOffsets, stackIndex);
+ }
+
+
+ /**
+ * Returns whether the stack specified entries after the given offset are
+ * necessary.
+ */
+ private boolean isStackEntriesNecessaryAfter(int instructionOffset,
+ int stackIndex1,
+ int stackIndex2)
+ {
+ boolean present1 = isStackEntryNecessaryAfter(instructionOffset, stackIndex1);
+ boolean present2 = isStackEntryNecessaryAfter(instructionOffset, stackIndex2);
+
+// if (present1 ^ present2)
+// {
+// throw new UnsupportedOperationException("Can't handle partial use of dup2 instructions");
+// }
+
+ return present1 || present2;
+ }
+
+
+ /**
+ * Returns whether any of the stack entries after the given offsets are
+ * necessary.
+ * @param instructionOffsets the offsets of the stack entries to be checked.
+ * @param stackIndex the index of the stack entries to be checked
+ * (counting from the bottom).
+ */
+ private boolean isAnyStackEntryNecessaryAfter(InstructionOffsetValue instructionOffsets,
+ int stackIndex)
+ {
+ int offsetCount = instructionOffsets.instructionOffsetCount();
+
+ for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
+ {
+ if (isStackEntryNecessaryAfter(instructionOffsets.instructionOffset(offsetIndex), stackIndex))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns whether the specified stack entry after the given offset is
+ * necessary.
+ * @param instructionOffset the offset of the stack entry to be checked.
+ * @param stackIndex the index of the stack entry to be checked
+ * (counting from the bottom).
+ */
+ private boolean isStackEntryNecessaryAfter(int instructionOffset,
+ int stackIndex)
+ {
+ return instructionOffset == PartialEvaluator.AT_CATCH_ENTRY ||
+ stacksNecessaryAfter[instructionOffset][stackIndex];
+ }
+
+
+ private void markStackSimplificationBefore(int instructionOffset,
+ int stackIndex)
+ {
+ stacksSimplifiedBefore[instructionOffset][stackIndex] = true;
+ }
+
+
+ private boolean isStackSimplifiedBefore(int instructionOffset,
+ int stackIndex)
+ {
+ return stacksSimplifiedBefore[instructionOffset][stackIndex];
+ }
+
+
+ private void markInstruction(int instructionOffset)
+ {
+ if (!isInstructionNecessary(instructionOffset))
+ {
+ if (DEBUG) System.out.print(instructionOffset+",");
+
+ instructionsNecessary[instructionOffset] = true;
+
+ if (maxMarkedOffset < instructionOffset)
+ {
+ maxMarkedOffset = instructionOffset;
+ }
+ }
+ }
+
+
+ private boolean isAnyInstructionNecessary(int instructionOffset1,
+ int instructionOffset2)
+ {
+ for (int instructionOffset = instructionOffset1;
+ instructionOffset < instructionOffset2;
+ instructionOffset++)
+ {
+ if (isInstructionNecessary(instructionOffset))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns the highest offset of an instruction that has been marked as
+ * necessary, before the given offset.
+ */
+ private int lastNecessaryInstructionOffset(int instructionOffset)
+ {
+ for (int offset = instructionOffset-1; offset >= 0; offset--)
+ {
+ if (isInstructionNecessary(instructionOffset))
+ {
+ return offset;
+ }
+ }
+
+ return 0;
+ }
+
+
+ private boolean isInstructionNecessary(int instructionOffset)
+ {
+ return instructionOffset == PartialEvaluator.AT_METHOD_ENTRY ||
+ instructionsNecessary[instructionOffset];
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/EvaluationSimplifier.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/EvaluationSimplifier.java
new file mode 100644
index 0000000000..2beb43bbc4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/EvaluationSimplifier.java
@@ -0,0 +1,1392 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.ClassPrinter;
+import proguard.evaluation.TracedVariables;
+import proguard.evaluation.value.*;
+import proguard.optimize.info.SideEffectInstructionChecker;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor simplifies the code attributes that it visits, based
+ * on partial evaluation.
+ *
+ * @author Eric Lafortune
+ */
+public class EvaluationSimplifier
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor
+{
+ private static final int POS_ZERO_FLOAT_BITS = Float.floatToIntBits(0.0f);
+ private static final long POS_ZERO_DOUBLE_BITS = Double.doubleToLongBits(0.0);
+
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("es") != null;
+ //*/
+
+ private final InstructionVisitor extraInstructionVisitor;
+
+ private final PartialEvaluator partialEvaluator;
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true, true);
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false, true);
+
+
+ /**
+ * Creates a new EvaluationSimplifier.
+ */
+ public EvaluationSimplifier()
+ {
+ this(new PartialEvaluator(), null);
+ }
+
+
+ /**
+ * Creates a new EvaluationSimplifier.
+ * @param partialEvaluator the partial evaluator that will
+ * execute the code and provide
+ * information about the results.
+ * @param extraInstructionVisitor an optional extra visitor for all
+ * simplified instructions.
+ */
+ public EvaluationSimplifier(PartialEvaluator partialEvaluator,
+ InstructionVisitor extraInstructionVisitor)
+ {
+ this.partialEvaluator = partialEvaluator;
+ this.extraInstructionVisitor = extraInstructionVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ // TODO: Remove this when the evaluation simplifier has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while simplifying instructions after partial evaluation:");
+ System.err.println(" Class = ["+clazz.getName()+"]");
+ System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+ System.err.println("Not optimizing this method");
+
+ if (DEBUG)
+ {
+ method.accept(clazz, new ClassPrinter());
+
+ throw ex;
+ }
+ }
+ }
+
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (DEBUG)
+ {
+ System.out.println();
+ System.out.println("EvaluationSimplifier ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ }
+
+ // Evaluate the method.
+ partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
+ int codeLength = codeAttribute.u4codeLength;
+
+ // Reset the code changes.
+ codeAttributeEditor.reset(codeLength);
+
+ // Replace any instructions that can be simplified.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (partialEvaluator.isTraced(offset))
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+
+ instruction.accept(clazz, method, codeAttribute, offset, this);
+ }
+ }
+
+ // Apply all accumulated changes to the code.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ switch (simpleInstruction.opcode)
+ {
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+ case InstructionConstants.OP_IADD:
+ case InstructionConstants.OP_ISUB:
+ case InstructionConstants.OP_IMUL:
+ case InstructionConstants.OP_IDIV:
+ case InstructionConstants.OP_IREM:
+ case InstructionConstants.OP_INEG:
+ case InstructionConstants.OP_ISHL:
+ case InstructionConstants.OP_ISHR:
+ case InstructionConstants.OP_IUSHR:
+ case InstructionConstants.OP_IAND:
+ case InstructionConstants.OP_IOR:
+ case InstructionConstants.OP_IXOR:
+ case InstructionConstants.OP_L2I:
+ case InstructionConstants.OP_F2I:
+ case InstructionConstants.OP_D2I:
+ case InstructionConstants.OP_I2B:
+ case InstructionConstants.OP_I2C:
+ case InstructionConstants.OP_I2S:
+ case InstructionConstants.OP_ARRAYLENGTH:
+ if (!sideEffectInstructionChecker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ simpleInstruction))
+ {
+ replaceIntegerPushInstruction(clazz, offset, simpleInstruction);
+ }
+ break;
+
+ case InstructionConstants.OP_LALOAD:
+ case InstructionConstants.OP_LADD:
+ case InstructionConstants.OP_LSUB:
+ case InstructionConstants.OP_LMUL:
+ case InstructionConstants.OP_LDIV:
+ case InstructionConstants.OP_LREM:
+ case InstructionConstants.OP_LNEG:
+ case InstructionConstants.OP_LSHL:
+ case InstructionConstants.OP_LSHR:
+ case InstructionConstants.OP_LUSHR:
+ case InstructionConstants.OP_LAND:
+ case InstructionConstants.OP_LOR:
+ case InstructionConstants.OP_LXOR:
+ case InstructionConstants.OP_I2L:
+ case InstructionConstants.OP_F2L:
+ case InstructionConstants.OP_D2L:
+ if (!sideEffectInstructionChecker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ simpleInstruction))
+ {
+ replaceLongPushInstruction(clazz, offset, simpleInstruction);
+ }
+ break;
+
+ case InstructionConstants.OP_FALOAD:
+ case InstructionConstants.OP_FADD:
+ case InstructionConstants.OP_FSUB:
+ case InstructionConstants.OP_FMUL:
+ case InstructionConstants.OP_FDIV:
+ case InstructionConstants.OP_FREM:
+ case InstructionConstants.OP_FNEG:
+ case InstructionConstants.OP_I2F:
+ case InstructionConstants.OP_L2F:
+ case InstructionConstants.OP_D2F:
+ if (!sideEffectInstructionChecker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ simpleInstruction))
+ {
+ replaceFloatPushInstruction(clazz, offset, simpleInstruction);
+ }
+ break;
+
+ case InstructionConstants.OP_DALOAD:
+ case InstructionConstants.OP_DADD:
+ case InstructionConstants.OP_DSUB:
+ case InstructionConstants.OP_DMUL:
+ case InstructionConstants.OP_DDIV:
+ case InstructionConstants.OP_DREM:
+ case InstructionConstants.OP_DNEG:
+ case InstructionConstants.OP_I2D:
+ case InstructionConstants.OP_L2D:
+ case InstructionConstants.OP_F2D:
+ if (!sideEffectInstructionChecker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ simpleInstruction))
+ {
+ replaceDoublePushInstruction(clazz, offset, simpleInstruction);
+ }
+ break;
+
+ case InstructionConstants.OP_AALOAD:
+ if (!sideEffectInstructionChecker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ simpleInstruction))
+ {
+ replaceReferencePushInstruction(clazz, offset, simpleInstruction);
+ }
+ break;
+ }
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ int variableIndex = variableInstruction.variableIndex;
+
+ switch (variableInstruction.opcode)
+ {
+ case InstructionConstants.OP_ILOAD:
+ case InstructionConstants.OP_ILOAD_0:
+ case InstructionConstants.OP_ILOAD_1:
+ case InstructionConstants.OP_ILOAD_2:
+ case InstructionConstants.OP_ILOAD_3:
+ replaceIntegerPushInstruction(clazz, offset, variableInstruction, variableIndex);
+ break;
+
+ case InstructionConstants.OP_LLOAD:
+ case InstructionConstants.OP_LLOAD_0:
+ case InstructionConstants.OP_LLOAD_1:
+ case InstructionConstants.OP_LLOAD_2:
+ case InstructionConstants.OP_LLOAD_3:
+ replaceLongPushInstruction(clazz, offset, variableInstruction, variableIndex);
+ break;
+
+ case InstructionConstants.OP_FLOAD:
+ case InstructionConstants.OP_FLOAD_0:
+ case InstructionConstants.OP_FLOAD_1:
+ case InstructionConstants.OP_FLOAD_2:
+ case InstructionConstants.OP_FLOAD_3:
+ replaceFloatPushInstruction(clazz, offset, variableInstruction, variableIndex);
+ break;
+
+ case InstructionConstants.OP_DLOAD:
+ case InstructionConstants.OP_DLOAD_0:
+ case InstructionConstants.OP_DLOAD_1:
+ case InstructionConstants.OP_DLOAD_2:
+ case InstructionConstants.OP_DLOAD_3:
+ replaceDoublePushInstruction(clazz, offset, variableInstruction, variableIndex);
+ break;
+
+ case InstructionConstants.OP_ALOAD:
+ case InstructionConstants.OP_ALOAD_0:
+ case InstructionConstants.OP_ALOAD_1:
+ case InstructionConstants.OP_ALOAD_2:
+ case InstructionConstants.OP_ALOAD_3:
+ replaceReferencePushInstruction(clazz, offset, variableInstruction);
+ break;
+
+ case InstructionConstants.OP_ASTORE:
+ case InstructionConstants.OP_ASTORE_0:
+ case InstructionConstants.OP_ASTORE_1:
+ case InstructionConstants.OP_ASTORE_2:
+ case InstructionConstants.OP_ASTORE_3:
+ deleteReferencePopInstruction(clazz, offset, variableInstruction);
+ break;
+
+ case InstructionConstants.OP_RET:
+ replaceBranchInstruction(clazz, offset, variableInstruction);
+ break;
+ }
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_GETFIELD:
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ if (constantInstruction.stackPushCount(clazz) > 0 &&
+ !sideEffectInstructionChecker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ constantInstruction))
+ {
+ replaceAnyPushInstruction(clazz, offset, constantInstruction);
+ }
+
+ break;
+
+ case InstructionConstants.OP_CHECKCAST:
+ replaceReferencePushInstruction(clazz, offset, constantInstruction);
+ break;
+ }
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ switch (branchInstruction.opcode)
+ {
+ case InstructionConstants.OP_GOTO:
+ case InstructionConstants.OP_GOTO_W:
+ // Don't replace unconditional branches.
+ break;
+
+ case InstructionConstants.OP_JSR:
+ case InstructionConstants.OP_JSR_W:
+ replaceJsrInstruction(clazz, offset, branchInstruction);
+ break;
+
+ default:
+ replaceBranchInstruction(clazz, offset, branchInstruction);
+ break;
+ }
+ }
+
+
+ public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
+ {
+ // First try to simplify it to a simple branch.
+ replaceBranchInstruction(clazz, offset, tableSwitchInstruction);
+
+ // Otherwise try to simplify simple enum switches.
+ if (!codeAttributeEditor.isModified(offset))
+ {
+ replaceSimpleEnumSwitchInstruction(clazz,
+ codeAttribute,
+ offset,
+ tableSwitchInstruction);
+
+ // Otherwise make sure all branch targets are valid.
+ if (!codeAttributeEditor.isModified(offset))
+ {
+ cleanUpSwitchInstruction(clazz, offset, tableSwitchInstruction);
+
+ trimSwitchInstruction(clazz, offset, tableSwitchInstruction);
+ }
+ }
+ }
+
+
+ public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
+ {
+ // First try to simplify it to a simple branch.
+ replaceBranchInstruction(clazz, offset, lookUpSwitchInstruction);
+
+ // Otherwise try to simplify simple enum switches.
+ if (!codeAttributeEditor.isModified(offset))
+ {
+ replaceSimpleEnumSwitchInstruction(clazz,
+ codeAttribute,
+ offset,
+ lookUpSwitchInstruction);
+
+ // Otherwise make sure all branch targets are valid.
+ if (!codeAttributeEditor.isModified(offset))
+ {
+ cleanUpSwitchInstruction(clazz, offset, lookUpSwitchInstruction);
+
+ trimSwitchInstruction(clazz, offset, lookUpSwitchInstruction);
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Replaces the push instruction at the given offset by a simpler push
+ * instruction, if possible.
+ */
+ private void replaceAnyPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
+ if (pushedValue.isParticular())
+ {
+ switch (pushedValue.computationalType())
+ {
+ case Value.TYPE_INTEGER:
+ replaceIntegerPushInstruction(clazz, offset, instruction);
+ break;
+ case Value.TYPE_LONG:
+ replaceLongPushInstruction(clazz, offset, instruction);
+ break;
+ case Value.TYPE_FLOAT:
+ replaceFloatPushInstruction(clazz, offset, instruction);
+ break;
+ case Value.TYPE_DOUBLE:
+ replaceDoublePushInstruction(clazz, offset, instruction);
+ break;
+ case Value.TYPE_REFERENCE:
+ replaceReferencePushInstruction(clazz, offset, instruction);
+ break;
+ }
+ }
+ }
+
+
+ /**
+ * Replaces the integer pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
+ */
+ private void replaceIntegerPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ replaceIntegerPushInstruction(clazz,
+ offset,
+ instruction,
+ partialEvaluator.getVariablesBefore(offset).size());
+ }
+
+
+ /**
+ * Replaces the integer pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
+ */
+ private void replaceIntegerPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ int maxVariableIndex)
+ {
+ Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
+ if (pushedValue.isParticular())
+ {
+ // Push a constant instead.
+ int value = pushedValue.integerValue().value();
+ if ((short)value == value)
+ {
+ replaceConstantPushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_SIPUSH,
+ value);
+ }
+ else
+ {
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
+
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_LDC,
+ constantPoolEditor.addIntegerConstant(value));
+
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
+ }
+ }
+ else if (pushedValue.isSpecific())
+ {
+ // Load an equivalent lower-numbered variable instead, if any.
+ TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
+ for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
+ {
+ if (pushedValue.equals(variables.load(variableIndex)))
+ {
+ replaceVariablePushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_ILOAD,
+ variableIndex);
+ break;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Replaces the long pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
+ */
+ private void replaceLongPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ replaceLongPushInstruction(clazz,
+ offset,
+ instruction,
+ partialEvaluator.getVariablesBefore(offset).size());
+ }
+
+
+ /**
+ * Replaces the long pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
+ */
+ private void replaceLongPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ int maxVariableIndex)
+ {
+ Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
+ if (pushedValue.isParticular())
+ {
+ // Push a constant instead.
+ long value = pushedValue.longValue().value();
+ if (value == 0L ||
+ value == 1L)
+ {
+ replaceConstantPushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_LCONST_0,
+ (int)value);
+ }
+ else
+ {
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
+
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W,
+ constantPoolEditor.addLongConstant(value));
+
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
+ }
+ }
+ else if (pushedValue.isSpecific())
+ {
+ // Load an equivalent lower-numbered variable instead, if any.
+ TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
+ for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
+ {
+ // Note that we have to check the second part as well.
+ if (pushedValue.equals(variables.load(variableIndex)) &&
+ variables.load(variableIndex + 1) != null &&
+ variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
+ {
+ replaceVariablePushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_LLOAD,
+ variableIndex);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Replaces the float pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
+ */
+ private void replaceFloatPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ replaceFloatPushInstruction(clazz,
+ offset,
+ instruction,
+ partialEvaluator.getVariablesBefore(offset).size());
+ }
+
+
+ /**
+ * Replaces the float pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
+ */
+ private void replaceFloatPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ int maxVariableIndex)
+ {
+ Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
+ if (pushedValue.isParticular())
+ {
+ // Push a constant instead.
+ // Make sure to distinguish between +0.0 and -0.0.
+ float value = pushedValue.floatValue().value();
+ if (value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS ||
+ value == 1.0f ||
+ value == 2.0f)
+ {
+ replaceConstantPushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_FCONST_0,
+ (int)value);
+ }
+ else
+ {
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
+
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_LDC,
+ constantPoolEditor.addFloatConstant(value));
+
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
+ }
+ }
+ else if (pushedValue.isSpecific())
+ {
+ // Load an equivalent lower-numbered variable instead, if any.
+ TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
+ for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
+ {
+ if (pushedValue.equals(variables.load(variableIndex)))
+ {
+ replaceVariablePushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_FLOAD,
+ variableIndex);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Replaces the double pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
+ */
+ private void replaceDoublePushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ replaceDoublePushInstruction(clazz,
+ offset,
+ instruction,
+ partialEvaluator.getVariablesBefore(offset).size());
+ }
+
+
+ /**
+ * Replaces the double pushing instruction at the given offset by a simpler
+ * push instruction, if possible.
+ */
+ private void replaceDoublePushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ int maxVariableIndex)
+ {
+ Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
+ if (pushedValue.isParticular())
+ {
+ // Push a constant instead.
+ // Make sure to distinguish between +0.0 and -0.0.
+ double value = pushedValue.doubleValue().value();
+ if (value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS ||
+ value == 1.0)
+ {
+ replaceConstantPushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_DCONST_0,
+ (int)value);
+ }
+ else
+ {
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
+
+ Instruction replacementInstruction =
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W,
+ constantPoolEditor.addDoubleConstant(value));
+
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
+ }
+ }
+ else if (pushedValue.isSpecific())
+ {
+ // Load an equivalent lower-numbered variable instead, if any.
+ TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
+ for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
+ {
+ // Note that we have to check the second part as well.
+ if (pushedValue.equals(variables.load(variableIndex)) &&
+ variables.load(variableIndex + 1) != null &&
+ variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
+ {
+ replaceVariablePushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_DLOAD,
+ variableIndex);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Replaces the reference pushing instruction at the given offset by a
+ * simpler push instruction, if possible.
+ */
+ private void replaceReferencePushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
+ if (pushedValue.isParticular())
+ {
+ // A reference value can only be specific if it is null.
+ replaceConstantPushInstruction(clazz,
+ offset,
+ instruction,
+ InstructionConstants.OP_ACONST_NULL,
+ 0);
+ }
+ }
+
+
+ /**
+ * Replaces the instruction at a given offset by a given push instruction
+ * of a constant.
+ */
+ private void replaceConstantPushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ byte replacementOpcode,
+ int value)
+ {
+ Instruction replacementInstruction =
+ new SimpleInstruction(replacementOpcode, value);
+
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
+ }
+
+
+ /**
+ * Replaces the instruction at a given offset by a given push instruction
+ * of a variable.
+ */
+ private void replaceVariablePushInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ byte replacementOpcode,
+ int variableIndex)
+ {
+ Instruction replacementInstruction =
+ new VariableInstruction(replacementOpcode, variableIndex);
+
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
+ }
+
+
+ /**
+ * Replaces the given 'jsr' instruction by a simpler branch instruction,
+ * if it jumps to a subroutine that doesn't return or a subroutine that
+ * is only called from one place.
+ */
+ private void replaceJsrInstruction(Clazz clazz,
+ int offset,
+ BranchInstruction branchInstruction)
+ {
+ // Is the subroutine ever returning?
+ int subroutineStart = offset + branchInstruction.branchOffset;
+ if (!partialEvaluator.isSubroutineReturning(subroutineStart) ||
+ partialEvaluator.branchOrigins(subroutineStart).instructionOffsetCount() == 1)
+ {
+ // All 'jsr' instructions to this subroutine can be replaced
+ // by unconditional branch instructions.
+ replaceBranchInstruction(clazz, offset, branchInstruction);
+ }
+ else if (!partialEvaluator.isTraced(offset + branchInstruction.length(offset)))
+ {
+ // We have to make sure the instruction after this 'jsr'
+ // instruction is valid, even if it is never reached.
+ replaceByInfiniteLoop(clazz, offset + branchInstruction.length(offset), branchInstruction);
+ }
+ }
+
+
+ /**
+ * Deletes the reference popping instruction at the given offset, if
+ * it is at the start of a subroutine that doesn't return or a subroutine
+ * that is only called from one place.
+ */
+ private void deleteReferencePopInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ if (partialEvaluator.isSubroutineStart(offset) &&
+ (!partialEvaluator.isSubroutineReturning(offset) ||
+ partialEvaluator.branchOrigins(offset).instructionOffsetCount() == 1))
+ {
+ if (DEBUG) System.out.println(" Deleting store of subroutine return address "+instruction.toString(offset));
+
+ // A reference value can only be specific if it is null.
+ codeAttributeEditor.deleteInstruction(offset);
+ }
+ }
+
+
+ /**
+ * Deletes the given branch instruction, or replaces it by a simpler branch
+ * instruction, if possible.
+ */
+ private void replaceBranchInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset);
+
+ // Is there exactly one branch target (not from a goto or jsr)?
+ if (branchTargets != null &&
+ branchTargets.instructionOffsetCount() == 1)
+ {
+ // Is it branching to the next instruction?
+ int branchOffset = branchTargets.instructionOffset(0) - offset;
+ if (branchOffset == instruction.length(offset))
+ {
+ if (DEBUG) System.out.println(" Ignoring zero branch instruction at ["+offset+"]");
+ }
+ else
+ {
+ // Replace the branch instruction by a simple branch instruction.
+ Instruction replacementInstruction =
+ new BranchInstruction(InstructionConstants.OP_GOTO,
+ branchOffset);
+
+ replaceInstruction(clazz, offset, instruction, replacementInstruction);
+ }
+ }
+ }
+
+
+ /**
+ * Replaces the given table switch instruction, if it is based on the value
+ * of a fixed array. This is typical for switches on simple enums.
+ */
+ private void replaceSimpleEnumSwitchInstruction(Clazz clazz,
+ CodeAttribute codeAttribute,
+ int offset,
+ TableSwitchInstruction tableSwitchInstruction)
+ {
+ // Check if the switch instruction is consuming a single value loaded
+ // from a fully specified array.
+ InstructionOffsetValue producerOffsets =
+ partialEvaluator.getStackBefore(offset).getTopProducerValue(0).instructionOffsetValue();
+
+ if (producerOffsets.instructionOffsetCount() == 1)
+ {
+ int producerOffset = producerOffsets.instructionOffset(0);
+
+ if (codeAttribute.code[producerOffset] == InstructionConstants.OP_IALOAD &&
+ !codeAttributeEditor.isModified(producerOffset))
+ {
+ ReferenceValue referenceValue =
+ partialEvaluator.getStackBefore(producerOffset).getTop(1).referenceValue();
+
+ if (referenceValue.isParticular())
+ {
+ // Simplify the entire construct.
+ replaceSimpleEnumSwitchInstruction(clazz,
+ codeAttribute,
+ producerOffset,
+ offset,
+ tableSwitchInstruction,
+ referenceValue);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Replaces the given table switch instruction that is based on a value of
+ * the given fixed array.
+ */
+ private void replaceSimpleEnumSwitchInstruction(Clazz clazz,
+ CodeAttribute codeAttribute,
+ int loadOffset,
+ int switchOffset,
+ TableSwitchInstruction tableSwitchInstruction,
+ ReferenceValue mappingValue)
+ {
+ ValueFactory valueFactory = new ParticularValueFactory();
+
+ // Transform the jump offsets.
+ int[] jumpOffsets = tableSwitchInstruction.jumpOffsets;
+ int[] newJumpOffsets = new int[mappingValue.arrayLength(valueFactory).value()];
+
+ for (int index = 0; index < newJumpOffsets.length; index++)
+ {
+ int switchCase =
+ mappingValue.integerArrayLoad(valueFactory.createIntegerValue(
+ index),
+ valueFactory).value();
+
+ newJumpOffsets[index] =
+ switchCase >= tableSwitchInstruction.lowCase &&
+ switchCase <= tableSwitchInstruction.highCase ?
+ jumpOffsets[switchCase - tableSwitchInstruction.lowCase] :
+ tableSwitchInstruction.defaultOffset;
+ }
+
+ // Update the instruction.
+ tableSwitchInstruction.lowCase = 0;
+ tableSwitchInstruction.highCase = newJumpOffsets.length - 1;
+ tableSwitchInstruction.jumpOffsets = newJumpOffsets;
+
+ // Replace the original one with the new version.
+ replaceSimpleEnumSwitchInstruction(clazz,
+ loadOffset,
+ switchOffset,
+ tableSwitchInstruction);
+
+ cleanUpSwitchInstruction(clazz, switchOffset, tableSwitchInstruction);
+
+ trimSwitchInstruction(clazz, switchOffset, tableSwitchInstruction);
+ }
+
+
+ /**
+ * Replaces the given look up switch instruction, if it is based on the
+ * value of a fixed array. This is typical for switches on simple enums.
+ */
+ private void replaceSimpleEnumSwitchInstruction(Clazz clazz,
+ CodeAttribute codeAttribute,
+ int offset,
+ LookUpSwitchInstruction lookupSwitchInstruction)
+ {
+ // Check if the switch instruction is consuming a single value loaded
+ // from a fully specified array.
+ InstructionOffsetValue producerOffsets =
+ partialEvaluator.getStackBefore(offset).getTopProducerValue(0).instructionOffsetValue();
+
+ if (producerOffsets.instructionOffsetCount() == 1)
+ {
+ int producerOffset = producerOffsets.instructionOffset(0);
+
+ if (codeAttribute.code[producerOffset] == InstructionConstants.OP_IALOAD &&
+ !codeAttributeEditor.isModified(producerOffset))
+ {
+ ReferenceValue referenceValue =
+ partialEvaluator.getStackBefore(producerOffset).getTop(1).referenceValue();
+
+ if (referenceValue.isParticular())
+ {
+ // Simplify the entire construct.
+ replaceSimpleEnumSwitchInstruction(clazz,
+ codeAttribute,
+ producerOffset,
+ offset,
+ lookupSwitchInstruction,
+ referenceValue);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Replaces the given look up switch instruction that is based on a value of
+ * the given fixed array. This is typical for switches on simple enums.
+ */
+ private void replaceSimpleEnumSwitchInstruction(Clazz clazz,
+ CodeAttribute codeAttribute,
+ int loadOffset,
+ int switchOffset,
+ LookUpSwitchInstruction lookupSwitchInstruction,
+ ReferenceValue mappingValue)
+ {
+ ValueFactory valueFactory = new ParticularValueFactory();
+
+ // Transform the jump offsets.
+ int[] cases = lookupSwitchInstruction.cases;
+ int[] jumpOffsets = lookupSwitchInstruction.jumpOffsets;
+ int[] newJumpOffsets = new int[mappingValue.arrayLength(valueFactory).value()];
+
+ for (int index = 0; index < newJumpOffsets.length; index++)
+ {
+ int switchCase =
+ mappingValue.integerArrayLoad(valueFactory.createIntegerValue(index),
+ valueFactory).value();
+
+ int caseIndex = Arrays.binarySearch(cases, switchCase);
+
+ newJumpOffsets[index] = caseIndex >= 0 ?
+ jumpOffsets[caseIndex] :
+ lookupSwitchInstruction.defaultOffset;
+ }
+
+ // Replace the original lookup switch with a table switch.
+ TableSwitchInstruction replacementSwitchInstruction =
+ new TableSwitchInstruction(InstructionConstants.OP_TABLESWITCH,
+ lookupSwitchInstruction.defaultOffset,
+ 0,
+ newJumpOffsets.length - 1,
+ newJumpOffsets);
+
+ replaceSimpleEnumSwitchInstruction(clazz,
+ loadOffset,
+ switchOffset,
+ replacementSwitchInstruction);
+
+ cleanUpSwitchInstruction(clazz, switchOffset, replacementSwitchInstruction);
+
+ trimSwitchInstruction(clazz, switchOffset, replacementSwitchInstruction);
+ }
+
+
+ /**
+ * Makes sure all branch targets of the given switch instruction are valid.
+ */
+ private void cleanUpSwitchInstruction(Clazz clazz,
+ int offset,
+ SwitchInstruction switchInstruction)
+ {
+ // Get the actual branch targets.
+ InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset);
+
+ // Get an offset that can serve as a valid default offset.
+ int defaultOffset =
+ branchTargets.instructionOffset(branchTargets.instructionOffsetCount()-1) -
+ offset;
+
+ Instruction replacementInstruction = null;
+
+ // Check the jump offsets.
+ int[] jumpOffsets = switchInstruction.jumpOffsets;
+ for (int index = 0; index < jumpOffsets.length; index++)
+ {
+ if (!branchTargets.contains(offset + jumpOffsets[index]))
+ {
+ // Replace the unused offset.
+ jumpOffsets[index] = defaultOffset;
+
+ // Remember to replace the instruction.
+ replacementInstruction = switchInstruction;
+ }
+ }
+
+ // Check the default offset.
+ if (!branchTargets.contains(offset + switchInstruction.defaultOffset))
+ {
+ // Replace the unused offset.
+ switchInstruction.defaultOffset = defaultOffset;
+
+ // Remember to replace the instruction.
+ replacementInstruction = switchInstruction;
+ }
+
+ if (replacementInstruction != null)
+ {
+ replaceInstruction(clazz, offset, switchInstruction, replacementInstruction);
+ }
+ }
+
+
+ /**
+ * Trims redundant offsets from the given switch instruction.
+ */
+ private void trimSwitchInstruction(Clazz clazz,
+ int offset,
+ TableSwitchInstruction tableSwitchInstruction)
+ {
+ // Get an offset that can serve as a valid default offset.
+ int defaultOffset = tableSwitchInstruction.defaultOffset;
+ int[] jumpOffsets = tableSwitchInstruction.jumpOffsets;
+ int length = jumpOffsets.length;
+
+ // Find the lowest index with a non-default jump offset.
+ int lowIndex = 0;
+ while (lowIndex < length &&
+ jumpOffsets[lowIndex] == defaultOffset)
+ {
+ lowIndex++;
+ }
+
+ // Find the highest index with a non-default jump offset.
+ int highIndex = length - 1;
+ while (highIndex >= 0 &&
+ jumpOffsets[highIndex] == defaultOffset)
+ {
+ highIndex--;
+ }
+
+ // Can we use a shorter array?
+ int newLength = highIndex - lowIndex + 1;
+ if (newLength < length)
+ {
+ if (newLength <= 0)
+ {
+ // Replace the switch instruction by a simple branch instruction.
+ Instruction replacementInstruction =
+ new BranchInstruction(InstructionConstants.OP_GOTO,
+ defaultOffset);
+
+ replaceInstruction(clazz, offset, tableSwitchInstruction,
+ replacementInstruction);
+ }
+ else
+ {
+ // Trim the array.
+ int[] newJumpOffsets = new int[newLength];
+
+ System.arraycopy(jumpOffsets, lowIndex, newJumpOffsets, 0, newLength);
+
+ tableSwitchInstruction.jumpOffsets = newJumpOffsets;
+ tableSwitchInstruction.lowCase += lowIndex;
+ tableSwitchInstruction.highCase -= length - newLength - lowIndex;
+
+ replaceInstruction(clazz, offset, tableSwitchInstruction,
+ tableSwitchInstruction);
+ }
+ }
+ }
+
+
+ /**
+ * Trims redundant offsets from the given switch instruction.
+ */
+ private void trimSwitchInstruction(Clazz clazz,
+ int offset,
+ LookUpSwitchInstruction lookUpSwitchInstruction)
+ {
+ // Get an offset that can serve as a valid default offset.
+ int defaultOffset = lookUpSwitchInstruction.defaultOffset;
+ int[] jumpOffsets = lookUpSwitchInstruction.jumpOffsets;
+ int length = jumpOffsets.length;
+ int newLength = length;
+
+ // Count the default jump offsets.
+ for (int index = 0; index < length; index++)
+ {
+ if (jumpOffsets[index] == defaultOffset)
+ {
+ newLength--;
+ }
+ }
+
+ // Can we use shorter arrays?
+ if (newLength < length)
+ {
+ if (newLength <= 0)
+ {
+ // Replace the switch instruction by a simple branch instruction.
+ Instruction replacementInstruction =
+ new BranchInstruction(InstructionConstants.OP_GOTO,
+ defaultOffset);
+
+ replaceInstruction(clazz, offset, lookUpSwitchInstruction,
+ replacementInstruction);
+ }
+ else
+ {
+ // Remove redundant entries from the arrays.
+ int[] cases = lookUpSwitchInstruction.cases;
+ int[] newJumpOffsets = new int[newLength];
+ int[] newCases = new int[newLength];
+
+ int newIndex = 0;
+
+ for (int index = 0; index < length; index++)
+ {
+ if (jumpOffsets[index] != defaultOffset)
+ {
+ newJumpOffsets[newIndex] = jumpOffsets[index];
+ newCases[newIndex++] = cases[index];
+ }
+ }
+
+ lookUpSwitchInstruction.jumpOffsets = newJumpOffsets;
+ lookUpSwitchInstruction.cases = newCases;
+
+ replaceInstruction(clazz, offset, lookUpSwitchInstruction,
+ lookUpSwitchInstruction);
+ }
+ }
+ }
+
+
+ /**
+ * Replaces the given instruction by an infinite loop.
+ */
+ private void replaceByInfiniteLoop(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ // Replace the instruction by an infinite loop.
+ Instruction replacementInstruction =
+ new BranchInstruction(InstructionConstants.OP_GOTO, 0);
+
+ if (DEBUG) System.out.println(" Replacing unreachable instruction by infinite loop "+replacementInstruction.toString(offset));
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ // Note: we're not passing the right arguments for now, knowing that
+ // they aren't used anyway.
+ instruction.accept(clazz,
+ null,
+ null,
+ offset,
+ extraInstructionVisitor);
+ }
+ }
+
+
+ /**
+ * Replaces the instruction at a given offset by a given push instruction.
+ */
+ private void replaceInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ Instruction replacementInstruction)
+ {
+ // Pop unneeded stack entries if necessary.
+ int popCount =
+ instruction.stackPopCount(clazz) -
+ replacementInstruction.stackPopCount(clazz);
+
+ insertPopInstructions(offset, popCount);
+
+ if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstruction.toString()+(popCount == 0 ? "" : " ("+popCount+" pops)"));
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ // Note: we're not passing the right arguments for now, knowing that
+ // they aren't used anyway.
+ instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
+ }
+ }
+
+
+ /**
+ * Pops the given number of stack entries before the instruction at the
+ * given offset.
+ */
+ private void insertPopInstructions(int offset, int popCount)
+ {
+ switch (popCount)
+ {
+ case 0:
+ {
+ break;
+ }
+ case 1:
+ {
+ // Insert a single pop instruction.
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP);
+
+ codeAttributeEditor.insertBeforeInstruction(offset,
+ popInstruction);
+ break;
+ }
+ case 2:
+ {
+ // Insert a single pop2 instruction.
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP2);
+
+ codeAttributeEditor.insertBeforeInstruction(offset,
+ popInstruction);
+ break;
+ }
+ default:
+ {
+ // Insert the specified number of pop instructions.
+ Instruction[] popInstructions =
+ new Instruction[popCount / 2 + popCount % 2];
+
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP2);
+
+ for (int index = 0; index < popCount / 2; index++)
+ {
+ popInstructions[index] = popInstruction;
+ }
+
+ if (popCount % 2 == 1)
+ {
+ popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP);
+
+ popInstructions[popCount / 2] = popInstruction;
+ }
+
+ codeAttributeEditor.insertBeforeInstruction(offset,
+ popInstructions);
+ break;
+ }
+ }
+ }
+
+
+ /**
+ * Replaces the simple enum switch instructions at a given offsets by a
+ * given replacement instruction.
+ */
+ private void replaceSimpleEnumSwitchInstruction(Clazz clazz,
+ int loadOffset,
+ int switchOffset,
+ SwitchInstruction replacementSwitchInstruction)
+ {
+ if (DEBUG) System.out.println(" Replacing switch instruction at ["+switchOffset+"] -> ["+loadOffset+"] swap + pop, "+replacementSwitchInstruction.toString(switchOffset)+")");
+
+ // Remove the array load instruction.
+ codeAttributeEditor.replaceInstruction(loadOffset, new Instruction[]
+ {
+ new SimpleInstruction(InstructionConstants.OP_SWAP),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ });
+
+ // Replace the switch instruction.
+ codeAttributeEditor.replaceInstruction(switchOffset, replacementSwitchInstruction);
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ // Note: we're not passing the right arguments for now, knowing that
+ // they aren't used anyway.
+ replacementSwitchInstruction.accept(clazz,
+ null,
+ null,
+ switchOffset,
+ extraInstructionVisitor);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/LivenessAnalyzer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/LivenessAnalyzer.java
new file mode 100644
index 0000000000..bfcb62959d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/LivenessAnalyzer.java
@@ -0,0 +1,526 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.evaluation.value.*;
+
+/**
+ * This AttributeVisitor analyzes the liveness of the variables in the code
+ * attributes that it visits, based on partial evaluation.
+ *
+ * @author Eric Lafortune
+ */
+public class LivenessAnalyzer
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ExceptionInfoVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("la") != null;
+ //*/
+
+ private static final int MAX_VARIABLES_SIZE = 64;
+
+ private final PartialEvaluator partialEvaluator;
+
+ private long[] isAliveBefore = new long[ClassConstants.TYPICAL_CODE_LENGTH];
+ private long[] isAliveAfter = new long[ClassConstants.TYPICAL_CODE_LENGTH];
+ private long[] isCategory2 = new long[ClassConstants.TYPICAL_CODE_LENGTH];
+
+ // Fields acting as global temporary variables.
+ private boolean checkAgain;
+ private long alive;
+
+
+ /**
+ * Creates a new LivenessAnalyzer.
+ */
+ public LivenessAnalyzer()
+ {
+ this(new PartialEvaluator());
+ }
+
+
+ /**
+ * Creates a new LivenessAnalyzer that will use the given partial evaluator.
+ * It will run this evaluator on every code attribute that it visits.
+ */
+ public LivenessAnalyzer(PartialEvaluator partialEvaluator)
+ {
+ this.partialEvaluator = partialEvaluator;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset has ever been
+ * executed during the partial evaluation.
+ */
+ public boolean isTraced(int instructionOffset)
+ {
+ return partialEvaluator.isTraced(instructionOffset);
+ }
+
+
+ /**
+ * Returns whether the specified variable is alive before the instruction
+ * at the given offset.
+ */
+ public boolean isAliveBefore(int instructionOffset, int variableIndex)
+ {
+ return variableIndex >= MAX_VARIABLES_SIZE ||
+ (isAliveBefore[instructionOffset] & (1L << variableIndex)) != 0;
+ }
+
+
+ /**
+ * Sets whether the specified variable is alive before the instruction
+ * at the given offset.
+ */
+ public void setAliveBefore(int instructionOffset, int variableIndex, boolean alive)
+ {
+ if (variableIndex < MAX_VARIABLES_SIZE)
+ {
+ if (alive)
+ {
+ isAliveBefore[instructionOffset] |= 1L << variableIndex;
+ }
+ else
+ {
+ isAliveBefore[instructionOffset] &= ~(1L << variableIndex);
+ }
+ }
+ }
+
+
+ /**
+ * Returns whether the specified variable is alive after the instruction
+ * at the given offset.
+ */
+ public boolean isAliveAfter(int instructionOffset, int variableIndex)
+ {
+ return variableIndex >= MAX_VARIABLES_SIZE ||
+ (isAliveAfter[instructionOffset] & (1L << variableIndex)) != 0;
+ }
+
+
+ /**
+ * Sets whether the specified variable is alive after the instruction
+ * at the given offset.
+ */
+ public void setAliveAfter(int instructionOffset, int variableIndex, boolean alive)
+ {
+ if (variableIndex < MAX_VARIABLES_SIZE)
+ {
+ if (alive)
+ {
+ isAliveAfter[instructionOffset] |= 1L << variableIndex;
+ }
+ else
+ {
+ isAliveAfter[instructionOffset] &= ~(1L << variableIndex);
+ }
+ }
+ }
+
+
+ /**
+ * Returns whether the specified variable takes up two entries after the
+ * instruction at the given offset.
+ */
+ public boolean isCategory2(int instructionOffset, int variableIndex)
+ {
+ return variableIndex < MAX_VARIABLES_SIZE &&
+ (isCategory2[instructionOffset] & (1L << variableIndex)) != 0;
+ }
+
+
+ /**
+ * Sets whether the specified variable takes up two entries after the
+ * instruction at the given offset.
+ */
+ public void setCategory2(int instructionOffset, int variableIndex, boolean category2)
+ {
+ if (variableIndex < MAX_VARIABLES_SIZE)
+ {
+ if (category2)
+ {
+ isCategory2[instructionOffset] |= 1L << variableIndex;
+ }
+ else
+ {
+ isCategory2[instructionOffset] &= ~(1L << variableIndex);
+ }
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ if (DEBUG)
+ {
+ System.out.println();
+ System.out.println("Liveness analysis: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ }
+
+ // Initialize the global arrays.
+ initializeArrays(codeAttribute);
+
+ // Evaluate the method.
+ partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
+ int codeLength = codeAttribute.u4codeLength;
+ int variablesSize = codeAttribute.u2maxLocals;
+
+ // We'll only really analyze the first 64 variables.
+ if (variablesSize > MAX_VARIABLES_SIZE)
+ {
+ variablesSize = MAX_VARIABLES_SIZE;
+ }
+
+ // Mark liveness blocks, as many times as necessary.
+ do
+ {
+ checkAgain = false;
+ alive = 0L;
+
+ // Loop over all traced instructions, backward.
+ for (int offset = codeLength - 1; offset >= 0; offset--)
+ {
+ if (partialEvaluator.isTraced(offset))
+ {
+ // Update the liveness based on the branch targets.
+ InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset);
+ if (branchTargets != null)
+ {
+ // Update the liveness right after the branch instruction.
+ alive = combinedLiveness(branchTargets);
+ }
+
+ // Merge the current liveness.
+ alive |= isAliveAfter[offset];
+
+ // Update the liveness after the instruction.
+ isAliveAfter[offset] = alive;
+
+ // Update the current liveness based on the instruction.
+ codeAttribute.instructionAccept(clazz, method, offset, this);
+
+ // Merge the current liveness.
+ alive |= isAliveBefore[offset];
+
+ // Update the liveness before the instruction.
+ if ((~isAliveBefore[offset] & alive) != 0L)
+ {
+ isAliveBefore[offset] = alive;
+
+ // Do we have to check again after this loop?
+ checkAgain |= offset < maxOffset(partialEvaluator.branchOrigins(offset));
+ }
+ }
+ }
+
+ // Account for the liveness at the start of the exception handlers.
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ }
+ while (checkAgain);
+
+ // Loop over all instructions, to mark variables that take up two entries.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (partialEvaluator.isTraced(offset))
+ {
+ // Loop over all variables.
+ for (int variableIndex = 0; variableIndex < variablesSize; variableIndex++)
+ {
+ // Is the variable alive and a category 2 type?
+ if (isAliveBefore(offset, variableIndex))
+ {
+ Value value = partialEvaluator.getVariablesBefore(offset).getValue(variableIndex);
+ if (value != null && value.isCategory2())
+ {
+ // Mark it as such.
+ setCategory2(offset, variableIndex, true);
+
+ // Mark the next variable as well.
+ setAliveBefore(offset, variableIndex + 1, true);
+ setCategory2( offset, variableIndex + 1, true);
+ }
+ }
+
+ // Is the variable alive and a category 2 type?
+ if (isAliveAfter(offset, variableIndex))
+ {
+ Value value = partialEvaluator.getVariablesAfter(offset).getValue(variableIndex);
+ if (value != null && value.isCategory2())
+ {
+ // Mark it as such.
+ setCategory2(offset, variableIndex, true);
+
+ // Mark the next variable as well.
+ setAliveAfter(offset, variableIndex + 1, true);
+ setCategory2( offset, variableIndex + 1, true);
+ }
+ }
+ }
+ }
+ }
+
+ if (DEBUG)
+ {
+ // Loop over all instructions.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (partialEvaluator.isTraced(offset))
+ {
+ long aliveBefore = isAliveBefore[offset];
+ long aliveAfter = isAliveAfter[offset];
+ long category2 = isCategory2[offset];
+
+ // Print out the liveness of all variables before the instruction.
+ for (int variableIndex = 0; variableIndex < variablesSize; variableIndex++)
+ {
+ long variableMask = (1L << variableIndex);
+ System.out.print((aliveBefore & variableMask) == 0L ? '.' :
+ (category2 & variableMask) == 0L ? 'x' :
+ '*');
+ }
+
+ // Print out the instruction itself.
+ System.out.println(" "+ InstructionFactory.create(codeAttribute.code, offset).toString(offset));
+
+ // Print out the liveness of all variables after the instruction.
+ for (int variableIndex = 0; variableIndex < variablesSize; variableIndex++)
+ {
+ long variableMask = (1L << variableIndex);
+ System.out.print((aliveAfter & variableMask) == 0L ? '.' :
+ (category2 & variableMask) == 0L ? 'x' :
+ '=');
+ }
+
+ System.out.println();
+ }
+ }
+ }
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ int variableIndex = variableInstruction.variableIndex;
+ if (variableIndex < MAX_VARIABLES_SIZE)
+ {
+ long livenessMask = 1L << variableIndex;
+
+ // Is it a load instruction or a store instruction?
+ if (variableInstruction.isLoad())
+ {
+ // Start marking the variable before the load instruction.
+ alive |= livenessMask;
+ }
+ else
+ {
+ // Stop marking the variable before the store instruction.
+ alive &= ~livenessMask;
+
+ // But do mark the variable right after the store instruction.
+ isAliveAfter[offset] |= livenessMask;
+ }
+ }
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ // Special case: variable 0 ('this') in an initializer has to be alive
+ // as long as it hasn't been initialized.
+ if (offset == partialEvaluator.superInitializationOffset())
+ {
+ alive |= 1L;
+ }
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ // Are any variables alive at the start of the handler?
+ long alive = isAliveBefore[exceptionInfo.u2handlerPC];
+ if (alive != 0L)
+ {
+ // Set the same liveness flags for the entire try block.
+ int startOffset = exceptionInfo.u2startPC;
+ int endOffset = exceptionInfo.u2endPC;
+
+ for (int offset = startOffset; offset < endOffset; offset++)
+ {
+ if (partialEvaluator.isTraced(offset))
+ {
+ if ((~(isAliveBefore[offset] & isAliveAfter[offset]) & alive) != 0L)
+ {
+ isAliveBefore[offset] |= alive;
+ isAliveAfter[offset] |= alive;
+
+ // Check again after having marked this try block.
+ checkAgain = true;
+ }
+ }
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Initializes the global arrays.
+ */
+ private void initializeArrays(CodeAttribute codeAttribute)
+ {
+ int codeLength = codeAttribute.u4codeLength;
+
+ // Create new arrays for storing information at each instruction offset.
+ if (isAliveBefore.length < codeLength)
+ {
+ isAliveBefore = new long[codeLength];
+ isAliveAfter = new long[codeLength];
+ isCategory2 = new long[codeLength];
+ }
+ else
+ {
+ for (int index = 0; index < codeLength; index++)
+ {
+ isAliveBefore[index] = 0L;
+ isAliveAfter[index] = 0L;
+ isCategory2[index] = 0L;
+ }
+ }
+ }
+
+
+ /**
+ * Returns the combined liveness mask of the variables right before the
+ * specified instruction offsets.
+ */
+ private long combinedLiveness(InstructionOffsetValue instructionOffsetValue)
+ {
+ long alive = 0L;
+
+ int count = instructionOffsetValue.instructionOffsetCount();
+ for (int index = 0; index < count; index++)
+ {
+ alive |= isAliveBefore[instructionOffsetValue.instructionOffset(index)];
+ }
+
+ return alive;
+ }
+
+
+ /**
+ * Returns the minimum offset from the given instruction offsets.
+ */
+ private int minOffset(Value instructionOffsets)
+ {
+ return minOffset(instructionOffsets, Integer.MAX_VALUE);
+ }
+
+
+ /**
+ * Returns the minimum offset from the given instruction offsets.
+ */
+ private int minOffset(Value instructionOffsets, int minOffset)
+ {
+ if (instructionOffsets != null)
+ {
+ InstructionOffsetValue instructionOffsetValue =
+ instructionOffsets.instructionOffsetValue();
+
+ int count = instructionOffsetValue.instructionOffsetCount();
+ for (int index = 0; index < count; index++)
+ {
+ int offset = instructionOffsetValue.instructionOffset(index);
+ if (minOffset > offset)
+ {
+ minOffset = offset;
+ }
+ }
+ }
+
+ return minOffset;
+ }
+
+
+ /**
+ * Returns the maximum offset from the given instruction offsets.
+ */
+ private int maxOffset(Value instructionOffsets)
+ {
+ return maxOffset(instructionOffsets, Integer.MIN_VALUE);
+ }
+
+
+ /**
+ * Returns the maximum offset from the given instruction offsets.
+ */
+ private int maxOffset(Value instructionOffsets, int maxOffset)
+ {
+ if (instructionOffsets != null)
+ {
+ InstructionOffsetValue instructionOffsetValue =
+ instructionOffsets.instructionOffsetValue();
+
+ int count = instructionOffsetValue.instructionOffsetCount();
+ for (int index = 0; index < count; index++)
+ {
+ int offset = instructionOffsetValue.instructionOffset(index);
+ if (maxOffset < offset)
+ {
+ maxOffset = offset;
+ }
+ }
+ }
+
+ return maxOffset;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/LoadingInvocationUnit.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
new file mode 100644
index 0000000000..08a6e50adc
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
@@ -0,0 +1,164 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.RefConstant;
+import proguard.evaluation.BasicInvocationUnit;
+import proguard.evaluation.value.*;
+
+/**
+ * This InvocationUnit loads parameter values and return values that were
+ * previously stored with the methods that are invoked.
+ *
+ * @see StoringInvocationUnit
+ * @author Eric Lafortune
+ */
+public class LoadingInvocationUnit
+extends BasicInvocationUnit
+{
+ private final boolean loadFieldValues;
+ private final boolean loadMethodParameterValues;
+ private final boolean loadMethodReturnValues;
+
+
+ /**
+ * Creates a new LoadingInvocationUnit with the given value factory.
+ */
+ public LoadingInvocationUnit(ValueFactory valueFactory)
+ {
+ this(valueFactory, true, true, true);
+ }
+
+
+ /**
+ * Creates a new LoadingInvocationUnit with the given value factory, for
+ * loading the specified values.
+ */
+ public LoadingInvocationUnit(ValueFactory valueFactory,
+ boolean loadFieldValues,
+ boolean loadMethodParameterValues,
+ boolean loadMethodReturnValues)
+ {
+ super(valueFactory);
+
+ this.loadFieldValues = loadFieldValues;
+ this.loadMethodParameterValues = loadMethodParameterValues;
+ this.loadMethodReturnValues = loadMethodReturnValues;
+ }
+
+
+ // Implementations for BasicInvocationUnit.
+
+ protected Value getFieldClassValue(Clazz clazz,
+ RefConstant refConstant,
+ String type)
+ {
+ if (loadFieldValues)
+ {
+ // Do we know this field?
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ // Retrieve the stored field class value.
+ ReferenceValue value = StoringInvocationUnit.getFieldClassValue((Field)referencedMember);
+ if (value != null)
+ {
+ return value;
+ }
+ }
+ }
+
+ return super.getFieldClassValue(clazz, refConstant, type);
+ }
+
+
+ protected Value getFieldValue(Clazz clazz,
+ RefConstant refConstant,
+ String type)
+ {
+ if (loadFieldValues)
+ {
+ // Do we know this field?
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ // Retrieve the stored field value.
+ Value value = StoringInvocationUnit.getFieldValue((Field)referencedMember);
+ if (value != null)
+ {
+ return value;
+ }
+ }
+ }
+
+ return super.getFieldValue(clazz, refConstant, type);
+ }
+
+
+ protected Value getMethodParameterValue(Clazz clazz,
+ Method method,
+ int parameterIndex,
+ String type,
+ Clazz referencedClass)
+ {
+ if (loadMethodParameterValues)
+ {
+ // Retrieve the stored method parameter value.
+ Value value = StoringInvocationUnit.getMethodParameterValue(method, parameterIndex);
+ if (value != null)
+ {
+ return value;
+ }
+ }
+
+ return super.getMethodParameterValue(clazz,
+ method,
+ parameterIndex,
+ type,
+ referencedClass);
+ }
+
+
+ protected Value getMethodReturnValue(Clazz clazz,
+ RefConstant refConstant,
+ String type)
+ {
+ if (loadMethodReturnValues)
+ {
+ // Do we know this method?
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ // Retrieve the stored method return value.
+ Value value = StoringInvocationUnit.getMethodReturnValue((Method)referencedMember);
+ if (value != null)
+ {
+ return value;
+ }
+ }
+ }
+
+ return super.getMethodReturnValue(clazz,
+ refConstant,
+ type);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/PartialEvaluator.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/PartialEvaluator.java
new file mode 100644
index 0000000000..96281d2701
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/PartialEvaluator.java
@@ -0,0 +1,1308 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.instruction.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.evaluation.*;
+import proguard.evaluation.value.*;
+import proguard.evaluation.BranchTargetFinder;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor performs partial evaluation on the code attributes
+ * that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class PartialEvaluator
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ ExceptionInfoVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_RESULTS = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("pe") != null;
+ private static boolean DEBUG_RESULTS = DEBUG;
+ //*/
+
+ private static final int MAXIMUM_EVALUATION_COUNT = 5;
+
+ public static final int NONE = -2;
+ public static final int AT_METHOD_ENTRY = -1;
+ public static final int AT_CATCH_ENTRY = -1;
+
+ private final ValueFactory valueFactory;
+ private final InvocationUnit invocationUnit;
+ private final boolean evaluateAllCode;
+
+ private InstructionOffsetValue[] branchOriginValues = new InstructionOffsetValue[ClassConstants.TYPICAL_CODE_LENGTH];
+ private InstructionOffsetValue[] branchTargetValues = new InstructionOffsetValue[ClassConstants.TYPICAL_CODE_LENGTH];
+ private TracedVariables[] variablesBefore = new TracedVariables[ClassConstants.TYPICAL_CODE_LENGTH];
+ private TracedStack[] stacksBefore = new TracedStack[ClassConstants.TYPICAL_CODE_LENGTH];
+ private TracedVariables[] variablesAfter = new TracedVariables[ClassConstants.TYPICAL_CODE_LENGTH];
+ private TracedStack[] stacksAfter = new TracedStack[ClassConstants.TYPICAL_CODE_LENGTH];
+ private boolean[] generalizedContexts = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int[] evaluationCounts = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+ private boolean evaluateExceptions;
+ private int codeLength;
+
+ private final BasicBranchUnit branchUnit;
+ private final BranchTargetFinder branchTargetFinder;
+
+ private final java.util.Stack callingInstructionBlockStack;
+ private final java.util.Stack instructionBlockStack = new java.util.Stack();
+
+
+ /**
+ * Creates a simple PartialEvaluator.
+ */
+ public PartialEvaluator()
+ {
+ this(new ValueFactory(),
+ new BasicInvocationUnit(new ValueFactory()),
+ true);
+ }
+
+
+ /**
+ * Creates a new PartialEvaluator.
+ * @param valueFactory the value factory that will create all values
+ * during evaluation.
+ * @param invocationUnit the invocation unit that will handle all
+ * communication with other fields and methods.
+ * @param evaluateAllCode a flag that specifies whether all casts, branch
+ * targets, and exception handlers should be
+ * evaluated, even if they are unnecessary or
+ * unreachable.
+ */
+ public PartialEvaluator(ValueFactory valueFactory,
+ InvocationUnit invocationUnit,
+ boolean evaluateAllCode)
+ {
+ this(valueFactory,
+ invocationUnit,
+ evaluateAllCode,
+ evaluateAllCode ?
+ new BasicBranchUnit() :
+ new TracedBranchUnit(),
+ new BranchTargetFinder(),
+ null);
+ }
+
+
+ /**
+ * Creates a new PartialEvaluator, based on an existing one.
+ * @param partialEvaluator the subroutine calling partial evaluator.
+ */
+ private PartialEvaluator(PartialEvaluator partialEvaluator)
+ {
+ this(partialEvaluator.valueFactory,
+ partialEvaluator.invocationUnit,
+ partialEvaluator.evaluateAllCode,
+ partialEvaluator.branchUnit,
+ partialEvaluator.branchTargetFinder,
+ partialEvaluator.instructionBlockStack);
+ }
+
+
+ /**
+ * Creates a new PartialEvaluator.
+ * @param valueFactory the value factory that will create
+ * all values during evaluation.
+ * @param invocationUnit the invocation unit that will handle
+ * all communication with other fields
+ * and methods.
+ * @param evaluateAllCode a flag that specifies whether all
+ * casts, branch targets, and exception
+ * handlers should be evaluated, even
+ * if they are unnecessary or
+ * unreachable.
+ * @param branchUnit the branch unit that will handle all
+ * branches.
+ * @param branchTargetFinder the utility class that will find all
+ * branches.
+ * @param callingInstructionBlockStack the stack of instruction blocks to
+ * be evaluated
+ */
+ private PartialEvaluator(ValueFactory valueFactory,
+ InvocationUnit invocationUnit,
+ boolean evaluateAllCode,
+ BasicBranchUnit branchUnit,
+ BranchTargetFinder branchTargetFinder,
+ java.util.Stack callingInstructionBlockStack)
+ {
+ this.valueFactory = valueFactory;
+ this.invocationUnit = invocationUnit;
+ this.evaluateAllCode = evaluateAllCode;
+ this.branchUnit = branchUnit;
+ this.branchTargetFinder = branchTargetFinder;
+ this.callingInstructionBlockStack = callingInstructionBlockStack == null ?
+ this.instructionBlockStack :
+ callingInstructionBlockStack;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG = DEBUG_RESULTS =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ // TODO: Remove this when the partial evaluator has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while performing partial evaluation:");
+ System.err.println(" Class = ["+clazz.getName()+"]");
+ System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+
+ if (DEBUG)
+ {
+ method.accept(clazz, new ClassPrinter());
+
+ System.out.println("Evaluation results:");
+
+ int offset = 0;
+ do
+ {
+ if (isBranchOrExceptionTarget(offset))
+ {
+ System.out.println("Branch target from ["+branchOriginValues[offset]+"]:");
+ if (isTraced(offset))
+ {
+ System.out.println(" Vars: "+variablesBefore[offset]);
+ System.out.println(" Stack: "+stacksBefore[offset]);
+ }
+ }
+
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+ System.out.println(instruction.toString(offset));
+
+ if (isTraced(offset))
+ {
+ int initializationOffset = branchTargetFinder.initializationOffset(offset);
+ if (initializationOffset != NONE)
+ {
+ System.out.println(" is to be initialized at ["+initializationOffset+"]");
+ }
+
+ InstructionOffsetValue branchTargets = branchTargets(offset);
+ if (branchTargets != null)
+ {
+ System.out.println(" has overall been branching to "+branchTargets);
+ }
+
+ System.out.println(" Vars: "+variablesAfter[offset]);
+ System.out.println(" Stack: "+stacksAfter[offset]);
+ }
+
+ offset += instruction.length(offset);
+ }
+ while (offset < codeAttribute.u4codeLength);
+ }
+
+ throw ex;
+ }
+ }
+
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Evaluate the instructions, starting at the entry point.
+ if (DEBUG)
+ {
+ System.out.println();
+ System.out.println("Partial evaluation: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ System.out.println(" Max locals = "+codeAttribute.u2maxLocals);
+ System.out.println(" Max stack = "+codeAttribute.u2maxStack);
+ }
+
+ // Reuse the existing variables and stack objects, ensuring the right size.
+ TracedVariables variables = new TracedVariables(codeAttribute.u2maxLocals);
+ TracedStack stack = new TracedStack(codeAttribute.u2maxStack);
+
+ // Initialize the reusable arrays and variables.
+ initializeArrays(codeAttribute);
+ initializeParameters(clazz, method, codeAttribute, variables);
+
+ // Find all instruction offsets,...
+ codeAttribute.accept(clazz, method, branchTargetFinder);
+
+ // Start executing the first instruction block.
+ evaluateInstructionBlockAndExceptionHandlers(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ 0,
+ codeAttribute.u4codeLength);
+
+ if (DEBUG_RESULTS)
+ {
+ System.out.println("Evaluation results:");
+
+ int offset = 0;
+ do
+ {
+ if (isBranchOrExceptionTarget(offset))
+ {
+ System.out.println("Branch target from ["+branchOriginValues[offset]+"]:");
+ if (isTraced(offset))
+ {
+ System.out.println(" Vars: "+variablesBefore[offset]);
+ System.out.println(" Stack: "+stacksBefore[offset]);
+ }
+ }
+
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+ System.out.println(instruction.toString(offset));
+
+ if (isTraced(offset))
+ {
+ int initializationOffset = branchTargetFinder.initializationOffset(offset);
+ if (initializationOffset >= 0)
+ {
+ System.out.println(" is to be initialized at ["+initializationOffset+"]");
+ }
+
+ InstructionOffsetValue branchTargets = branchTargets(offset);
+ if (branchTargets != null)
+ {
+ System.out.println(" has overall been branching to "+branchTargets);
+ }
+
+ System.out.println(" Vars: "+variablesAfter[offset]);
+ System.out.println(" Stack: "+stacksAfter[offset]);
+ }
+
+ offset += instruction.length(offset);
+ }
+ while (offset < codeAttribute.u4codeLength);
+ }
+ }
+
+
+ /**
+ * Returns whether a block of instructions is ever used.
+ */
+ public boolean isTraced(int startOffset, int endOffset)
+ {
+ for (int index = startOffset; index < endOffset; index++)
+ {
+ if (isTraced(index))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset has ever been
+ * executed during the partial evaluation.
+ */
+ public boolean isTraced(int instructionOffset)
+ {
+ return evaluationCounts[instructionOffset] > 0;
+ }
+
+
+ /**
+ * Returns whether there is an instruction at the given offset.
+ */
+ public boolean isInstruction(int instructionOffset)
+ {
+ return branchTargetFinder.isInstruction(instructionOffset);
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is the target of a
+ * branch instruction or an exception.
+ */
+ public boolean isBranchOrExceptionTarget(int instructionOffset)
+ {
+ return branchTargetFinder.isBranchTarget(instructionOffset) ||
+ branchTargetFinder.isExceptionHandler(instructionOffset);
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is the start of a
+ * subroutine.
+ */
+ public boolean isSubroutineStart(int instructionOffset)
+ {
+ return branchTargetFinder.isSubroutineStart(instructionOffset);
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is a subroutine
+ * invocation.
+ */
+ public boolean isSubroutineInvocation(int instructionOffset)
+ {
+ return branchTargetFinder.isSubroutineInvocation(instructionOffset);
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is part of a
+ * subroutine.
+ */
+ public boolean isSubroutine(int instructionOffset)
+ {
+ return branchTargetFinder.isSubroutine(instructionOffset);
+ }
+
+
+ /**
+ * Returns whether the subroutine at the given offset is ever returning
+ * by means of a regular 'ret' instruction.
+ */
+ public boolean isSubroutineReturning(int instructionOffset)
+ {
+ return branchTargetFinder.isSubroutineReturning(instructionOffset);
+ }
+
+
+ /**
+ * Returns the offset after the subroutine that starts at the given
+ * offset.
+ */
+ public int subroutineEnd(int instructionOffset)
+ {
+ return branchTargetFinder.subroutineEnd(instructionOffset);
+ }
+
+
+ /**
+ * Returns the instruction offset at which the object instance that is
+ * created at the given 'new' instruction offset is initialized, or
+ * <code>NONE</code> if it is not being created.
+ */
+ public int initializationOffset(int instructionOffset)
+ {
+ return branchTargetFinder.initializationOffset(instructionOffset);
+ }
+
+
+ /**
+ * Returns whether the method is an instance initializer.
+ */
+ public boolean isInitializer()
+ {
+ return branchTargetFinder.isInitializer();
+ }
+
+
+ /**
+ * Returns the instruction offset at which this initializer is calling
+ * the "super" or "this" initializer method, or <code>NONE</code> if it is
+ * not an initializer.
+ */
+ public int superInitializationOffset()
+ {
+ return branchTargetFinder.superInitializationOffset();
+ }
+
+
+ /**
+ * Returns the offset of the 'new' instruction that corresponds to the
+ * invocation of the instance initializer at the given offset, or
+ * <code>AT_METHOD_ENTRY</code> if the invocation is calling the "super" or
+ * "this" initializer method, , or <code>NONE</code> if it is not a 'new'
+ * instruction.
+ */
+ public int creationOffset(int offset)
+ {
+ return branchTargetFinder.creationOffset(offset);
+ }
+
+
+ /**
+ * Returns the variables before execution of the instruction at the given
+ * offset.
+ */
+ public TracedVariables getVariablesBefore(int instructionOffset)
+ {
+ return variablesBefore[instructionOffset];
+ }
+
+
+ /**
+ * Returns the variables after execution of the instruction at the given
+ * offset.
+ */
+ public TracedVariables getVariablesAfter(int instructionOffset)
+ {
+ return variablesAfter[instructionOffset];
+ }
+
+
+ /**
+ * Returns the stack before execution of the instruction at the given
+ * offset.
+ */
+ public TracedStack getStackBefore(int instructionOffset)
+ {
+ return stacksBefore[instructionOffset];
+ }
+
+
+ /**
+ * Returns the stack after execution of the instruction at the given
+ * offset.
+ */
+ public TracedStack getStackAfter(int instructionOffset)
+ {
+ return stacksAfter[instructionOffset];
+ }
+
+
+ /**
+ * Returns the instruction offsets that branch to the given instruction
+ * offset.
+ */
+ public InstructionOffsetValue branchOrigins(int instructionOffset)
+ {
+ return branchOriginValues[instructionOffset];
+ }
+
+
+ /**
+ * Returns the instruction offsets to which the given instruction offset
+ * branches.
+ */
+ public InstructionOffsetValue branchTargets(int instructionOffset)
+ {
+ return branchTargetValues[instructionOffset];
+ }
+
+
+ // Utility methods to evaluate instruction blocks.
+
+ /**
+ * Pushes block of instructions to be executed in the calling partial
+ * evaluator.
+ */
+ private void pushCallingInstructionBlock(TracedVariables variables,
+ TracedStack stack,
+ int startOffset)
+ {
+ callingInstructionBlockStack.push(new MyInstructionBlock(variables,
+ stack,
+ startOffset));
+ }
+
+
+ /**
+ * Pushes block of instructions to be executed in this partial evaluator.
+ */
+ private void pushInstructionBlock(TracedVariables variables,
+ TracedStack stack,
+ int startOffset)
+ {
+ instructionBlockStack.push(new MyInstructionBlock(variables,
+ stack,
+ startOffset));
+ }
+
+
+ /**
+ * Evaluates the instruction block and the exception handlers covering the
+ * given instruction range in the given code.
+ */
+ private void evaluateInstructionBlockAndExceptionHandlers(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ TracedVariables variables,
+ TracedStack stack,
+ int startOffset,
+ int endOffset)
+ {
+ evaluateInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ startOffset);
+
+ evaluateExceptionHandlers(clazz,
+ method,
+ codeAttribute,
+ startOffset,
+ endOffset);
+ }
+
+
+ /**
+ * Evaluates a block of instructions, starting at the given offset and ending
+ * at a branch instruction, a return instruction, or a throw instruction.
+ */
+ private void evaluateInstructionBlock(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ TracedVariables variables,
+ TracedStack stack,
+ int startOffset)
+ {
+ // Execute the initial instruction block.
+ evaluateSingleInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ startOffset);
+
+ // Execute all resulting instruction blocks on the execution stack.
+ while (!instructionBlockStack.empty())
+ {
+ if (DEBUG) System.out.println("Popping alternative branch out of "+instructionBlockStack.size()+" blocks");
+
+ MyInstructionBlock instructionBlock =
+ (MyInstructionBlock)instructionBlockStack.pop();
+
+ evaluateSingleInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ instructionBlock.variables,
+ instructionBlock.stack,
+ instructionBlock.startOffset);
+ }
+ }
+
+
+ /**
+ * Evaluates a block of instructions, starting at the given offset and ending
+ * at a branch instruction, a return instruction, or a throw instruction.
+ * Instruction blocks that are to be evaluated as a result are pushed on
+ * the given stack.
+ */
+ private void evaluateSingleInstructionBlock(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ TracedVariables variables,
+ TracedStack stack,
+ int startOffset)
+ {
+ byte[] code = codeAttribute.code;
+
+ if (DEBUG)
+ {
+ System.out.println("Instruction block starting at ["+startOffset+"] in "+
+ ClassUtil.externalFullMethodDescription(clazz.getName(),
+ 0,
+ method.getName(clazz),
+ method.getDescriptor(clazz)));
+ System.out.println("Init vars: "+variables);
+ System.out.println("Init stack: "+stack);
+ }
+
+ Processor processor = new Processor(variables,
+ stack,
+ valueFactory,
+ branchUnit,
+ invocationUnit,
+ evaluateAllCode);
+
+ int instructionOffset = startOffset;
+
+ int maxOffset = startOffset;
+
+ // Evaluate the subsequent instructions.
+ while (true)
+ {
+ if (maxOffset < instructionOffset)
+ {
+ maxOffset = instructionOffset;
+ }
+
+ // Maintain a generalized local variable frame and stack at this
+ // instruction offset, before execution.
+ int evaluationCount = evaluationCounts[instructionOffset];
+ if (evaluationCount == 0)
+ {
+ // First time we're passing by this instruction.
+ if (variablesBefore[instructionOffset] == null)
+ {
+ // There's not even a context at this index yet.
+ variablesBefore[instructionOffset] = new TracedVariables(variables);
+ stacksBefore[instructionOffset] = new TracedStack(stack);
+ }
+ else
+ {
+ // Reuse the context objects at this index.
+ variablesBefore[instructionOffset].initialize(variables);
+ stacksBefore[instructionOffset].copy(stack);
+ }
+
+ // We'll execute in the generalized context, because it is
+ // the same as the current context.
+ generalizedContexts[instructionOffset] = true;
+ }
+ else
+ {
+ // Merge in the current context.
+ boolean variablesChanged = variablesBefore[instructionOffset].generalize(variables, true);
+ boolean stackChanged = stacksBefore[instructionOffset].generalize(stack);
+
+ //System.out.println("GVars: "+variablesBefore[instructionOffset]);
+ //System.out.println("GStack: "+stacksBefore[instructionOffset]);
+
+ // Bail out if the current context is the same as last time.
+ if (!variablesChanged &&
+ !stackChanged &&
+ generalizedContexts[instructionOffset])
+ {
+ if (DEBUG) System.out.println("Repeated variables, stack, and branch targets");
+
+ break;
+ }
+
+ // See if this instruction has been evaluated an excessive number
+ // of times.
+ if (evaluationCount >= MAXIMUM_EVALUATION_COUNT)
+ {
+ if (DEBUG) System.out.println("Generalizing current context after "+evaluationCount+" evaluations");
+
+ // Continue, but generalize the current context.
+ // Note that the most recent variable values have to remain
+ // last in the generalizations, for the sake of the ret
+ // instruction.
+ variables.generalize(variablesBefore[instructionOffset], false);
+ stack.generalize(stacksBefore[instructionOffset]);
+
+ // We'll execute in the generalized context.
+ generalizedContexts[instructionOffset] = true;
+ }
+ else
+ {
+ // We'll execute in the current context.
+ generalizedContexts[instructionOffset] = false;
+ }
+ }
+
+ // We'll evaluate this instruction.
+ evaluationCounts[instructionOffset]++;
+
+ // Remember this instruction's offset with any stored value.
+ Value storeValue = new InstructionOffsetValue(instructionOffset);
+ variables.setProducerValue(storeValue);
+ stack.setProducerValue(storeValue);
+
+ // Reset the trace value.
+ InstructionOffsetValue traceValue = InstructionOffsetValue.EMPTY_VALUE;
+
+ // Note that the instruction is only volatile.
+ Instruction instruction = InstructionFactory.create(code, instructionOffset);
+
+ // By default, the next instruction will be the one after this
+ // instruction.
+ int nextInstructionOffset = instructionOffset +
+ instruction.length(instructionOffset);
+ InstructionOffsetValue nextInstructionOffsetValue = new InstructionOffsetValue(nextInstructionOffset);
+ branchUnit.resetCalled();
+ branchUnit.setTraceBranchTargets(nextInstructionOffsetValue);
+
+ if (DEBUG)
+ {
+ System.out.println(instruction.toString(instructionOffset));
+ }
+
+ try
+ {
+ // Process the instruction. The processor may modify the
+ // variables and the stack, and it may call the branch unit
+ // and the invocation unit.
+ instruction.accept(clazz,
+ method,
+ codeAttribute,
+ instructionOffset,
+ processor);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while evaluating instruction:");
+ System.err.println(" Class = ["+clazz.getName()+"]");
+ System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ System.err.println(" Instruction = "+instruction.toString(instructionOffset));
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+
+ throw ex;
+ }
+
+ // Collect the branch targets from the branch unit.
+ InstructionOffsetValue branchTargets = branchUnit.getTraceBranchTargets();
+ int branchTargetCount = branchTargets.instructionOffsetCount();
+
+ // Stop tracing.
+ branchUnit.setTraceBranchTargets(traceValue);
+
+ if (DEBUG)
+ {
+ if (branchUnit.wasCalled())
+ {
+ System.out.println(" is branching to "+branchTargets);
+ }
+ if (branchTargetValues[instructionOffset] != null)
+ {
+ System.out.println(" has up till now been branching to "+branchTargetValues[instructionOffset]);
+ }
+
+ System.out.println(" Vars: "+variables);
+ System.out.println(" Stack: "+stack);
+ }
+
+ // Maintain a generalized local variable frame and stack at this
+ // instruction offset, after execution.
+ if (evaluationCount == 0)
+ {
+ // First time we're passing by this instruction.
+ if (variablesAfter[instructionOffset] == null)
+ {
+ // There's not even a context at this index yet.
+ variablesAfter[instructionOffset] = new TracedVariables(variables);
+ stacksAfter[instructionOffset] = new TracedStack(stack);
+ }
+ else
+ {
+ // Reuse the context objects at this index.
+ variablesAfter[instructionOffset].initialize(variables);
+ stacksAfter[instructionOffset].copy(stack);
+ }
+ }
+ else
+ {
+ // Merge in the current context.
+ variablesAfter[instructionOffset].generalize(variables, true);
+ stacksAfter[instructionOffset].generalize(stack);
+ }
+
+ // Did the branch unit get called?
+ if (branchUnit.wasCalled())
+ {
+ // Accumulate the branch targets at this offset.
+ branchTargetValues[instructionOffset] = branchTargetValues[instructionOffset] == null ?
+ branchTargets :
+ branchTargetValues[instructionOffset].generalize(branchTargets).instructionOffsetValue();
+
+ // Are there no branch targets at all?
+ if (branchTargetCount == 0)
+ {
+ // Exit from this code block.
+ break;
+ }
+
+ // Accumulate the branch origins at the branch target offsets.
+ InstructionOffsetValue instructionOffsetValue = new InstructionOffsetValue(instructionOffset);
+ for (int index = 0; index < branchTargetCount; index++)
+ {
+ int branchTarget = branchTargets.instructionOffset(index);
+ branchOriginValues[branchTarget] = branchOriginValues[branchTarget] == null ?
+ instructionOffsetValue:
+ branchOriginValues[branchTarget].generalize(instructionOffsetValue).instructionOffsetValue();
+ }
+
+ // Are there multiple branch targets?
+ if (branchTargetCount > 1)
+ {
+ // Push them on the execution stack and exit from this block.
+ for (int index = 0; index < branchTargetCount; index++)
+ {
+ if (DEBUG) System.out.println("Pushing alternative branch #"+index+" out of "+branchTargetCount+", from ["+instructionOffset+"] to ["+branchTargets.instructionOffset(index)+"]");
+
+ pushInstructionBlock(new TracedVariables(variables),
+ new TracedStack(stack),
+ branchTargets.instructionOffset(index));
+ }
+
+ break;
+ }
+
+ if (DEBUG) System.out.println("Definite branch from ["+instructionOffset+"] to ["+branchTargets.instructionOffset(0)+"]");
+ }
+
+ // Just continue with the next instruction.
+ instructionOffset = branchTargets.instructionOffset(0);
+
+ // Is this a subroutine invocation?
+ if (instruction.opcode == InstructionConstants.OP_JSR ||
+ instruction.opcode == InstructionConstants.OP_JSR_W)
+ {
+ // Evaluate the subroutine in another partial evaluator.
+ evaluateSubroutine(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ instructionOffset,
+ instructionBlockStack);
+
+ break;
+ }
+ else if (instruction.opcode == InstructionConstants.OP_RET)
+ {
+ // Let the partial evaluator that has called the subroutine
+ // handle the evaluation after the return.
+ pushCallingInstructionBlock(new TracedVariables(variables),
+ new TracedStack(stack),
+ instructionOffset);
+ break;
+ }
+ }
+
+ if (DEBUG) System.out.println("Ending processing of instruction block starting at ["+startOffset+"]");
+ }
+
+
+ /**
+ * Evaluates a subroutine and its exception handlers, starting at the given
+ * offset and ending at a subroutine return instruction.
+ */
+ private void evaluateSubroutine(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ TracedVariables variables,
+ TracedStack stack,
+ int subroutineStart,
+ java.util.Stack instructionBlockStack)
+ {
+ int subroutineEnd = branchTargetFinder.subroutineEnd(subroutineStart);
+
+ if (DEBUG) System.out.println("Evaluating subroutine from "+subroutineStart+" to "+subroutineEnd);
+
+ // Create a temporary partial evaluator, so there are no conflicts
+ // with variables that are alive across subroutine invocations, between
+ // different invocations.
+ PartialEvaluator subroutinePartialEvaluator =
+ new PartialEvaluator(this);
+
+ subroutinePartialEvaluator.initializeArrays(codeAttribute);
+
+ // Evaluate the subroutine.
+ subroutinePartialEvaluator.evaluateInstructionBlockAndExceptionHandlers(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ subroutineStart,
+ subroutineEnd);
+
+ // Merge back the temporary partial evaluator. This way, we'll get
+ // the lowest common denominator of stacks and variables.
+ generalize(subroutinePartialEvaluator, 0, codeAttribute.u4codeLength);
+
+ if (DEBUG) System.out.println("Ending subroutine from "+subroutineStart+" to "+subroutineEnd);
+ }
+
+
+ /**
+ * Generalizes the results of this partial evaluator with those of another
+ * given partial evaluator, over a given range of instructions.
+ */
+ private void generalize(PartialEvaluator other,
+ int codeStart,
+ int codeEnd)
+ {
+ if (DEBUG) System.out.println("Generalizing with temporary partial evaluation");
+
+ for (int offset = codeStart; offset < codeEnd; offset++)
+ {
+ if (other.branchOriginValues[offset] != null)
+ {
+ branchOriginValues[offset] = branchOriginValues[offset] == null ?
+ other.branchOriginValues[offset] :
+ branchOriginValues[offset].generalize(other.branchOriginValues[offset]).instructionOffsetValue();
+ }
+
+ if (other.isTraced(offset))
+ {
+ if (other.branchTargetValues[offset] != null)
+ {
+ branchTargetValues[offset] = branchTargetValues[offset] == null ?
+ other.branchTargetValues[offset] :
+ branchTargetValues[offset].generalize(other.branchTargetValues[offset]).instructionOffsetValue();
+ }
+
+ if (evaluationCounts[offset] == 0)
+ {
+ variablesBefore[offset] = other.variablesBefore[offset];
+ stacksBefore[offset] = other.stacksBefore[offset];
+ variablesAfter[offset] = other.variablesAfter[offset];
+ stacksAfter[offset] = other.stacksAfter[offset];
+ generalizedContexts[offset] = other.generalizedContexts[offset];
+ evaluationCounts[offset] = other.evaluationCounts[offset];
+ }
+ else
+ {
+ variablesBefore[offset].generalize(other.variablesBefore[offset], false);
+ stacksBefore[offset] .generalize(other.stacksBefore[offset]);
+ variablesAfter[offset] .generalize(other.variablesAfter[offset], false);
+ stacksAfter[offset] .generalize(other.stacksAfter[offset]);
+ //generalizedContexts[offset]
+ evaluationCounts[offset] += other.evaluationCounts[offset];
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Evaluates the exception handlers covering and targeting the given
+ * instruction range in the given code.
+ */
+ private void evaluateExceptionHandlers(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int startOffset,
+ int endOffset)
+ {
+ if (DEBUG) System.out.println("Evaluating exceptions covering ["+startOffset+" -> "+endOffset+"]:");
+
+ ExceptionHandlerFilter exceptionEvaluator =
+ new ExceptionHandlerFilter(startOffset,
+ endOffset,
+ this);
+
+ // Evaluate the exception catch blocks, until their entry variables
+ // have stabilized.
+ do
+ {
+ // Reset the flag to stop evaluating.
+ evaluateExceptions = false;
+
+ // Evaluate all relevant exception catch blocks once.
+ codeAttribute.exceptionsAccept(clazz,
+ method,
+ startOffset,
+ endOffset,
+ exceptionEvaluator);
+ }
+ while (evaluateExceptions);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ int startPC = exceptionInfo.u2startPC;
+ int endPC = exceptionInfo.u2endPC;
+
+ // Do we have to evaluate this exception catch block?
+ if (isTraced(startPC, endPC))
+ {
+ int handlerPC = exceptionInfo.u2handlerPC;
+ int catchType = exceptionInfo.u2catchType;
+
+ if (DEBUG) System.out.println("Evaluating exception ["+startPC +" -> "+endPC +": "+handlerPC+"]:");
+
+ // Reuse the existing variables and stack objects, ensuring the
+ // right size.
+ TracedVariables variables = new TracedVariables(codeAttribute.u2maxLocals);
+ TracedStack stack = new TracedStack(codeAttribute.u2maxStack);
+
+ // Initialize the trace values.
+ Value storeValue = new InstructionOffsetValue(AT_CATCH_ENTRY);
+ variables.setProducerValue(storeValue);
+ stack.setProducerValue(storeValue);
+
+ // Initialize the variables by generalizing the variables of the
+ // try block. Make sure to include the results of the last
+ // instruction for preverification.
+ generalizeVariables(startPC,
+ endPC,
+ evaluateAllCode,
+ variables);
+
+ // Initialize the the stack.
+ //stack.push(valueFactory.createReference((ClassConstant)((ProgramClass)clazz).getConstant(exceptionInfo.u2catchType), false));
+ String catchClassName = catchType != 0 ?
+ clazz.getClassName(catchType) :
+ ClassConstants.NAME_JAVA_LANG_THROWABLE;
+
+ Clazz catchClass = catchType != 0 ?
+ ((ClassConstant)((ProgramClass)clazz).getConstant(catchType)).referencedClass :
+ null;
+
+ stack.push(valueFactory.createReferenceValue(catchClassName,
+ catchClass,
+ false));
+
+ int evaluationCount = evaluationCounts[handlerPC];
+
+ // Evaluate the instructions, starting at the entry point.
+ evaluateInstructionBlock(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack,
+ handlerPC);
+
+ // Remember to evaluate all exception handlers once more.
+ if (!evaluateExceptions)
+ {
+ evaluateExceptions = evaluationCount < evaluationCounts[handlerPC];
+ }
+ }
+// else if (evaluateAllCode)
+// {
+// if (DEBUG) System.out.println("No information for partial evaluation of exception ["+startPC +" -> "+endPC +": "+exceptionInfo.u2handlerPC+"] yet");
+//
+// // We don't have any information on the try block yet, but we do
+// // have to evaluate the exception handler.
+// // Remember to evaluate all exception handlers once more.
+// evaluateExceptions = true;
+// }
+ else
+ {
+ if (DEBUG) System.out.println("No information for partial evaluation of exception ["+startPC +" -> "+endPC +": "+exceptionInfo.u2handlerPC+"]");
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Initializes the data structures for the variables, stack, etc.
+ */
+ private void initializeArrays(CodeAttribute codeAttribute)
+ {
+ int newCodeLength = codeAttribute.u4codeLength;
+
+ // Create new arrays for storing information at each instruction offset.
+ if (branchOriginValues.length < newCodeLength)
+ {
+ // Create new arrays.
+ branchOriginValues = new InstructionOffsetValue[newCodeLength];
+ branchTargetValues = new InstructionOffsetValue[newCodeLength];
+ variablesBefore = new TracedVariables[newCodeLength];
+ stacksBefore = new TracedStack[newCodeLength];
+ variablesAfter = new TracedVariables[newCodeLength];
+ stacksAfter = new TracedStack[newCodeLength];
+ generalizedContexts = new boolean[newCodeLength];
+ evaluationCounts = new int[newCodeLength];
+ }
+ else
+ {
+ // Reset the old arrays.
+ Arrays.fill(branchOriginValues, 0, codeLength, null);
+ Arrays.fill(branchTargetValues, 0, codeLength, null);
+ Arrays.fill(generalizedContexts, 0, codeLength, false);
+ Arrays.fill(evaluationCounts, 0, codeLength, 0);
+
+ for (int index = 0; index < newCodeLength; index++)
+ {
+ if (variablesBefore[index] != null)
+ {
+ variablesBefore[index].reset(codeAttribute.u2maxLocals);
+ }
+
+ if (stacksBefore[index] != null)
+ {
+ stacksBefore[index].reset(codeAttribute.u2maxStack);
+ }
+
+ if (variablesAfter[index] != null)
+ {
+ variablesAfter[index].reset(codeAttribute.u2maxLocals);
+ }
+
+ if (stacksAfter[index] != null)
+ {
+ stacksAfter[index].reset(codeAttribute.u2maxStack);
+ }
+ }
+
+ for (int index = newCodeLength; index < codeLength; index++)
+ {
+ if (variablesBefore[index] != null)
+ {
+ variablesBefore[index].reset(0);
+ }
+
+ if (stacksBefore[index] != null)
+ {
+ stacksBefore[index].reset(0);
+ }
+
+ if (variablesAfter[index] != null)
+ {
+ variablesAfter[index].reset(0);
+ }
+
+ if (stacksAfter[index] != null)
+ {
+ stacksAfter[index].reset(0);
+ }
+ }
+ }
+
+ codeLength = newCodeLength;
+ }
+
+
+ /**
+ * Initializes the data structures for the variables, stack, etc.
+ */
+ private void initializeParameters(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ TracedVariables variables)
+ {
+ // Create the method parameters.
+ TracedVariables parameters = new TracedVariables(codeAttribute.u2maxLocals);
+
+ // Remember this instruction's offset with any stored value.
+ Value storeValue = new InstructionOffsetValue(AT_METHOD_ENTRY);
+ parameters.setProducerValue(storeValue);
+
+ // Initialize the method parameters.
+ invocationUnit.enterMethod(clazz, method, parameters);
+
+ if (DEBUG)
+ {
+ System.out.println(" Params: "+parameters);
+ }
+
+ // Initialize the variables with the parameters.
+ variables.initialize(parameters);
+
+ // Set the store value of each parameter variable.
+ InstructionOffsetValue atMethodEntry = new InstructionOffsetValue(AT_METHOD_ENTRY);
+
+ for (int index = 0; index < parameters.size(); index++)
+ {
+ variables.setProducerValue(index, atMethodEntry);
+ }
+ }
+
+
+ /**
+ * Generalize the local variable frames of a block of instructions.
+ */
+ private void generalizeVariables(int startOffset,
+ int endOffset,
+ boolean includeAfterLastInstruction,
+ TracedVariables generalizedVariables)
+ {
+ boolean first = true;
+ int lastIndex = -1;
+
+ // Generalize the variables before each of the instructions in the block.
+ for (int index = startOffset; index < endOffset; index++)
+ {
+ if (isTraced(index))
+ {
+ TracedVariables tracedVariables = variablesBefore[index];
+
+ if (first)
+ {
+ // Initialize the variables with the first traced local
+ // variable frame.
+ generalizedVariables.initialize(tracedVariables);
+
+ first = false;
+ }
+ else
+ {
+ // Generalize the variables with the traced local variable
+ // frame. We can't use the return value, because local
+ // generalization can be different a couple of times,
+ // with the global generalization being the same.
+ generalizedVariables.generalize(tracedVariables, false);
+ }
+
+ lastIndex = index;
+ }
+ }
+
+ // Generalize the variables after the last instruction in the block,
+ // if required.
+ if (includeAfterLastInstruction &&
+ lastIndex >= 0)
+ {
+ TracedVariables tracedVariables = variablesAfter[lastIndex];
+
+ if (first)
+ {
+ // Initialize the variables with the local variable frame.
+ generalizedVariables.initialize(tracedVariables);
+ }
+ else
+ {
+ // Generalize the variables with the local variable frame.
+ generalizedVariables.generalize(tracedVariables, false);
+ }
+ }
+
+ // Just clear the variables if there aren't any traced instructions
+ // in the block.
+ if (first)
+ {
+ generalizedVariables.reset(generalizedVariables.size());
+ }
+ }
+
+
+ private static class MyInstructionBlock
+ {
+ private TracedVariables variables;
+ private TracedStack stack;
+ private int startOffset;
+
+
+ private MyInstructionBlock(TracedVariables variables,
+ TracedStack stack,
+ int startOffset)
+ {
+ this.variables = variables;
+ this.stack = stack;
+ this.startOffset = startOffset;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumArrayPropagator.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumArrayPropagator.java
new file mode 100644
index 0000000000..73b8b8ff9d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumArrayPropagator.java
@@ -0,0 +1,94 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+import proguard.evaluation.value.*;
+import proguard.optimize.info.*;
+
+/**
+ * This ClassVisitor propagates the value of the $VALUES field to the values()
+ * method in the simple enum classes that it visits.
+ *
+ * @see SimpleEnumMarker
+ * @author Eric Lafortune
+ */
+public class SimpleEnumArrayPropagator
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor
+{
+ private final ValueFactory valueFactory = new ParticularValueFactory();
+
+ private Value array;
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Update the return value of the "int[] values()" method.
+ programClass.methodsAccept(new MemberDescriptorFilter("()[I", this));
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Find the array length of the "int[] $VALUES" field.
+ programClass.fieldsAccept(new MemberDescriptorFilter("[I", this));
+
+ if (array != null)
+ {
+ // Set the array value with the found array length. We can't use
+ // the original array, because its elements might get overwritten.
+ Value propagatedArray =
+ valueFactory.createArrayReferenceValue("I",
+ null,
+ array.referenceValue().arrayLength(
+ valueFactory));
+
+ setMethodReturnValue(programMethod, propagatedArray);
+
+ array = null;
+ }
+ }
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ array = StoringInvocationUnit.getFieldValue(programField);
+ }
+
+
+ // Small utility methods.
+
+ private static void setMethodReturnValue(Method method, Value value)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setReturnValue(value);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumClassChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumClassChecker.java
new file mode 100644
index 0000000000..9208402d9e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumClassChecker.java
@@ -0,0 +1,75 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.*;
+import proguard.optimize.info.SimpleEnumMarker;
+
+/**
+ * This ClassVisitor marks all program classes that it visits as simple enums,
+ * if their methods qualify.
+ *
+ * @author Eric Lafortune
+ */
+public class SimpleEnumClassChecker
+implements ClassVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("enum") != null;
+ //*/
+
+
+ private final SimpleEnumMarker simpleEnumMarker = new SimpleEnumMarker(true);
+ private final MemberVisitor virtualMemberChecker = new MemberAccessFilter(0,
+ ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC,
+ new MemberToClassVisitor(
+ new SimpleEnumMarker(false)));
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Does the class have the simple enum constructor?
+ if (programClass.findMethod(ClassConstants.METHOD_NAME_INIT,
+ ClassConstants.METHOD_TYPE_INIT_ENUM) != null)
+ {
+ if (DEBUG)
+ {
+ System.out.println("SimpleEnumClassChecker: ["+programClass.getName()+"] is a candidate simple enum, without extra fields");
+ }
+
+ // Mark it.
+ simpleEnumMarker.visitProgramClass(programClass);
+
+ // However, unmark it again if it has any non-private, non-static
+ // fields or methods.
+ programClass.fieldsAccept(virtualMemberChecker);
+ programClass.methodsAccept(virtualMemberChecker);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumClassSimplifier.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumClassSimplifier.java
new file mode 100644
index 0000000000..07a17680f6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumClassSimplifier.java
@@ -0,0 +1,164 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.editor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+import proguard.optimize.info.SimpleEnumMarker;
+import proguard.optimize.peephole.*;
+
+/**
+ * This ClassVisitor simplifies the classes that it visits to simple enums.
+ *
+ * @see SimpleEnumMarker
+ * @see MemberReferenceFixer
+ * @author Eric Lafortune
+ */
+public class SimpleEnumClassSimplifier
+extends SimplifiedVisitor
+implements ClassVisitor,
+ AttributeVisitor,
+ InstructionVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("enum") != null;
+ //*/
+
+
+ private static final int ENUM_CLASS_NAME = InstructionSequenceReplacer.A;
+ private static final int ENUM_TYPE_NAME = InstructionSequenceReplacer.B;
+ private static final int ENUM_CONSTANT_NAME = InstructionSequenceReplacer.X;
+ private static final int ENUM_CONSTANT_ORDINAL = InstructionSequenceReplacer.Y;
+ private static final int ENUM_CONSTANT_FIELD_NAME = InstructionSequenceReplacer.Z;
+
+ private static final int STRING_ENUM_CONSTANT_NAME = 0;
+
+ private static final int METHOD_ENUM_INIT = 1;
+ private static final int FIELD_ENUM_CONSTANT = 2;
+
+ private static final int CLASS_ENUM = 3;
+
+ private static final int NAME_AND_TYPE_ENUM_INIT = 4;
+ private static final int NAME_AND_TYPE_ENUM_CONSTANT = 5;
+
+ private static final int UTF8_INIT = 6;
+ private static final int UTF8_STRING_I = 7;
+
+
+ private static final Constant[] CONSTANTS = new Constant[]
+ {
+ new StringConstant(ENUM_CONSTANT_NAME, null, null),
+
+ new MethodrefConstant(CLASS_ENUM, NAME_AND_TYPE_ENUM_INIT, null, null),
+ new FieldrefConstant( CLASS_ENUM, NAME_AND_TYPE_ENUM_CONSTANT, null, null),
+
+ new ClassConstant(ENUM_CLASS_NAME, null),
+
+ new NameAndTypeConstant(UTF8_INIT, UTF8_STRING_I),
+ new NameAndTypeConstant(ENUM_CONSTANT_FIELD_NAME, ENUM_TYPE_NAME),
+
+ new Utf8Constant(ClassConstants.METHOD_NAME_INIT),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_INIT_ENUM),
+ };
+
+ private static final Instruction[] INSTRUCTIONS = new Instruction[]
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_ENUM),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_ENUM_CONSTANT_NAME),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, ENUM_CONSTANT_ORDINAL),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_ENUM_INIT),
+ };
+
+ private static final Instruction[] REPLACEMENT_INSTRUCTIONS = new Instruction[]
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, ENUM_CONSTANT_ORDINAL),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ };
+
+
+ private final CodeAttributeEditor codeAttributeEditor =
+ new CodeAttributeEditor(true, true);
+
+ private final InstructionSequenceReplacer instructionSequenceReplacer =
+ new InstructionSequenceReplacer(CONSTANTS,
+ INSTRUCTIONS,
+ REPLACEMENT_INSTRUCTIONS,
+ null,
+ codeAttributeEditor);
+
+ private final MemberVisitor initializerSimplifier = new AllAttributeVisitor(this);
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (DEBUG)
+ {
+ System.out.println("SimpleEnumClassSimplifier: ["+programClass.getName()+"]");
+ }
+
+ // Unmark the class as an enum.
+ programClass.u2accessFlags &= ~ClassConstants.ACC_ENUM;
+
+ // Remove the valueOf method, if present.
+ Method valueOfMethod =
+ programClass.findMethod(ClassConstants.METHOD_NAME_VALUEOF, null);
+ if (valueOfMethod != null)
+ {
+ new ClassEditor(programClass).removeMethod(valueOfMethod);
+ }
+
+ // Simplify the static initializer.
+ programClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT,
+ ClassConstants.METHOD_TYPE_CLINIT,
+ initializerSimplifier);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Set up the code attribute editor.
+ codeAttributeEditor.reset(codeAttribute.u4codeLength);
+
+ // Find the peephole changes.
+ codeAttribute.instructionsAccept(clazz, method, instructionSequenceReplacer);
+
+ // Apply the peephole changes.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumDescriptorSimplifier.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumDescriptorSimplifier.java
new file mode 100644
index 0000000000..1dcd80e37a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumDescriptorSimplifier.java
@@ -0,0 +1,799 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.optimize.info.*;
+
+/**
+ * This ClassVisitor simplifies the descriptors that contain simple enums in
+ * the program classes that it visits.
+ *
+ * @see SimpleEnumMarker
+ * @see MemberReferenceFixer
+ * @author Eric Lafortune
+ */
+public class SimpleEnumDescriptorSimplifier
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor,
+ MemberVisitor,
+ AttributeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("enum") != null;
+ //*/
+
+ private static final boolean DEBUG_EXTRA = false;
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (DEBUG)
+ {
+ System.out.println("SimpleEnumDescriptorSimplifier: "+programClass.getName());
+ }
+
+ // Simplify the class members.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ // Simplify the attributes.
+ //programClass.attributesAccept(this);
+
+ // Simplify the simple enum array constants.
+ programClass.constantPoolEntriesAccept(this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Does the constant refer to a simple enum type?
+ Clazz referencedClass = stringConstant.referencedClass;
+ if (isSimpleEnum(referencedClass))
+ {
+ // Is it an array type?
+ String name = stringConstant.getString(clazz);
+ if (ClassUtil.isInternalArrayType(name))
+ {
+ // Update the type.
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
+
+ String newName = simplifyDescriptor(name, referencedClass);
+
+ stringConstant.u2stringIndex =
+ constantPoolEditor.addUtf8Constant(newName);
+
+ // Clear the referenced class.
+ stringConstant.referencedClass = null;
+ }
+ }
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Update the descriptor if it has any simple enum classes.
+ String descriptor = invokeDynamicConstant.getType(clazz);
+ String newDescriptor = simplifyDescriptor(descriptor, invokeDynamicConstant.referencedClasses);
+
+ if (!descriptor.equals(newDescriptor))
+ {
+ // Update the descriptor.
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
+
+ invokeDynamicConstant.u2nameAndTypeIndex =
+ constantPoolEditor.addNameAndTypeConstant(invokeDynamicConstant.getName(clazz),
+ newDescriptor);
+
+ // Update the referenced classes.
+ invokeDynamicConstant.referencedClasses =
+ simplifyReferencedClasses(descriptor, invokeDynamicConstant.referencedClasses);
+ }
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Does the constant refer to a simple enum type?
+ Clazz referencedClass = classConstant.referencedClass;
+ if (isSimpleEnum(referencedClass))
+ {
+ // Is it an array type?
+ String name = classConstant.getName(clazz);
+ if (ClassUtil.isInternalArrayType(name))
+ {
+ // Update the type.
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
+
+ String newName = simplifyDescriptor(name, referencedClass);
+
+ classConstant.u2nameIndex =
+ constantPoolEditor.addUtf8Constant(newName);
+
+ // Clear the referenced class.
+ classConstant.referencedClass = null;
+ }
+ }
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ // Update the descriptor if it has any simple enum classes.
+ String descriptor = methodTypeConstant.getType(clazz);
+ String newDescriptor = simplifyDescriptor(descriptor, methodTypeConstant.referencedClasses);
+
+ if (!descriptor.equals(newDescriptor))
+ {
+ // Update the descriptor.
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor((ProgramClass)clazz);
+
+ methodTypeConstant.u2descriptorIndex =
+ constantPoolEditor.addUtf8Constant(newDescriptor);
+
+ // Update the referenced classes.
+ methodTypeConstant.referencedClasses =
+ simplifyReferencedClasses(descriptor, methodTypeConstant.referencedClasses);
+ }
+ }
+
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Update the descriptor if it has a simple enum class.
+ String descriptor = programField.getDescriptor(programClass);
+ String newDescriptor = simplifyDescriptor(descriptor, programField.referencedClass);
+
+ if (!descriptor.equals(newDescriptor))
+ {
+ String name = programField.getName(programClass);
+ String newName = name + ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode()));
+
+ if (DEBUG)
+ {
+ System.out.println("SimpleEnumDescriptorSimplifier: ["+programClass.getName()+"."+name+" "+descriptor + "] -> ["+newName+" "+newDescriptor+"]");
+ }
+
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor(programClass);
+
+ // Update the name.
+ programField.u2nameIndex =
+ constantPoolEditor.addUtf8Constant(newName);
+
+ // Update the descriptor itself.
+ programField.u2descriptorIndex =
+ constantPoolEditor.addUtf8Constant(newDescriptor);
+
+ // Clear the referenced class.
+ programField.referencedClass = null;
+
+ // Clear the enum flag.
+ programField.u2accessFlags &= ~ClassConstants.ACC_ENUM;
+
+ // Clear the field value.
+ FieldOptimizationInfo fieldOptimizationInfo =
+ FieldOptimizationInfo.getFieldOptimizationInfo(programField);
+ if (fieldOptimizationInfo != null)
+ {
+ fieldOptimizationInfo.resetValue(programClass, programField);
+ }
+
+ // Simplify the signature.
+ programField.attributesAccept(programClass, this);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+// // Skip the valueOf method.
+// if (programMethod.getName(programClass).equals(ClassConstants.METHOD_NAME_VALUEOF))
+// {
+// return;
+// }
+
+ // Simplify the code, the signature, and the parameter annotations,
+ // before simplifying the descriptor.
+ programMethod.attributesAccept(programClass, this);
+
+ // Update the descriptor if it has any simple enum classes.
+ String descriptor = programMethod.getDescriptor(programClass);
+ String newDescriptor = simplifyDescriptor(descriptor, programMethod.referencedClasses);
+
+ if (!descriptor.equals(newDescriptor))
+ {
+ String name = programMethod.getName(programClass);
+ String newName = name;
+
+ // Append a code, if the method isn't a class instance initializer.
+ if (!name.equals(ClassConstants.METHOD_NAME_INIT))
+ {
+ newName += ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode()));
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("SimpleEnumDescriptorSimplifier: ["+programClass.getName()+"."+name+descriptor+"] -> ["+newName+newDescriptor+"]");
+ }
+
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor(programClass);
+
+ // Update the name, if necessary.
+ if (!newName.equals(name))
+ {
+ programMethod.u2nameIndex =
+ constantPoolEditor.addUtf8Constant(newName);
+ }
+
+ // Update the descriptor itself.
+ programMethod.u2descriptorIndex =
+ constantPoolEditor.addUtf8Constant(newDescriptor);
+
+ // Update the referenced classes.
+ programMethod.referencedClasses =
+ simplifyReferencedClasses(descriptor, programMethod.referencedClasses);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Simplify the local variable descriptors.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Change the references of the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Change the references of the local variables.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ // Compute the new signature.
+ String signature = signatureAttribute.getSignature(clazz);
+ String newSignature = simplifyDescriptor(signature,
+ signatureAttribute.referencedClasses);
+
+ if (!signature.equals(newSignature))
+ {
+ // Update the signature.
+ signatureAttribute.u2signatureIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature);
+
+ // Update the referenced classes.
+ signatureAttribute.referencedClasses =
+ simplifyReferencedClasses(signature, signatureAttribute.referencedClasses);
+ }
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Update the descriptor if it has a simple enum class.
+ String descriptor = localVariableInfo.getDescriptor(clazz);
+ String newDescriptor = simplifyDescriptor(descriptor, localVariableInfo.referencedClass);
+
+ if (!descriptor.equals(newDescriptor))
+ {
+ // Update the descriptor.
+ localVariableInfo.u2descriptorIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newDescriptor);
+
+ // Clear the referenced class.
+ localVariableInfo.referencedClass = null;
+ }
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // We're only looking at the base type for now.
+ if (localVariableTypeInfo.referencedClasses != null &&
+ localVariableTypeInfo.referencedClasses.length > 0)
+ {
+ // Update the signature if it has any simple enum classes.
+ String signature = localVariableTypeInfo.getSignature(clazz);
+ String newSignature = simplifyDescriptor(signature,
+ localVariableTypeInfo.referencedClasses[0]);
+
+ if (!signature.equals(newSignature))
+ {
+ // Update the signature.
+ localVariableTypeInfo.u2signatureIndex =
+ new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature);
+
+ // Clear the referenced class.
+ localVariableTypeInfo.referencedClasses[0] = null;
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the descriptor with simplified enum type.
+ */
+ private String simplifyDescriptor(String descriptor,
+ Clazz referencedClass)
+ {
+ return isSimpleEnum(referencedClass) ?
+ descriptor.substring(0, ClassUtil.internalArrayTypeDimensionCount(descriptor)) + ClassConstants.TYPE_INT :
+ descriptor;
+ }
+
+
+ /**
+ * Returns the descriptor with simplified enum types.
+ */
+ private String simplifyDescriptor(String descriptor,
+ Clazz[] referencedClasses)
+ {
+ if (referencedClasses != null)
+ {
+ if (DEBUG_EXTRA)
+ {
+ System.out.println(" Before: ["+descriptor+"]");
+ }
+
+ InternalTypeEnumeration typeEnumeration =
+ new InternalTypeEnumeration(descriptor);
+
+ int referencedClassIndex = 0;
+
+ StringBuffer newDescriptorBuffer =
+ new StringBuffer(descriptor.length());
+
+ // Go over the formal type parameters.
+ if (typeEnumeration.hasFormalTypeParameters())
+ {
+ // Consider the classes referenced by this formal type
+ // parameter.
+ String type = typeEnumeration.formalTypeParameters();
+
+ DescriptorClassEnumeration classEnumeration =
+ new DescriptorClassEnumeration(type);
+
+ newDescriptorBuffer.append(classEnumeration.nextFluff());
+
+ // Replace any simple enum types.
+ while (classEnumeration.hasMoreClassNames())
+ {
+ // Get the class.
+ String className =
+ classEnumeration.nextClassName();
+
+ Clazz referencedClass =
+ referencedClasses[referencedClassIndex++];
+
+ // Is this class a simple enum type?
+ if (isSimpleEnum(referencedClass))
+ {
+ // Let's replace it by java.lang.Integer.
+ className = ClassConstants.NAME_JAVA_LANG_INTEGER;
+ }
+
+ newDescriptorBuffer.append(className);
+ newDescriptorBuffer.append(classEnumeration.nextFluff());
+ }
+ }
+
+ if (typeEnumeration.isMethodSignature())
+ {
+ newDescriptorBuffer.append(ClassConstants.METHOD_ARGUMENTS_OPEN);
+ }
+
+ // Go over the main types (class types or parameter types).
+ while (typeEnumeration.hasMoreTypes())
+ {
+ // Consider the classes referenced by this parameter type.
+ String type = typeEnumeration.nextType();
+
+ DescriptorClassEnumeration classEnumeration =
+ new DescriptorClassEnumeration(type);
+
+ String firstFluff = classEnumeration.nextFluff();
+
+ if (classEnumeration.hasMoreClassNames())
+ {
+ // Get the first class.
+ String firstClassName =
+ classEnumeration.nextClassName();
+
+ Clazz firstReferencedClass =
+ referencedClasses[referencedClassIndex++];
+
+ // Is the first class a simple enum type?
+ if (isSimpleEnum(firstReferencedClass))
+ {
+ // Replace it by a primitive int, with any array
+ // prefix.
+ newDescriptorBuffer.append(type.substring(0, ClassUtil.internalArrayTypeDimensionCount(type)));
+ newDescriptorBuffer.append(ClassConstants.TYPE_INT);
+
+ // Skip any other classes of this type.
+ classEnumeration.nextFluff();
+ while (classEnumeration.hasMoreClassNames())
+ {
+ classEnumeration.nextClassName();
+ classEnumeration.nextFluff();
+
+ referencedClassIndex++;
+ }
+ }
+ else
+ {
+ newDescriptorBuffer.append(firstFluff);
+ newDescriptorBuffer.append(firstClassName);
+ newDescriptorBuffer.append(classEnumeration.nextFluff());
+
+ // Replace any other simple enum types.
+ while (classEnumeration.hasMoreClassNames())
+ {
+ // Get the class.
+ String className =
+ classEnumeration.nextClassName();
+
+ Clazz referencedClass =
+ referencedClasses[referencedClassIndex++];
+
+ // Is this class a simple enum type?
+ if (isSimpleEnum(referencedClass))
+ {
+ // Let's replace it by java.lang.Integer.
+ className = ClassConstants.NAME_JAVA_LANG_INTEGER;
+ }
+
+ newDescriptorBuffer.append(className);
+ newDescriptorBuffer.append(classEnumeration.nextFluff());
+ }
+ }
+ }
+ else
+ {
+ newDescriptorBuffer.append(firstFluff);
+ }
+ }
+
+ if (typeEnumeration.isMethodSignature())
+ {
+ newDescriptorBuffer.append(ClassConstants.METHOD_ARGUMENTS_CLOSE);
+
+ // Consider the classes referenced by the return type.
+ String type = typeEnumeration.returnType();
+
+ DescriptorClassEnumeration classEnumeration =
+ new DescriptorClassEnumeration(type);
+
+ String firstFluff = classEnumeration.nextFluff();
+
+ if (classEnumeration.hasMoreClassNames())
+ {
+ // Get the first class.
+ String firstClassName =
+ classEnumeration.nextClassName();
+
+ Clazz firstReferencedClass =
+ referencedClasses[referencedClassIndex++];
+
+ // Is the first class a simple enum type?
+ if (isSimpleEnum(firstReferencedClass))
+ {
+ // Replace it by a primitive int, with any array
+ // prefix.
+ newDescriptorBuffer.append(type.substring(0, ClassUtil.internalArrayTypeDimensionCount(type)));
+ newDescriptorBuffer.append(ClassConstants.TYPE_INT);
+ }
+ else
+ {
+ newDescriptorBuffer.append(firstFluff);
+ newDescriptorBuffer.append(firstClassName);
+ newDescriptorBuffer.append(classEnumeration.nextFluff());
+
+ // Replace any other simple enum types.
+ while (classEnumeration.hasMoreClassNames())
+ {
+ // Get the class.
+ String className =
+ classEnumeration.nextClassName();
+
+ Clazz referencedClass =
+ referencedClasses[referencedClassIndex++];
+
+ // Is this class a simple enum type?
+ if (isSimpleEnum(referencedClass))
+ {
+ // Let's replace it by java.lang.Integer.
+ className = ClassConstants.NAME_JAVA_LANG_INTEGER;
+ }
+
+ newDescriptorBuffer.append(className);
+ newDescriptorBuffer.append(classEnumeration.nextFluff());
+ }
+ }
+ }
+ else
+ {
+ newDescriptorBuffer.append(firstFluff);
+ }
+ }
+
+ descriptor = newDescriptorBuffer.toString();
+
+ if (DEBUG_EXTRA)
+ {
+ System.out.println(" After: ["+descriptor+"]");
+ }
+ }
+
+ return descriptor;
+ }
+
+
+ /**
+ * Returns the simplified and shrunk array of referenced classes for the
+ * given descriptor.
+ */
+ private Clazz[] simplifyReferencedClasses(String descriptor,
+ Clazz[] referencedClasses)
+ {
+ if (referencedClasses != null)
+ {
+ if (DEBUG_EXTRA)
+ {
+ System.out.print(" Referenced before:");
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ System.out.print(" ["+(referencedClasses[index] == null ? null : referencedClasses[index].getName())+"]");
+ }
+ System.out.println();
+ }
+
+ InternalTypeEnumeration typeEnumeration =
+ new InternalTypeEnumeration(descriptor);
+
+ int referencedClassIndex = 0;
+ int newReferencedClassIndex = 0;
+
+ // Go over the formal type parameters.
+ if (typeEnumeration.hasFormalTypeParameters())
+ {
+ // Consider the classes referenced by this formal type
+ // parameter.
+ String type = typeEnumeration.formalTypeParameters();
+
+ DescriptorClassEnumeration classEnumeration =
+ new DescriptorClassEnumeration(type);
+
+ classEnumeration.nextFluff();
+
+ // Replace any simple enum types.
+ while (classEnumeration.hasMoreClassNames())
+ {
+ // Get the class.
+ classEnumeration.nextClassName();
+ classEnumeration.nextFluff();
+
+ Clazz referencedClass =
+ referencedClasses[referencedClassIndex++];
+
+ // Clear the referenced class if it is a simple
+ // enum type (now java.lang.Integer).
+ referencedClasses[newReferencedClassIndex++] =
+ isSimpleEnum(referencedClass) ? null : referencedClass;
+ }
+ }
+
+ // Go over the main types (class types or parameter types).
+ while (typeEnumeration.hasMoreTypes())
+ {
+ // Consider the classes referenced by this parameter type.
+ String type = typeEnumeration.nextType();
+
+ DescriptorClassEnumeration classEnumeration =
+ new DescriptorClassEnumeration(type);
+
+ classEnumeration.nextFluff();
+
+ if (classEnumeration.hasMoreClassNames())
+ {
+ // Get the first class.
+ classEnumeration.nextClassName();
+ classEnumeration.nextFluff();
+
+ Clazz firstReferencedClass =
+ referencedClasses[referencedClassIndex++];
+
+ // Is the first class a simple enum type?
+ if (isSimpleEnum(firstReferencedClass))
+ {
+ // Replace it by a primitive int.
+
+ // Skip any other classes of this type.
+ classEnumeration.nextFluff();
+ while (classEnumeration.hasMoreClassNames())
+ {
+ classEnumeration.nextClassName();
+ classEnumeration.nextFluff();
+
+ referencedClassIndex++;
+ }
+ }
+ else
+ {
+ referencedClasses[newReferencedClassIndex++] =
+ firstReferencedClass;
+
+ // Replace any other simple enum types.
+ while (classEnumeration.hasMoreClassNames())
+ {
+ // Get the class.
+ classEnumeration.nextClassName();
+ classEnumeration.nextFluff();
+
+ Clazz referencedClass =
+ referencedClasses[referencedClassIndex++];
+
+ // Clear the referenced class if it is a simple
+ // enum type (now java.lang.Integer).
+ referencedClasses[newReferencedClassIndex++] =
+ isSimpleEnum(referencedClass) ? null : referencedClass;
+ }
+ }
+ }
+ }
+
+ if (typeEnumeration.isMethodSignature())
+ {
+ // Consider the classes referenced by the return type.
+ String type = typeEnumeration.returnType();
+
+ DescriptorClassEnumeration classEnumeration =
+ new DescriptorClassEnumeration(type);
+
+ classEnumeration.nextFluff();
+
+ if (classEnumeration.hasMoreClassNames())
+ {
+ // Get the first class.
+ classEnumeration.nextClassName();
+ classEnumeration.nextFluff();
+
+ Clazz firstReferencedClass =
+ referencedClasses[referencedClassIndex++];
+
+ // Is the first class a simple enum type?
+ if (isSimpleEnum(firstReferencedClass))
+ {
+ // Replace it by a primitive int.
+ // Clear all remaining referenced classes.
+ }
+ else
+ {
+ referencedClasses[newReferencedClassIndex++] =
+ firstReferencedClass;
+
+ // Replace any other simple enum types.
+ while (classEnumeration.hasMoreClassNames())
+ {
+ // Get the class.
+ classEnumeration.nextClassName();
+ classEnumeration.nextFluff();
+
+ Clazz referencedClass =
+ referencedClasses[referencedClassIndex++];
+
+ // Clear the referenced class if it is a simple
+ // enum type (now java.lang.Integer).
+ referencedClasses[newReferencedClassIndex++] =
+ isSimpleEnum(referencedClass) ? null : referencedClass;
+ }
+ }
+ }
+ }
+
+ // Shrink the array to the proper size.
+ if (newReferencedClassIndex == 0)
+ {
+ referencedClasses = null;
+ }
+ else if (newReferencedClassIndex < referencedClassIndex)
+ {
+ Clazz[] newReferencedClasses = new Clazz[newReferencedClassIndex];
+ System.arraycopy(referencedClasses, 0,
+ newReferencedClasses, 0,
+ newReferencedClassIndex);
+
+ referencedClasses = newReferencedClasses;
+
+ if (DEBUG_EXTRA)
+ {
+ System.out.print(" Referenced after: ");
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ System.out.print(" ["+(referencedClasses[index] == null ? null : referencedClasses[index].getName())+"]");
+ }
+ System.out.println();
+ }
+ }
+ }
+
+ return referencedClasses;
+ }
+
+
+ /**
+ * Returns whether the given class is not null and a simple enum class.
+ */
+ private boolean isSimpleEnum(Clazz clazz)
+ {
+ return clazz != null &&
+ SimpleEnumMarker.isSimpleEnum(clazz);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumUseChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumUseChecker.java
new file mode 100644
index 0000000000..37c885af72
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumUseChecker.java
@@ -0,0 +1,766 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.evaluation.*;
+import proguard.evaluation.value.*;
+import proguard.optimize.info.SimpleEnumMarker;
+
+/**
+ * This ClassVisitor marks enums that can't be simplified due to the way they
+ * are used in the classes that it visits.
+ *
+ * @see SimpleEnumMarker
+ * @author Eric Lafortune
+ */
+public class SimpleEnumUseChecker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor,
+ InstructionVisitor,
+ ConstantVisitor,
+ ParameterVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("enum") != null;
+ //*/
+
+ private final PartialEvaluator partialEvaluator;
+ private final MemberVisitor methodCodeChecker = new AllAttributeVisitor(this);
+ private final ConstantVisitor invokedMethodChecker = new ReferencedMemberVisitor(this);
+ private final ConstantVisitor parameterChecker = new ReferencedMemberVisitor(new AllParameterVisitor(this));
+ private final ClassVisitor complexEnumMarker = new SimpleEnumMarker(false);
+ private final ReferencedClassVisitor referencedComplexEnumMarker = new ReferencedClassVisitor(complexEnumMarker);
+
+
+ // Fields acting as parameters and return values for the visitor methods.
+ private int invocationOffset;
+
+
+ /**
+ * Creates a new SimpleEnumUseSimplifier.
+ */
+ public SimpleEnumUseChecker()
+ {
+ this(new PartialEvaluator());
+ }
+
+
+ /**
+ * Creates a new SimpleEnumUseChecker.
+ * @param partialEvaluator the partial evaluator that will execute the code
+ * and provide information about the results.
+ */
+ public SimpleEnumUseChecker(PartialEvaluator partialEvaluator)
+ {
+ this.partialEvaluator = partialEvaluator;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if ((programClass.getAccessFlags() & ClassConstants.ACC_ANNOTATTION) != 0)
+ {
+ // Unmark the simple enum classes in annotations.
+ programClass.methodsAccept(referencedComplexEnumMarker);
+ }
+ else
+ {
+ // Unmark the simple enum classes that are used in a complex way.
+ programClass.methodsAccept(methodCodeChecker);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Evaluate the method.
+ partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
+ int codeLength = codeAttribute.u4codeLength;
+
+ // Check all traced instructions.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (partialEvaluator.isTraced(offset))
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+
+ instruction.accept(clazz, method, codeAttribute, offset, this);
+
+ // Check generalized stacks and variables at branch targets.
+ if (partialEvaluator.isBranchOrExceptionTarget(offset))
+ {
+ checkMixedStackEntriesBefore(offset);
+
+ checkMixedVariablesBefore(offset);
+ }
+ }
+ }
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ switch (simpleInstruction.opcode)
+ {
+ case InstructionConstants.OP_AASTORE:
+ {
+ // Check if the instruction is storing a simple enum in a
+ // more general array.
+ if (!isPoppingSimpleEnumType(offset, 2))
+ {
+ if (DEBUG)
+ {
+ if (isPoppingSimpleEnumType(offset))
+ {
+ System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] stores enum ["+
+ partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] in more general array ["+
+ partialEvaluator.getStackBefore(offset).getTop(2).referenceValue().getType()+"]");
+ }
+ }
+
+ markPoppedComplexEnumType(offset);
+ }
+ break;
+ }
+ case InstructionConstants.OP_ARETURN:
+ {
+ // Check if the instruction is returning a simple enum as a
+ // more general type.
+ if (!isReturningSimpleEnumType(clazz, method))
+ {
+ if (DEBUG)
+ {
+ if (isPoppingSimpleEnumType(offset))
+ {
+ System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] returns enum [" +
+ partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] as more general type");
+ }
+ }
+
+ markPoppedComplexEnumType(offset);
+ }
+ break;
+ }
+ case InstructionConstants.OP_MONITORENTER:
+ case InstructionConstants.OP_MONITOREXIT:
+ {
+ // Make sure the popped type is not a simple enum type.
+ if (DEBUG)
+ {
+ if (isPoppingSimpleEnumType(offset))
+ {
+ System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] uses enum ["+
+ partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] as monitor");
+ }
+ }
+
+ markPoppedComplexEnumType(offset);
+
+ break;
+ }
+ }
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_PUTFIELD:
+ {
+ // Check if the instruction is generalizing a simple enum to a
+ // different type.
+ invocationOffset = offset;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ parameterChecker);
+ break;
+ }
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ {
+ // Check if the instruction is calling a simple enum.
+ String invokedMethodName =
+ clazz.getRefName(constantInstruction.constantIndex);
+ String invokedMethodType =
+ clazz.getRefType(constantInstruction.constantIndex);
+ int stackEntryIndex =
+ ClassUtil.internalMethodParameterSize(invokedMethodType);
+ if (isPoppingSimpleEnumType(offset, stackEntryIndex) &&
+ !isSupportedMethod(invokedMethodName,
+ invokedMethodType))
+ {
+ if (DEBUG)
+ {
+ System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] calls ["+partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue().getType()+"."+invokedMethodName+"]");
+ }
+
+ markPoppedComplexEnumType(offset, stackEntryIndex);
+ }
+
+ // Check if any of the parameters is generalizing a simple
+ // enum to a different type.
+ invocationOffset = offset;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ parameterChecker);
+ break;
+ }
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ {
+ // Check if it is calling a method that we can't simplify.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ invokedMethodChecker);
+
+ // Check if any of the parameters is generalizing a simple
+ // enum to a different type.
+ invocationOffset = offset;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ parameterChecker);
+ break;
+ }
+ case InstructionConstants.OP_CHECKCAST:
+ case InstructionConstants.OP_INSTANCEOF:
+ {
+ // Check if the instruction is popping a different type.
+ if (!isPoppingExpectedType(offset,
+ clazz,
+ constantInstruction.constantIndex))
+ {
+ if (DEBUG)
+ {
+ if (isPoppingSimpleEnumType(offset))
+ {
+ System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] is casting or checking ["+
+ partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] as ["+
+ clazz.getClassName(constantInstruction.constantIndex)+"]");
+ }
+ }
+
+ // Make sure the popped type is not a simple enum type.
+ markPoppedComplexEnumType(offset);
+
+ // Make sure the checked type is not a simple enum type.
+ // Casts in values() and valueOf(String) are ok.
+ if (constantInstruction.opcode != InstructionConstants.OP_CHECKCAST ||
+ !isSimpleEnum(clazz) ||
+ (method.getAccessFlags() & ClassConstants.ACC_STATIC) == 0 ||
+ !isMethodSkippedForCheckcast(method.getName(clazz),
+ method.getDescriptor(clazz)))
+ {
+ if (DEBUG)
+ {
+ if (isSimpleEnum(((ClassConstant)((ProgramClass)clazz).getConstant(constantInstruction.constantIndex)).referencedClass))
+ {
+ System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] is casting or checking ["+
+ partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] as ["+
+ clazz.getClassName(constantInstruction.constantIndex)+"]");
+ }
+ }
+
+ markConstantComplexEnumType(clazz, constantInstruction.constantIndex);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ switch (branchInstruction.opcode)
+ {
+ case InstructionConstants.OP_IFACMPEQ:
+ case InstructionConstants.OP_IFACMPNE:
+ {
+ // Check if the instruction is comparing different types.
+ if (!isPoppingIdenticalTypes(offset, 0, 1))
+ {
+ if (DEBUG)
+ {
+ if (isPoppingSimpleEnumType(offset, 0))
+ {
+ System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] compares ["+partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] to plain type");
+ }
+
+ if (isPoppingSimpleEnumType(offset, 1))
+ {
+ System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] compares ["+partialEvaluator.getStackBefore(offset).getTop(1).referenceValue().getType()+"] to plain type");
+ }
+ }
+
+ // Make sure the first popped type is not a simple enum type.
+ markPoppedComplexEnumType(offset, 0);
+
+ // Make sure the second popped type is not a simple enum type.
+ markPoppedComplexEnumType(offset, 1);
+ }
+ break;
+ }
+ }
+ }
+
+
+ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ {
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (isSimpleEnum(programClass) &&
+ isUnsupportedMethod(programMethod.getName(programClass),
+ programMethod.getDescriptor(programClass)))
+ {
+ if (DEBUG)
+ {
+ System.out.println("SimpleEnumUseChecker: invocation of ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"]");
+ }
+
+ complexEnumMarker.visitProgramClass(programClass);
+ }
+ }
+
+
+ // Implementations for ParameterVisitor.
+
+ public void visitParameter(Clazz clazz, Member member, int parameterIndex, int parameterCount, int parameterOffset, int parameterSize, String parameterType, Clazz referencedClass)
+ {
+ // Check if the parameter is passing a simple enum as a more general
+ // type.
+ int stackEntryIndex = parameterSize - parameterOffset - 1;
+ if (ClassUtil.isInternalClassType(parameterType) &&
+ !isPoppingExpectedType(invocationOffset, stackEntryIndex,
+ ClassUtil.isInternalArrayType(parameterType) ?
+ parameterType :
+ ClassUtil.internalClassNameFromClassType(parameterType)))
+ {
+ if (DEBUG)
+ {
+ ReferenceValue poppedValue =
+ partialEvaluator.getStackBefore(invocationOffset).getTop(stackEntryIndex).referenceValue();
+ if (isSimpleEnumType(poppedValue))
+ {
+ System.out.println("SimpleEnumUseChecker: ["+poppedValue.getType()+"] "+
+ (member instanceof Field ?
+ ("is stored as more general type ["+parameterType+"] in field ["+clazz.getName()+"."+member.getName(clazz)+"]") :
+ ("is passed as more general argument #"+parameterIndex+" ["+parameterType+"] to ["+clazz.getName()+"."+member.getName(clazz)+"]")));
+ }
+ }
+
+ // Make sure the popped type is not a simple enum type.
+ markPoppedComplexEnumType(invocationOffset, stackEntryIndex);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the specified enum method is supported for simple enums.
+ */
+ private boolean isSupportedMethod(String name, String type)
+ {
+ return name.equals(ClassConstants.METHOD_NAME_ORDINAL) &&
+ type.equals(ClassConstants.METHOD_TYPE_ORDINAL) ||
+
+ name.equals(ClassConstants.METHOD_NAME_CLONE) &&
+ type.equals(ClassConstants.METHOD_TYPE_CLONE);
+ }
+
+
+ /**
+ * Returns whether the specified enum method is unsupported for simple enums.
+ */
+ private boolean isUnsupportedMethod(String name, String type)
+ {
+ return name.equals(ClassConstants.METHOD_NAME_VALUEOF);
+ }
+
+
+ /**
+ * Returns whether the specified enum method shall be skipped when
+ * analyzing checkcast instructions.
+ */
+ private boolean isMethodSkippedForCheckcast(String name, String type)
+ {
+ return name.equals(ClassConstants.METHOD_NAME_VALUEOF) ||
+ name.equals(ClassConstants.METHOD_NAME_VALUES);
+ }
+
+
+ /**
+ * Unmarks simple enum classes that are mixed with incompatible reference
+ * types in the stack before the given instruction offset.
+ */
+ private void checkMixedStackEntriesBefore(int offset)
+ {
+ TracedStack stackBefore = partialEvaluator.getStackBefore(offset);
+
+ // Check all stack entries.
+ int stackSize = stackBefore.size();
+
+ for (int stackEntryIndex = 0; stackEntryIndex < stackSize; stackEntryIndex++)
+ {
+ // Check reference entries.
+ Value stackEntry = stackBefore.getBottom(stackEntryIndex);
+ if (stackEntry.computationalType() == Value.TYPE_REFERENCE)
+ {
+ // Check reference entries with multiple producers.
+ InstructionOffsetValue producerOffsets =
+ stackBefore.getBottomActualProducerValue(stackEntryIndex).instructionOffsetValue();
+
+ int producerCount = producerOffsets.instructionOffsetCount();
+ if (producerCount > 1)
+ {
+ // Is the consumed stack entry not a simple enum?
+ ReferenceValue consumedStackEntry =
+ stackEntry.referenceValue();
+
+ if (!isSimpleEnumType(consumedStackEntry))
+ {
+ // Check all producers.
+ for (int producerIndex = 0; producerIndex < producerCount; producerIndex++)
+ {
+ int producerOffset =
+ producerOffsets.instructionOffset(producerIndex);
+
+ if (producerOffset >= 0)
+ {
+ if (DEBUG)
+ {
+ ReferenceValue producedValue =
+ partialEvaluator.getStackAfter(producerOffset).getTop(0).referenceValue();
+ if (isSimpleEnumType(producedValue))
+ {
+ System.out.println("SimpleEnumUseChecker: ["+producedValue.getType()+"] mixed with general type on stack");
+ }
+ }
+
+ // Make sure the produced stack entry isn't a
+ // simple enum either.
+ markPushedComplexEnumType(producerOffset);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Unmarks simple enum classes that are mixed with incompatible reference
+ * types in the variables before the given instruction offset.
+ */
+ private void checkMixedVariablesBefore(int offset)
+ {
+ TracedVariables variablesBefore =
+ partialEvaluator.getVariablesBefore(offset);
+
+ // Check all variables.
+ int variablesSize = variablesBefore.size();
+
+ for (int variableIndex = 0; variableIndex < variablesSize; variableIndex++)
+ {
+ // Check reference variables.
+ Value variable = variablesBefore.getValue(variableIndex);
+ if (variable != null &&
+ variable.computationalType() == Value.TYPE_REFERENCE)
+ {
+ // Check reference variables with multiple producers.
+ InstructionOffsetValue producerOffsets =
+ variablesBefore.getProducerValue(variableIndex).instructionOffsetValue();
+
+ int producerCount = producerOffsets.instructionOffsetCount();
+ if (producerCount > 1)
+ {
+ // Is the consumed variable not a simple enum?
+ ReferenceValue consumedVariable =
+ variable.referenceValue();
+
+ if (!isSimpleEnumType(consumedVariable))
+ {
+ // Check all producers.
+ for (int producerIndex = 0; producerIndex < producerCount; producerIndex++)
+ {
+ int producerOffset =
+ producerOffsets.instructionOffset(producerIndex);
+
+ if (producerOffset >= 0)
+ {
+ if (DEBUG)
+ {
+ ReferenceValue producedValue =
+ partialEvaluator.getVariablesAfter(producerOffset).getValue(variableIndex).referenceValue();
+ if (isSimpleEnumType(producedValue))
+ {
+ System.out.println("SimpleEnumUseChecker: ["+producedValue.getType()+"] mixed with general type in variables");
+ }
+ }
+
+ // Make sure the stored variable entry isn't a
+ // simple enum either.
+ markStoredComplexEnumType(producerOffset, variableIndex);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is popping two
+ * identical reference types.
+ */
+ private boolean isPoppingIdenticalTypes(int offset,
+ int stackEntryIndex1,
+ int stackEntryIndex2)
+ {
+ TracedStack stackBefore = partialEvaluator.getStackBefore(offset);
+
+ String type1 =
+ stackBefore.getTop(stackEntryIndex1).referenceValue().getType();
+ String type2 =
+ stackBefore.getTop(stackEntryIndex2).referenceValue().getType();
+
+ return type1 == null ? type2 == null : type1.equals(type2);
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is popping exactly
+ * the reference type of the specified class constant.
+ */
+ private boolean isPoppingExpectedType(int offset,
+ Clazz clazz,
+ int constantIndex)
+ {
+ return isPoppingExpectedType(offset, 0, clazz, constantIndex);
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is popping exactly
+ * the reference type of the specified class constant.
+ */
+ private boolean isPoppingExpectedType(int offset,
+ int stackEntryIndex,
+ Clazz clazz,
+ int constantIndex)
+ {
+ return isPoppingExpectedType(offset,
+ stackEntryIndex,
+ clazz.getClassName(constantIndex));
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is popping exactly
+ * the given reference type.
+ */
+ private boolean isPoppingExpectedType(int offset,
+ int stackEntryIndex,
+ String expectedType)
+ {
+ TracedStack stackBefore = partialEvaluator.getStackBefore(offset);
+
+ String poppedType =
+ stackBefore.getTop(stackEntryIndex).referenceValue().getType();
+
+ return expectedType.equals(poppedType);
+ }
+
+
+ /**
+ * Returns whether the given method is returning a simple enum type.
+ * This includes simple enum arrays.
+ */
+ private boolean isReturningSimpleEnumType(Clazz clazz, Method method)
+ {
+ String descriptor = method.getDescriptor(clazz);
+ String returnType = ClassUtil.internalMethodReturnType(descriptor);
+
+ if (ClassUtil.isInternalClassType(returnType))
+ {
+ Clazz[] referencedClasses =
+ ((ProgramMethod)method).referencedClasses;
+
+ if (referencedClasses != null)
+ {
+ Clazz referencedClass =
+ referencedClasses[referencedClasses.length - 1];
+
+ return isSimpleEnum(referencedClass);
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is popping a type
+ * with a simple enum class. This includes simple enum arrays.
+ */
+ private boolean isPoppingSimpleEnumType(int offset)
+ {
+ return isPoppingSimpleEnumType(offset, 0);
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is popping a type
+ * with a simple enum class. This includes simple enum arrays.
+ */
+ private boolean isPoppingSimpleEnumType(int offset, int stackEntryIndex)
+ {
+ ReferenceValue referenceValue =
+ partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue();
+
+ return isSimpleEnumType(referenceValue);
+ }
+
+
+ /**
+ * Returns whether the given value is a simple enum type. This includes
+ * simple enum arrays.
+ */
+ private boolean isSimpleEnumType(ReferenceValue referenceValue)
+ {
+ return isSimpleEnum(referenceValue.getReferencedClass());
+ }
+
+
+ /**
+ * Returns whether the given class is not null and a simple enum class.
+ */
+ private boolean isSimpleEnum(Clazz clazz)
+ {
+ return clazz != null &&
+ SimpleEnumMarker.isSimpleEnum(clazz);
+ }
+
+
+ /**
+ * Marks the enum class of the popped type as complex.
+ */
+ private void markConstantComplexEnumType(Clazz clazz, int constantIndex)
+ {
+ clazz.constantPoolEntryAccept(constantIndex,
+ referencedComplexEnumMarker);
+ }
+
+
+ /**
+ * Marks the enum class of the popped type as complex.
+ */
+ private void markPoppedComplexEnumType(int offset)
+ {
+ markPoppedComplexEnumType(offset, 0);
+ }
+
+
+ /**
+ * Marks the enum class of the specified popped type as complex.
+ */
+ private void markPoppedComplexEnumType(int offset, int stackEntryIndex)
+ {
+ ReferenceValue referenceValue =
+ partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue();
+
+ markComplexEnumType(referenceValue);
+ }
+
+
+ /**
+ * Marks the enum class of the specified pushed type as complex.
+ */
+ private void markPushedComplexEnumType(int offset)
+ {
+ ReferenceValue referenceValue =
+ partialEvaluator.getStackAfter(offset).getTop(0).referenceValue();
+
+ markComplexEnumType(referenceValue);
+ }
+
+
+ /**
+ * Marks the enum class of the specified stored type as complex.
+ */
+ private void markStoredComplexEnumType(int offset, int variableIndex)
+ {
+ ReferenceValue referenceValue =
+ partialEvaluator.getVariablesAfter(offset).getValue(variableIndex).referenceValue();
+
+ markComplexEnumType(referenceValue);
+ }
+
+
+ /**
+ * Marks the enum class of the specified value as complex.
+ */
+ private void markComplexEnumType(ReferenceValue referenceValue)
+ {
+ Clazz clazz = referenceValue.getReferencedClass();
+ if (clazz != null)
+ {
+ clazz.accept(complexEnumMarker);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java
new file mode 100644
index 0000000000..295cdfbc8d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java
@@ -0,0 +1,818 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.evaluation.value.*;
+import proguard.optimize.info.SimpleEnumMarker;
+
+/**
+ * This AttributeVisitor simplifies the use of enums in the code attributes that
+ * it visits.
+ *
+ * @see SimpleEnumMarker
+ * @see MemberReferenceFixer
+ * @author Eric Lafortune
+ */
+public class SimpleEnumUseSimplifier
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ConstantVisitor,
+ ParameterVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("enum") != null;
+ //*/
+
+ private final InstructionVisitor extraInstructionVisitor;
+
+ private final PartialEvaluator partialEvaluator;
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(true, true);
+ private final ConstantVisitor nullParameterFixer = new ReferencedMemberVisitor(new AllParameterVisitor(this));
+
+ // Fields acting as parameters and return values for the visitor methods.
+ private Clazz invocationClazz;
+ private Method invocationMethod;
+ private CodeAttribute invocationCodeAttribute;
+ private int invocationOffset;
+ private boolean isSimpleEnum;
+
+
+ /**
+ * Creates a new SimpleEnumUseSimplifier.
+ */
+ public SimpleEnumUseSimplifier()
+ {
+ this(new PartialEvaluator(), null);
+ }
+
+
+ /**
+ * Creates a new SimpleEnumDescriptorSimplifier.
+ * @param partialEvaluator the partial evaluator that will
+ * execute the code and provide
+ * information about the results.
+ * @param extraInstructionVisitor an optional extra visitor for all
+ * simplified instructions.
+ */
+ public SimpleEnumUseSimplifier(PartialEvaluator partialEvaluator,
+ InstructionVisitor extraInstructionVisitor)
+ {
+ this.partialEvaluator = partialEvaluator;
+ this.extraInstructionVisitor = extraInstructionVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (DEBUG)
+ {
+ System.out.println("SimpleEnumUseSimplifier: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ }
+
+ // Skip the non-static methods of simple enum classes.
+ if (SimpleEnumMarker.isSimpleEnum(clazz) &&
+ (method.getAccessFlags() & ClassConstants.ACC_STATIC) == 0)
+ {
+ return;
+ }
+
+ // Evaluate the method.
+ partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
+ int codeLength = codeAttribute.u4codeLength;
+
+ // Reset the code changes.
+ codeAttributeEditor.reset(codeLength);
+
+ // Replace any instructions that can be simplified.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if (partialEvaluator.isTraced(offset))
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code,
+ offset);
+
+ instruction.accept(clazz, method, codeAttribute, offset, this);
+ }
+ }
+
+ // Apply all accumulated changes to the code.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ switch (simpleInstruction.opcode)
+ {
+ case InstructionConstants.OP_AALOAD:
+ {
+ if (isPushingSimpleEnum(offset))
+ {
+ // Load a simple enum integer from an integer array.
+ replaceInstruction(clazz,
+ offset,
+ simpleInstruction,
+ new SimpleInstruction(
+ InstructionConstants.OP_IALOAD));
+ }
+ break;
+ }
+ case InstructionConstants.OP_AASTORE:
+ {
+ if (isPoppingSimpleEnumArray(offset, 2))
+ {
+ // Store a simple enum integer in an integer array.
+ replaceInstruction(clazz,
+ offset,
+ simpleInstruction,
+ new SimpleInstruction(InstructionConstants.OP_IASTORE));
+
+ // Replace any producers of null constants.
+ replaceNullStackEntryProducers(clazz, method, codeAttribute, offset);
+ }
+ break;
+ }
+ case InstructionConstants.OP_ARETURN:
+ {
+ if (isReturningSimpleEnum(clazz, method))
+ {
+ // Return a simple enum integer instead of an enum.
+ replaceInstruction(clazz,
+ offset,
+ simpleInstruction,
+ new SimpleInstruction(InstructionConstants.OP_IRETURN));
+
+ // Replace any producers of null constants.
+ replaceNullStackEntryProducers(clazz, method, codeAttribute, offset);
+ }
+ break;
+ }
+ }
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ int variableIndex = variableInstruction.variableIndex;
+
+ switch (variableInstruction.opcode)
+ {
+ case InstructionConstants.OP_ALOAD:
+ case InstructionConstants.OP_ALOAD_0:
+ case InstructionConstants.OP_ALOAD_1:
+ case InstructionConstants.OP_ALOAD_2:
+ case InstructionConstants.OP_ALOAD_3:
+ {
+ if (isPushingSimpleEnum(offset))
+ {
+ // Load a simple enum integer instead of an enum.
+ replaceInstruction(clazz,
+ offset,
+ variableInstruction,
+ new VariableInstruction(InstructionConstants.OP_ILOAD,
+ variableIndex));
+
+ // Replace any producers of null constants.
+ replaceNullVariableProducers(clazz,
+ method,
+ codeAttribute,
+ offset,
+ variableIndex);
+ }
+ break;
+ }
+ case InstructionConstants.OP_ASTORE:
+ case InstructionConstants.OP_ASTORE_0:
+ case InstructionConstants.OP_ASTORE_1:
+ case InstructionConstants.OP_ASTORE_2:
+ case InstructionConstants.OP_ASTORE_3:
+ {
+ if (!partialEvaluator.isSubroutineStart(offset) &&
+ isPoppingSimpleEnum(offset))
+ {
+ // Store a simple enum integer instead of an enum.
+ replaceInstruction(clazz,
+ offset,
+ variableInstruction,
+ new VariableInstruction(InstructionConstants.OP_ISTORE,
+ variableIndex));
+
+ // Replace any producers of null constants.
+ replaceNullStackEntryProducers(clazz, method, codeAttribute, offset);
+ }
+ break;
+ }
+ }
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_PUTFIELD:
+ {
+ // Replace any producers of null constants.
+ invocationClazz = clazz;
+ invocationMethod = method;
+ invocationCodeAttribute = codeAttribute;
+ invocationOffset = offset;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ nullParameterFixer);
+ break;
+ }
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ {
+ // Check if the instruction is calling a simple enum.
+ String invokedMethodName =
+ clazz.getRefName(constantInstruction.constantIndex);
+ String invokedMethodType =
+ clazz.getRefType(constantInstruction.constantIndex);
+ int stackEntryIndex =
+ ClassUtil.internalMethodParameterSize(invokedMethodType);
+ if (isPoppingSimpleEnum(offset, stackEntryIndex))
+ {
+ replaceSupportedMethod(clazz,
+ offset,
+ constantInstruction,
+ invokedMethodName,
+ invokedMethodType);
+ }
+
+ // Fall through to check the parameters.
+ }
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ {
+ // Replace any producers of null constants.
+ invocationClazz = clazz;
+ invocationMethod = method;
+ invocationCodeAttribute = codeAttribute;
+ invocationOffset = offset;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ nullParameterFixer);
+ break;
+ }
+ case InstructionConstants.OP_ANEWARRAY:
+ {
+ int constantIndex = constantInstruction.constantIndex;
+
+ if (isReferencingSimpleEnum(clazz, constantIndex) &&
+ !ClassUtil.isInternalArrayType(clazz.getClassName(constantIndex)))
+ {
+ // Create an integer array instead of an enum array.
+ replaceInstruction(clazz,
+ offset,
+ constantInstruction,
+ new SimpleInstruction(InstructionConstants.OP_NEWARRAY,
+ InstructionConstants.ARRAY_T_INT));
+ }
+ break;
+ }
+ case InstructionConstants.OP_CHECKCAST:
+ {
+ if (isPoppingSimpleEnum(offset))
+ {
+ // Enum classes can only be simple if the checkcast
+ // succeeds, so we can delete it.
+ deleteInstruction(clazz,
+ offset,
+ constantInstruction);
+
+ // Replace any producers of null constants.
+ replaceNullStackEntryProducers(clazz, method, codeAttribute, offset);
+ }
+ break;
+ }
+ case InstructionConstants.OP_INSTANCEOF:
+ {
+ if (isPoppingSimpleEnum(offset))
+ {
+ // Enum classes can only be simple if the instanceof
+ // succeeds, so we can push a constant result.
+ replaceInstruction(clazz,
+ offset,
+ constantInstruction,
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1));
+
+ // Replace any producers of null constants.
+ replaceNullStackEntryProducers(clazz, method, codeAttribute, offset);
+ }
+ break;
+ }
+ }
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ switch (branchInstruction.opcode)
+ {
+ case InstructionConstants.OP_IFACMPEQ:
+ {
+ if (isPoppingSimpleEnum(offset))
+ {
+ // Compare simple enum integers instead of enums.
+ replaceInstruction(clazz,
+ offset,
+ branchInstruction,
+ new BranchInstruction(InstructionConstants.OP_IFICMPEQ,
+ branchInstruction.branchOffset));
+ }
+ break;
+ }
+ case InstructionConstants.OP_IFACMPNE:
+ {
+ if (isPoppingSimpleEnum(offset))
+ {
+ // Compare simple enum integers instead of enums.
+ replaceInstruction(clazz,
+ offset,
+ branchInstruction,
+ new BranchInstruction(InstructionConstants.OP_IFICMPNE,
+ branchInstruction.branchOffset));
+ }
+ break;
+ }
+ case InstructionConstants.OP_IFNULL:
+ {
+ if (isPoppingSimpleEnum(offset))
+ {
+ // Compare with 0 instead of null.
+ replaceInstruction(clazz,
+ offset,
+ branchInstruction,
+ new BranchInstruction(
+ InstructionConstants.OP_IFEQ,
+ branchInstruction.branchOffset));
+ }
+ break;
+ }
+ case InstructionConstants.OP_IFNONNULL:
+ {
+ if (isPoppingSimpleEnum(offset))
+ {
+ // Compare with 0 instead of null.
+ replaceInstruction(clazz,
+ offset,
+ branchInstruction,
+ new BranchInstruction(InstructionConstants.OP_IFNE,
+ branchInstruction.branchOffset));
+ }
+ break;
+ }
+ }
+ }
+
+
+ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ {
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Does the constant refer to a simple enum type?
+ isSimpleEnum = isSimpleEnum(stringConstant.referencedClass);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Does the constant refer to a simple enum type?
+ isSimpleEnum = isSimpleEnum(classConstant.referencedClass);
+ }
+
+
+ // Implementations for ParameterVisitor.
+
+ public void visitParameter(Clazz clazz, Member member, int parameterIndex, int parameterCount, int parameterOffset, int parameterSize, String parameterType, Clazz referencedClass)
+ {
+ // Check if the parameter is passing a simple enum as a more general type.
+ if (!ClassUtil.isInternalPrimitiveType(parameterType.charAt(0)) &&
+ !ClassUtil.isInternalArrayType(parameterType) &&
+ isSimpleEnum(referencedClass))
+ {
+ // Replace any producers of null constants for this parameter.
+ int stackEntryIndex = parameterSize - parameterOffset - 1;
+
+ replaceNullStackEntryProducers(invocationClazz,
+ invocationMethod,
+ invocationCodeAttribute,
+ invocationOffset,
+ stackEntryIndex);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the constant at the given offset is referencing a
+ * simple enum class.
+ */
+ private boolean isReferencingSimpleEnum(Clazz clazz, int constantIndex)
+ {
+ isSimpleEnum = false;
+
+ clazz.constantPoolEntryAccept(constantIndex, this);
+
+ return isSimpleEnum;
+ }
+
+
+ /**
+ * Returns whether the given method is returning a simple enum class.
+ */
+ private boolean isReturningSimpleEnum(Clazz clazz, Method method)
+ {
+ String descriptor = method.getDescriptor(clazz);
+ String returnType = ClassUtil.internalMethodReturnType(descriptor);
+
+ if (ClassUtil.isInternalClassType(returnType) &&
+ !ClassUtil.isInternalArrayType(returnType))
+ {
+ Clazz[] referencedClasses =
+ ((ProgramMethod)method).referencedClasses;
+
+ if (referencedClasses != null)
+ {
+ Clazz returnedClass =
+ referencedClasses[referencedClasses.length - 1];
+
+ return isSimpleEnum(returnedClass);
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is pushing a simple
+ * enum class.
+ */
+ private boolean isPushingSimpleEnum(int offset)
+ {
+ ReferenceValue referenceValue =
+ partialEvaluator.getStackAfter(offset).getTop(0).referenceValue();
+
+ Clazz referencedClass = referenceValue.getReferencedClass();
+
+ return isSimpleEnum(referencedClass) &&
+ !ClassUtil.isInternalArrayType(referenceValue.getType());
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is popping a simple
+ * enum class.
+ */
+ private boolean isPoppingSimpleEnum(int offset)
+ {
+ return isPoppingSimpleEnum(offset, 0);
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is popping a simple
+ * enum class.
+ */
+ private boolean isPoppingSimpleEnum(int offset, int stackEntryIndex)
+ {
+ ReferenceValue referenceValue =
+ partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue();
+
+ return isSimpleEnum(referenceValue.getReferencedClass()) &&
+ !ClassUtil.isInternalArrayType(referenceValue.getType());
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is popping a simple
+ * enum type. This includes simple enum arrays.
+ */
+ private boolean isPoppingSimpleEnumType(int offset, int stackEntryIndex)
+ {
+ ReferenceValue referenceValue =
+ partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue();
+
+ return isSimpleEnum(referenceValue.getReferencedClass());
+ }
+
+
+ /**
+ * Returns whether the instruction at the given offset is popping a
+ * one-dimensional simple enum array.
+ */
+ private boolean isPoppingSimpleEnumArray(int offset, int stackEntryIndex)
+ {
+ ReferenceValue referenceValue =
+ partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue();
+
+ return isSimpleEnum(referenceValue.getReferencedClass()) &&
+ ClassUtil.internalArrayTypeDimensionCount(referenceValue.getType()) == 1;
+ }
+
+
+ /**
+ * Returns whether the given class is not null and a simple enum class.
+ */
+ private boolean isSimpleEnum(Clazz clazz)
+ {
+ return clazz != null &&
+ SimpleEnumMarker.isSimpleEnum(clazz);
+ }
+
+
+ /**
+ * Returns whether the specified enum method is supported for simple enums.
+ */
+ private void replaceSupportedMethod(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ String name,
+ String type)
+ {
+ if (name.equals(ClassConstants.METHOD_NAME_ORDINAL) &&
+ type.equals(ClassConstants.METHOD_TYPE_ORDINAL))
+ {
+ Instruction[] replacementInstructions = new Instruction[]
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new SimpleInstruction(InstructionConstants.OP_ISUB),
+ };
+
+ replaceInstructions(clazz,
+ offset,
+ instruction,
+ replacementInstructions);
+ }
+ }
+
+
+ /**
+ * Replaces the instruction at the given offset by the given instructions.
+ */
+ private void replaceInstructions(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ Instruction[] replacementInstructions)
+ {
+ if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstructions.length+" instructions");
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstructions);
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ // Note: we're not passing the right arguments for now, knowing that
+ // they aren't used anyway.
+ instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
+ }
+ }
+
+
+ /**
+ * Replaces the instruction at the given offset by the given instruction,
+ * popping any now unused stack entries.
+ */
+ private void replaceInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction,
+ Instruction replacementInstruction)
+ {
+ // Pop unneeded stack entries if necessary.
+ int popCount =
+ instruction.stackPopCount(clazz) -
+ replacementInstruction.stackPopCount(clazz);
+
+ insertPopInstructions(offset, popCount);
+
+ if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstruction.toString()+(popCount == 0 ? "" : " ("+popCount+" pops)"));
+
+ codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ // Note: we're not passing the right arguments for now, knowing that
+ // they aren't used anyway.
+ instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
+ }
+ }
+
+
+ /**
+ * Deletes the instruction at the given offset, popping any now unused
+ * stack entries.
+ */
+ private void deleteInstruction(Clazz clazz,
+ int offset,
+ Instruction instruction)
+ {
+ // Pop unneeded stack entries if necessary.
+ //int popCount = instruction.stackPopCount(clazz);
+ //
+ //insertPopInstructions(offset, popCount);
+ //
+ //if (DEBUG) System.out.println(" Deleting instruction "+instruction.toString(offset)+(popCount == 0 ? "" : " ("+popCount+" pops)"));
+
+ if (DEBUG) System.out.println(" Deleting instruction "+instruction.toString(offset));
+
+ codeAttributeEditor.deleteInstruction(offset);
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ // Note: we're not passing the right arguments for now, knowing that
+ // they aren't used anyway.
+ instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
+ }
+ }
+
+
+ /**
+ * Pops the given number of stack entries before the instruction at the
+ * given offset.
+ */
+ private void insertPopInstructions(int offset, int popCount)
+ {
+ switch (popCount)
+ {
+ case 0:
+ {
+ break;
+ }
+ case 1:
+ {
+ // Insert a single pop instruction.
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP);
+
+ codeAttributeEditor.insertBeforeInstruction(offset,
+ popInstruction);
+ break;
+ }
+ case 2:
+ {
+ // Insert a single pop2 instruction.
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP2);
+
+ codeAttributeEditor.insertBeforeInstruction(offset,
+ popInstruction);
+ break;
+ }
+ default:
+ {
+ // Insert the specified number of pop instructions.
+ Instruction[] popInstructions =
+ new Instruction[popCount / 2 + popCount % 2];
+
+ Instruction popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP2);
+
+ for (int index = 0; index < popCount / 2; index++)
+ {
+ popInstructions[index] = popInstruction;
+ }
+
+ if (popCount % 2 == 1)
+ {
+ popInstruction =
+ new SimpleInstruction(InstructionConstants.OP_POP);
+
+ popInstructions[popCount / 2] = popInstruction;
+ }
+
+ codeAttributeEditor.insertBeforeInstruction(offset,
+ popInstructions);
+ break;
+ }
+ }
+ }
+
+
+ /**
+ * Replaces aconst_null producers of the consumer of the top stack entry
+ * at the given offset by iconst_0.
+ */
+ private void replaceNullStackEntryProducers(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int consumerOffset)
+ {
+ replaceNullStackEntryProducers(clazz, method, codeAttribute, consumerOffset, 0);
+ }
+
+
+ /**
+ * Replaces aconst_null producers of the specified stack entry by
+ * iconst_0.
+ */
+ private void replaceNullStackEntryProducers(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int consumerOffset,
+ int stackEntryIndex)
+ {
+ InstructionOffsetValue producerOffsets =
+ partialEvaluator.getStackBefore(consumerOffset).getTopActualProducerValue(stackEntryIndex).instructionOffsetValue();
+
+ for (int index = 0; index < producerOffsets.instructionOffsetCount(); index++)
+ {
+ int producerOffset = producerOffsets.instructionOffset(index);
+
+ // TODO: A method might be pushing the null constant.
+ if (producerOffset >= 0 &&
+ codeAttribute.code[producerOffset] == InstructionConstants.OP_ACONST_NULL)
+ {
+ // Replace pushing null by pushing 0.
+ replaceInstruction(clazz,
+ producerOffset,
+ new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0));
+ }
+ }
+ }
+
+
+ /**
+ * Replaces aconst_null/astore producers of the specified reference variable by
+ * iconst_0/istore.
+ */
+ private void replaceNullVariableProducers(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int consumerOffset,
+ int variableIndex)
+ {
+ InstructionOffsetValue producerOffsets =
+ partialEvaluator.getVariablesBefore(consumerOffset).getProducerValue(variableIndex).instructionOffsetValue();
+
+ for (int index = 0; index < producerOffsets.instructionOffsetCount(); index++)
+ {
+ int producerOffset = producerOffsets.instructionOffset(index);
+
+ if (producerOffset >= 0 &&
+ partialEvaluator.getVariablesAfter(producerOffset).getValue(variableIndex).referenceValue().isNull() == Value.ALWAYS)
+ {
+ // Replace loading null by loading 0.
+ replaceInstruction(clazz,
+ producerOffset,
+ new VariableInstruction(InstructionConstants.OP_ASTORE, variableIndex),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, variableIndex));
+
+ // Replace pushing null by pushing 0.
+ replaceNullStackEntryProducers(clazz, method, codeAttribute, producerOffset);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/StoringInvocationUnit.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/StoringInvocationUnit.java
new file mode 100644
index 0000000000..27af58cc3e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/StoringInvocationUnit.java
@@ -0,0 +1,207 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.RefConstant;
+import proguard.evaluation.BasicInvocationUnit;
+import proguard.evaluation.value.*;
+import proguard.optimize.info.*;
+
+/**
+ * This InvocationUnit stores parameter values and return values with the
+ * methods that are invoked.
+ *
+ * @see LoadingInvocationUnit
+ * @author Eric Lafortune
+ */
+public class StoringInvocationUnit
+extends BasicInvocationUnit
+{
+ private boolean storeFieldValues;
+ private boolean storeMethodParameterValues;
+ private boolean storeMethodReturnValues;
+
+
+ /**
+ * Creates a new StoringInvocationUnit with the given value factory.
+ */
+ public StoringInvocationUnit(ValueFactory valueFactory)
+ {
+ this(valueFactory, true, true, true);
+ }
+
+
+ /**
+ * Creates a new StoringInvocationUnit with the given value factory, for
+ * storing the specified values.
+ */
+ public StoringInvocationUnit(ValueFactory valueFactory,
+ boolean storeFieldValues,
+ boolean storeMethodParameterValues,
+ boolean storeMethodReturnValues)
+ {
+ super(valueFactory);
+
+ this.storeFieldValues = storeFieldValues;
+ this.storeMethodParameterValues = storeMethodParameterValues;
+ this.storeMethodReturnValues = storeMethodReturnValues;
+ }
+
+
+ // Implementations for BasicInvocationUnit.
+
+ protected void setFieldClassValue(Clazz clazz,
+ RefConstant refConstant,
+ ReferenceValue value)
+ {
+ if (storeFieldValues)
+ {
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ generalizeFieldClassValue((Field)referencedMember, value);
+ }
+ }
+ }
+
+
+ protected void setFieldValue(Clazz clazz,
+ RefConstant refConstant,
+ Value value)
+ {
+ if (storeFieldValues)
+ {
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ generalizeFieldValue((Field)referencedMember, value);
+ }
+ }
+ }
+
+
+ protected void setMethodParameterValue(Clazz clazz,
+ RefConstant refConstant,
+ int parameterIndex,
+ Value value)
+ {
+ if (storeMethodParameterValues)
+ {
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null)
+ {
+ generalizeMethodParameterValue((Method)referencedMember,
+ parameterIndex,
+ value);
+ }
+ }
+ }
+
+
+ protected void setMethodReturnValue(Clazz clazz,
+ Method method,
+ Value value)
+ {
+ if (storeMethodReturnValues)
+ {
+ generalizeMethodReturnValue(method, value);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void generalizeFieldClassValue(Field field, ReferenceValue value)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ if (info != null)
+ {
+ info.generalizeReferencedClass(value);
+ }
+ }
+
+
+ public static ReferenceValue getFieldClassValue(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ return info != null ?
+ info.getReferencedClass() :
+ null;
+ }
+
+
+ private static void generalizeFieldValue(Field field, Value value)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ if (info != null)
+ {
+ info.generalizeValue(value);
+ }
+ }
+
+
+ public static Value getFieldValue(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ return info != null ?
+ info.getValue() :
+ null;
+ }
+
+
+ private static void generalizeMethodParameterValue(Method method, int parameterIndex, Value value)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.generalizeParameter(parameterIndex, value);
+ }
+ }
+
+
+ public static Value getMethodParameterValue(Method method, int parameterIndex)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null ?
+ info.getParameter(parameterIndex) :
+ null;
+ }
+
+
+ private static void generalizeMethodReturnValue(Method method, Value value)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.generalizeReturnValue(value);
+ }
+ }
+
+
+ public static Value getMethodReturnValue(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null ?
+ info.getReturnValue() :
+ null;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/TracedBranchUnit.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/TracedBranchUnit.java
new file mode 100644
index 0000000000..8d6e1504ab
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/TracedBranchUnit.java
@@ -0,0 +1,59 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.Clazz;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.evaluation.BasicBranchUnit;
+import proguard.evaluation.value.Value;
+
+/**
+ * This BranchUnit remembers the branch unit commands that are invoked on it.
+ *
+ * @author Eric Lafortune
+ */
+class TracedBranchUnit
+extends BasicBranchUnit
+{
+ // Implementations for BranchUnit.
+
+ public void branchConditionally(Clazz clazz,
+ CodeAttribute codeAttribute,
+ int offset,
+ int branchTarget,
+ int conditional)
+ {
+ if (conditional == Value.ALWAYS)
+ {
+ // Always branch.
+ super.branch(clazz, codeAttribute, offset, branchTarget);
+ }
+ else if (conditional != Value.NEVER)
+ {
+ // Maybe branch.
+ super.branchConditionally(clazz, codeAttribute, offset, branchTarget, conditional);
+ }
+ else
+ {
+ super.setCalled();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/VariableOptimizer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/VariableOptimizer.java
new file mode 100644
index 0000000000..239ec2ea61
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/VariableOptimizer.java
@@ -0,0 +1,357 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.evaluation;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.editor.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This AttributeVisitor optimizes variable allocation based on their the liveness,
+ * in the code attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableOptimizer
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("vo") != null;
+ //*/
+
+ private static final int MAX_VARIABLES_SIZE = 64;
+
+
+ private final boolean reuseThis;
+ private final MemberVisitor extraVariableMemberVisitor;
+
+ private final LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
+ private final VariableRemapper variableRemapper = new VariableRemapper();
+ private VariableCleaner variableCleaner = new VariableCleaner();
+
+ private int[] variableMap = new int[ClassConstants.TYPICAL_VARIABLES_SIZE];
+
+
+ /**
+ * Creates a new VariableOptimizer.
+ * @param reuseThis specifies whether the 'this' variable can be reused.
+ * Many JVMs for JME and IBM's JVMs for JSE can't handle
+ * such reuse.
+ */
+ public VariableOptimizer(boolean reuseThis)
+ {
+ this(reuseThis, null);
+ }
+
+
+ /**
+ * Creates a new VariableOptimizer with an extra visitor.
+ * @param reuseThis specifies whether the 'this' variable
+ * can be reused. Many JVMs for JME and
+ * IBM's JVMs for JSE can't handle such
+ * reuse.
+ * @param extraVariableMemberVisitor an optional extra visitor for all
+ * removed variables.
+ */
+ public VariableOptimizer(boolean reuseThis,
+ MemberVisitor extraVariableMemberVisitor)
+ {
+ this.reuseThis = reuseThis;
+ this.extraVariableMemberVisitor = extraVariableMemberVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ // Initialize the global arrays.
+ initializeArrays(codeAttribute);
+
+ // Analyze the liveness of the variables in the code.
+ livenessAnalyzer.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Trim the variables in the local variable tables, because even
+ // clipping the tables individually may leave some inconsistencies
+ // between them.
+ codeAttribute.attributesAccept(clazz, method, this);
+
+ int startIndex =
+ (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ||
+ reuseThis ? 0 : 1;
+
+ int parameterSize =
+ ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz),
+ method.getAccessFlags());
+
+ int variableSize = codeAttribute.u2maxLocals;
+ int codeLength = codeAttribute.u4codeLength;
+
+ boolean remapping = false;
+
+ // Loop over all variables.
+ for (int oldIndex = 0; oldIndex < variableSize; oldIndex++)
+ {
+ // By default, the variable will be mapped onto itself.
+ variableMap[oldIndex] = oldIndex;
+
+ // Only try remapping the variable if it's not a parameter.
+ if (oldIndex >= parameterSize &&
+ oldIndex < MAX_VARIABLES_SIZE)
+ {
+ // Try to remap the variable to a variable with a smaller index.
+ for (int newIndex = startIndex; newIndex < oldIndex; newIndex++)
+ {
+ if (areNonOverlapping(oldIndex, newIndex, codeLength))
+ {
+ variableMap[oldIndex] = newIndex;
+
+ updateLiveness(oldIndex, newIndex, codeLength);
+
+ remapping = true;
+
+ // This variable has been remapped. Go to the next one.
+ break;
+ }
+ }
+ }
+ }
+
+ // Have we been able to remap any variables?
+ if (remapping)
+ {
+ if (DEBUG)
+ {
+ System.out.println("VariableOptimizer: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ for (int index= 0; index < variableSize; index++)
+ {
+ System.out.println(" v"+index+" -> "+variableMap[index]);
+ }
+ }
+
+ // Remap the variables.
+ variableRemapper.setVariableMap(variableMap);
+ variableRemapper.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Visit the method, if required.
+ if (extraVariableMemberVisitor != null)
+ {
+ method.accept(clazz, extraVariableMemberVisitor);
+ }
+ }
+ else
+ {
+ // Just clean up any empty variables.
+ variableCleaner.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Trim the variables in the local variable table.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Trim the variables in the local variable type table.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Trim the local variable to the instructions at which it is alive.
+ int variable = localVariableInfo.u2index;
+ int startPC = localVariableInfo.u2startPC;
+ int endPC = startPC + localVariableInfo.u2length;
+
+ startPC = firstLiveness(startPC, endPC, variable);
+ endPC = lastLiveness(startPC, endPC, variable);
+
+ // Leave the start address of unused variables unchanged.
+ int length = endPC - startPC;
+ if (length > 0)
+ {
+ localVariableInfo.u2startPC = startPC;
+ }
+
+ localVariableInfo.u2length = length;
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Trim the local variable type to the instructions at which it is alive.
+ int variable = localVariableTypeInfo.u2index;
+ int startPC = localVariableTypeInfo.u2startPC;
+ int endPC = startPC + localVariableTypeInfo.u2length;
+
+ startPC = firstLiveness(startPC, endPC, variable);
+ endPC = lastLiveness(startPC, endPC, variable);
+
+ // Leave the start address of unused variables unchanged.
+ int length = endPC - startPC;
+ if (length > 0)
+ {
+ localVariableTypeInfo.u2startPC = startPC;
+ }
+
+ localVariableTypeInfo.u2length = length;
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Initializes the global arrays.
+ */
+ private void initializeArrays(CodeAttribute codeAttribute)
+ {
+ int codeLength = codeAttribute.u4codeLength;
+
+ // Create new arrays for storing information at each instruction offset.
+ if (variableMap.length < codeLength)
+ {
+ variableMap = new int[codeLength];
+ }
+ }
+
+
+ /**
+ * Returns whether the given variables are never alive at the same time.
+ */
+ private boolean areNonOverlapping(int variableIndex1,
+ int variableIndex2,
+ int codeLength)
+ {
+ // Loop over all instructions.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ if ((livenessAnalyzer.isAliveBefore(offset, variableIndex1) &&
+ livenessAnalyzer.isAliveBefore(offset, variableIndex2)) ||
+
+ (livenessAnalyzer.isAliveAfter(offset, variableIndex1) &&
+ livenessAnalyzer.isAliveAfter(offset, variableIndex2)) ||
+
+ // For now, exclude Category 2 variables.
+ livenessAnalyzer.isCategory2(offset, variableIndex1))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Updates the liveness resulting from mapping the given old variable on
+ * the given new variable.
+ */
+ private void updateLiveness(int oldVariableIndex,
+ int newVariableIndex,
+ int codeLength)
+ {
+ // Loop over all instructions.
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ // Update the liveness before the instruction.
+ if (livenessAnalyzer.isAliveBefore(offset, oldVariableIndex))
+ {
+ livenessAnalyzer.setAliveBefore(offset, oldVariableIndex, false);
+ livenessAnalyzer.setAliveBefore(offset, newVariableIndex, true);
+ }
+
+ // Update the liveness after the instruction.
+ if (livenessAnalyzer.isAliveAfter(offset, oldVariableIndex))
+ {
+ livenessAnalyzer.setAliveAfter(offset, oldVariableIndex, false);
+ livenessAnalyzer.setAliveAfter(offset, newVariableIndex, true);
+ }
+ }
+ }
+
+
+ /**
+ * Returns the first instruction offset between the given offsets at which
+ * the given variable goes alive.
+ */
+ private int firstLiveness(int startOffset, int endOffset, int variableIndex)
+ {
+ for (int offset = startOffset; offset < endOffset; offset++)
+ {
+ if (livenessAnalyzer.isTraced(offset) &&
+ livenessAnalyzer.isAliveBefore(offset, variableIndex))
+ {
+ return offset;
+ }
+ }
+
+ return endOffset;
+ }
+
+
+ /**
+ * Returns the last instruction offset between the given offsets before
+ * which the given variable is still alive.
+ */
+ private int lastLiveness(int startOffset, int endOffset, int variableIndex)
+ {
+ int previousOffset = endOffset;
+
+ for (int offset = endOffset-1; offset >= startOffset; offset--)
+ {
+ if (livenessAnalyzer.isTraced(offset))
+ {
+ if (livenessAnalyzer.isAliveBefore(offset, variableIndex))
+ {
+ return previousOffset;
+ }
+
+ previousOffset = offset;
+ }
+ }
+
+ return endOffset;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/package.html
new file mode 100644
index 0000000000..5341f9f8b6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/evaluation/package.html
@@ -0,0 +1,4 @@
+<body>
+This package contains visitors that perform partial evaluation and subsequent
+optimizations on byte code.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/AccessMethodMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/AccessMethodMarker.java
new file mode 100644
index 0000000000..b030c55ddb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/AccessMethodMarker.java
@@ -0,0 +1,201 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This InstructionVisitor marks the types of class accesses and class member
+ * accesses of the methods whose instructions it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AccessMethodMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ ClassVisitor,
+ MemberVisitor
+{
+ private Method invokingMethod;
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ invokingMethod = method;
+
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Check the referenced class or class member, if any.
+ stringConstant.referencedClassAccept(this);
+ stringConstant.referencedMemberAccept(this);
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Check the bootstrap method.
+ invokeDynamicConstant.bootstrapMethodHandleAccept(clazz, this);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Check the method reference.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Check the referenced class.
+ clazz.constantPoolEntryAccept(refConstant.u2classIndex, this);
+
+ // Check the referenced class member itself.
+ refConstant.referencedClassAccept(this);
+ refConstant.referencedMemberAccept(this);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Check the referenced class.
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ int accessFlags = clazz.getAccessFlags();
+
+ if ((accessFlags & ClassConstants.ACC_PUBLIC) == 0)
+ {
+ setAccessesPackageCode(invokingMethod);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ int accessFlags = member.getAccessFlags();
+
+ if ((accessFlags & ClassConstants.ACC_PRIVATE) != 0)
+ {
+ setAccessesPrivateCode(invokingMethod);
+ }
+ else if ((accessFlags & ClassConstants.ACC_PROTECTED) != 0)
+ {
+ setAccessesProtectedCode(invokingMethod);
+ }
+ else if ((accessFlags & ClassConstants.ACC_PUBLIC) == 0)
+ {
+ setAccessesPackageCode(invokingMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void setAccessesPrivateCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setAccessesPrivateCode();
+ }
+ }
+
+
+ /**
+ * Returns whether the given method accesses private class members.
+ */
+ public static boolean accessesPrivateCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.accessesPrivateCode();
+ }
+
+
+ private static void setAccessesPackageCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setAccessesPackageCode();
+ }
+ }
+
+
+ /**
+ * Returns whether the given method accesses package visible classes or class
+ * members.
+ */
+ public static boolean accessesPackageCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.accessesPackageCode();
+ }
+
+
+ private static void setAccessesProtectedCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setAccessesProtectedCode();
+ }
+ }
+
+
+ /**
+ * Returns whether the given method accesses protected class members.
+ */
+ public static boolean accessesProtectedCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.accessesProtectedCode();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/BackwardBranchMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/BackwardBranchMarker.java
new file mode 100644
index 0000000000..af1862e36e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/BackwardBranchMarker.java
@@ -0,0 +1,90 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor marks all methods that branch backward in any of the
+ * instructions that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class BackwardBranchMarker
+extends SimplifiedVisitor
+implements InstructionVisitor
+{
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ markBackwardBranch(method, branchInstruction.branchOffset);
+ }
+
+
+ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ {
+ markBackwardBranch(method, switchInstruction.defaultOffset);
+
+ for (int index = 0; index < switchInstruction.jumpOffsets.length; index++)
+ {
+ markBackwardBranch(method, switchInstruction.jumpOffsets[index]);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given method if the given branch offset is negative.
+ */
+ private void markBackwardBranch(Method method, int branchOffset)
+ {
+ if (branchOffset < 0)
+ {
+ setBranchesBackward(method);
+ }
+ }
+
+
+ private static void setBranchesBackward(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setBranchesBackward();
+ }
+ }
+
+
+ public static boolean branchesBackward(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.branchesBackward();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CatchExceptionMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CatchExceptionMarker.java
new file mode 100644
index 0000000000..9105142d6e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CatchExceptionMarker.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor marks all methods that catch exceptions.
+ *
+ * @author Eric Lafortune
+ */
+public class CatchExceptionMarker
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (codeAttribute.u2exceptionTableLength > 0)
+ {
+ markCatchException(method);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void markCatchException(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setCatchesExceptions();
+ }
+ }
+
+
+ public static boolean catchesExceptions(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null ||
+ info.catchesExceptions();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CaughtClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CaughtClassFilter.java
new file mode 100644
index 0000000000..78f10cf034
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CaughtClassFilter.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are caught as exceptions.
+ *
+ * @see CaughtClassMarker
+ * @author Eric Lafortune
+ */
+public class CaughtClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public CaughtClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (CaughtClassMarker.isCaught(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (CaughtClassMarker.isCaught(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CaughtClassMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CaughtClassMarker.java
new file mode 100644
index 0000000000..9d4a1e9e52
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/CaughtClassMarker.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor marks all program classes that it visits as caught.
+ * This means that these classes are exception classes that occur in exception
+ * handlers.
+ *
+ * @author Eric Lafortune
+ */
+public class CaughtClassMarker
+implements ClassVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ setCaught(programClass);
+ }
+
+
+ // Small utility methods.
+
+ private static void setCaught(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setCaught();
+ }
+ }
+
+
+ public static boolean isCaught(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.isCaught();
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ClassOptimizationInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ClassOptimizationInfo.java
new file mode 100644
index 0000000000..4bf1e9fd69
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ClassOptimizationInfo.java
@@ -0,0 +1,177 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.Clazz;
+
+/**
+ * This class stores some optimization information that can be attached to
+ * a class.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassOptimizationInfo
+{
+ private boolean isInstantiated = false;
+ private boolean isInstanceofed = false;
+ private boolean isDotClassed = false;
+ private boolean isCaught = false;
+ private boolean isSimpleEnum = false;
+ private boolean containsStaticInitializer = false;
+ private boolean containsPackageVisibleMembers = false;
+ private boolean invokesPackageVisibleMembers = false;
+ private Clazz targetClass;
+
+
+ public void setInstantiated()
+ {
+ isInstantiated = true;
+ }
+
+
+ public boolean isInstantiated()
+ {
+ return isInstantiated;
+ }
+
+
+ public void setInstanceofed()
+ {
+ isInstanceofed = true;
+ }
+
+
+ public boolean isInstanceofed()
+ {
+ return isInstanceofed;
+ }
+
+
+ public void setDotClassed()
+ {
+ isDotClassed = true;
+ }
+
+
+ public boolean isDotClassed()
+ {
+ return isDotClassed;
+ }
+
+
+ public void setCaught()
+ {
+ isCaught = true;
+ }
+
+
+ public boolean isCaught()
+ {
+ return isCaught;
+ }
+
+
+ public void setSimpleEnum(boolean simple)
+ {
+ isSimpleEnum = simple;
+ }
+
+
+ public boolean isSimpleEnum()
+ {
+ return isSimpleEnum;
+ }
+
+
+ public void setContainsStaticInitializer()
+ {
+ containsStaticInitializer = true;
+ }
+
+
+ public boolean containsStaticInitializer()
+ {
+ return containsStaticInitializer;
+ }
+
+
+ public void setContainsPackageVisibleMembers()
+ {
+ containsPackageVisibleMembers = true;
+ }
+
+
+ public boolean containsPackageVisibleMembers()
+ {
+ return containsPackageVisibleMembers;
+ }
+
+
+ public void setInvokesPackageVisibleMembers()
+ {
+ invokesPackageVisibleMembers = true;
+ }
+
+
+ public boolean invokesPackageVisibleMembers()
+ {
+ return invokesPackageVisibleMembers;
+ }
+
+
+ public void setTargetClass(Clazz targetClass)
+ {
+ this.targetClass = targetClass;
+ }
+
+
+ public Clazz getTargetClass()
+ {
+ return targetClass;
+ }
+
+
+ public void merge(ClassOptimizationInfo other)
+ {
+ this.isInstantiated |= other.isInstantiated;
+ this.isInstanceofed |= other.isInstanceofed;
+ this.isDotClassed |= other.isDotClassed;
+ this.isCaught |= other.isCaught;
+ this.containsStaticInitializer |= other.containsStaticInitializer;
+ this.containsPackageVisibleMembers |= other.containsPackageVisibleMembers;
+ this.invokesPackageVisibleMembers |= other.invokesPackageVisibleMembers;
+ }
+
+
+ public static void setClassOptimizationInfo(Clazz clazz)
+ {
+ clazz.setVisitorInfo(new ClassOptimizationInfo());
+ }
+
+
+ public static ClassOptimizationInfo getClassOptimizationInfo(Clazz clazz)
+ {
+ Object visitorInfo = clazz.getVisitorInfo();
+ return visitorInfo instanceof ClassOptimizationInfo ?
+ (ClassOptimizationInfo)visitorInfo :
+ null;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ClassOptimizationInfoSetter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
new file mode 100644
index 0000000000..ea143d68be
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
@@ -0,0 +1,47 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.ProgramClass;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+import proguard.optimize.KeepMarker;
+
+/**
+ * This ClassVisitor attaches a ClassOptimizationInfo instance to every class
+ * that is not being kept that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassOptimizationInfoSetter
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ // Implementations for MemberVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (!KeepMarker.isKept(programClass))
+ {
+ ClassOptimizationInfo.setClassOptimizationInfo(programClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DotClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DotClassFilter.java
new file mode 100644
index 0000000000..9c85568357
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DotClassFilter.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are used in a .class construct.
+ *
+ * @see DotClassMarker
+ * @author Eric Lafortune
+ */
+public class DotClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public DotClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (DotClassMarker.isDotClassed(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (DotClassMarker.isDotClassed(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DotClassMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DotClassMarker.java
new file mode 100644
index 0000000000..d7f8fa3149
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DotClassMarker.java
@@ -0,0 +1,96 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This InstructionVisitor marks all classes that are used in a .class
+ * construct by any of the instructions that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class DotClassMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ ClassVisitor
+{
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ if (constantInstruction.opcode == InstructionConstants.OP_LDC ||
+ constantInstruction.opcode == InstructionConstants.OP_LDC_W)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ setDotClassed(programClass);
+ }
+
+
+ // Small utility methods.
+
+ private static void setDotClassed(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setDotClassed();
+ }
+ }
+
+
+ public static boolean isDotClassed(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.isDotClassed();
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DynamicInvocationMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DynamicInvocationMarker.java
new file mode 100644
index 0000000000..f59244cfbf
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/DynamicInvocationMarker.java
@@ -0,0 +1,79 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This InstructionVisitor marks whether the methods whose instructions it
+ * visits contain the invokedynamic instruction.
+ *
+ * @author Eric Lafortune
+ */
+public class DynamicInvocationMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ ClassVisitor,
+ MemberVisitor
+{
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ if (constantInstruction.opcode == InstructionConstants.OP_INVOKEDYNAMIC)
+ {
+ setInvokesDynamically(method);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void setInvokesDynamically(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setInvokesDynamically();
+ }
+ }
+
+
+ /**
+ * Returns whether the given method calls the invokedynamic instruction.
+ */
+ public static boolean invokesDynamically(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.invokesDynamically();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ExceptionInstructionChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ExceptionInstructionChecker.java
new file mode 100644
index 0000000000..727139116f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ExceptionInstructionChecker.java
@@ -0,0 +1,260 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This class can tell whether an instruction might throw exceptions.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionInstructionChecker
+extends SimplifiedVisitor
+implements InstructionVisitor
+// ConstantVisitor,
+// MemberVisitor
+{
+ // A return value for the visitor methods.
+ private boolean mayThrowExceptions;
+
+
+ /**
+ * Returns whether the specified method may throw exceptions.
+ */
+ public boolean mayThrowExceptions(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute)
+ {
+ return mayThrowExceptions(clazz,
+ method,
+ codeAttribute,
+ 0,
+ codeAttribute.u4codeLength);
+ }
+
+
+ /**
+ * Returns whether the specified block of code may throw exceptions.
+ */
+ public boolean mayThrowExceptions(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int startOffset,
+ int endOffset)
+ {
+ byte[] code = codeAttribute.code;
+
+ // Go over all instructions.
+ int offset = startOffset;
+ while (offset < endOffset)
+ {
+ // Get the current instruction.
+ Instruction instruction = InstructionFactory.create(code, offset);
+
+ // Check if it may be throwing exceptions.
+ if (mayThrowExceptions(clazz,
+ method,
+ codeAttribute,
+ offset,
+ instruction))
+ {
+ return true;
+ }
+
+ // Go to the next instruction.
+ offset += instruction.length(offset);
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns whether the specified instruction may throw exceptions.
+ */
+ public boolean mayThrowExceptions(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int offset)
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code, offset);
+
+ return mayThrowExceptions(clazz,
+ method,
+ codeAttribute,
+ offset,
+ instruction);
+ }
+
+
+ /**
+ * Returns whether the given instruction may throw exceptions.
+ */
+ public boolean mayThrowExceptions(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int offset,
+ Instruction instruction)
+ {
+ return instruction.mayThrowExceptions();
+
+// mayThrowExceptions = false;
+//
+// instruction.accept(clazz, method, codeAttribute, offset, this);
+//
+// return mayThrowExceptions;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ // Check for instructions that may throw exceptions.
+ // Note that monitorexit can not sensibly throw exceptions, except the
+ // broken and deprecated asynchronous ThreadDeath. Removing the
+ // artificial infinite looping exception blocks that recent compilers
+ // add does not strictly follow the JVM specs, but it does have the
+ // additional benefit of avoiding a bug in the JVM in JDK 1.1.
+ switch (simpleInstruction.opcode)
+ {
+ case InstructionConstants.OP_IDIV:
+ case InstructionConstants.OP_LDIV:
+ case InstructionConstants.OP_IREM:
+ case InstructionConstants.OP_LREM:
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_LALOAD:
+ case InstructionConstants.OP_FALOAD:
+ case InstructionConstants.OP_DALOAD:
+ case InstructionConstants.OP_AALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+ case InstructionConstants.OP_IASTORE:
+ case InstructionConstants.OP_LASTORE:
+ case InstructionConstants.OP_FASTORE:
+ case InstructionConstants.OP_DASTORE:
+ case InstructionConstants.OP_AASTORE:
+ case InstructionConstants.OP_BASTORE:
+ case InstructionConstants.OP_CASTORE:
+ case InstructionConstants.OP_SASTORE:
+ case InstructionConstants.OP_NEWARRAY:
+ case InstructionConstants.OP_ARRAYLENGTH:
+ case InstructionConstants.OP_ATHROW:
+ case InstructionConstants.OP_MONITORENTER:
+ // These instructions may throw exceptions.
+ mayThrowExceptions = true;
+ }
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ // Check for instructions that may throw exceptions.
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_GETFIELD:
+ case InstructionConstants.OP_PUTFIELD:
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ case InstructionConstants.OP_NEW:
+ case InstructionConstants.OP_ANEWARRAY:
+ case InstructionConstants.OP_CHECKCAST:
+ case InstructionConstants.OP_INSTANCEOF:
+ case InstructionConstants.OP_MULTIANEWARRAY:
+ // These instructions may throw exceptions.
+ mayThrowExceptions = true;
+
+// case InstructionConstants.OP_INVOKEVIRTUAL:
+// case InstructionConstants.OP_INVOKESPECIAL:
+// case InstructionConstants.OP_INVOKESTATIC:
+// case InstructionConstants.OP_INVOKEINTERFACE:
+// // Check if the invoking the method may throw an exception.
+// clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ }
+
+
+// // Implementations for ConstantVisitor.
+//
+// public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+// {
+// Member referencedMember = refConstant.referencedMember;
+//
+// // Do we have a reference to the method?
+// if (referencedMember == null)
+// {
+// // We'll have to assume invoking the unknown method may throw an
+// // an exception.
+// mayThrowExceptions = true;
+// }
+// else
+// {
+// // First check the referenced method itself.
+// refConstant.referencedMemberAccept(this);
+//
+// // If the result isn't conclusive, check down the hierarchy.
+// if (!mayThrowExceptions)
+// {
+// Clazz referencedClass = refConstant.referencedClass;
+// Method referencedMethod = (Method)referencedMember;
+//
+// // Check all other implementations of the method in the class
+// // hierarchy.
+// referencedClass.methodImplementationsAccept(referencedMethod,
+// false,
+// false,
+// true,
+// true,
+// this);
+// }
+// }
+// }
+//
+//
+// // Implementations for MemberVisitor.
+//
+// public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+// {
+// mayThrowExceptions = mayThrowExceptions ||
+// ExceptionMethodMarker.mayThrowExceptions(programMethod);
+// }
+//
+//
+// public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+// {
+// mayThrowExceptions = mayThrowExceptions ||
+// !NoExceptionMethodMarker.doesntThrowExceptions(libraryMethod);
+// }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/FieldOptimizationInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/FieldOptimizationInfo.java
new file mode 100644
index 0000000000..5be9ce7df3
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/FieldOptimizationInfo.java
@@ -0,0 +1,188 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.evaluation.ConstantValueFactory;
+import proguard.evaluation.value.*;
+
+/**
+ * This class stores some optimization information that can be attached to
+ * a field.
+ *
+ * @author Eric Lafortune
+ */
+public class FieldOptimizationInfo
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private static final ParticularValueFactory VALUE_FACTORY = new ParticularValueFactory();
+ private static final ConstantValueFactory CONSTANT_VALUE_FACTORY = new ConstantValueFactory(VALUE_FACTORY);
+ private static final InitialValueFactory INITIAL_VALUE_FACTORY = new InitialValueFactory(VALUE_FACTORY);
+
+ private boolean isWritten;
+ private boolean isRead;
+ private boolean canBeMadePrivate = true;
+ private ReferenceValue referencedClass;
+ private Value value;
+
+
+ public FieldOptimizationInfo(Clazz clazz, Field field)
+ {
+ int accessFlags = field.getAccessFlags();
+
+ isWritten =
+ isRead = (accessFlags & ClassConstants.ACC_VOLATILE) != 0;
+
+ resetValue(clazz, field);
+ }
+
+
+ public FieldOptimizationInfo(FieldOptimizationInfo FieldOptimizationInfo)
+ {
+ this.isWritten = FieldOptimizationInfo.isWritten;
+ this.isRead = FieldOptimizationInfo.isRead;
+ this.canBeMadePrivate = FieldOptimizationInfo.canBeMadePrivate;
+ this.referencedClass = FieldOptimizationInfo.referencedClass;
+ this.value = FieldOptimizationInfo.value;
+ }
+
+
+ public void setWritten()
+ {
+ isWritten = true;
+ }
+
+
+ public boolean isWritten()
+ {
+ return isWritten;
+ }
+
+
+ public void setRead()
+ {
+ isRead = true;
+ }
+
+
+ public boolean isRead()
+ {
+ return isRead;
+ }
+
+
+ public void setCanNotBeMadePrivate()
+ {
+ canBeMadePrivate = false;
+ }
+
+
+ public boolean canBeMadePrivate()
+ {
+ return canBeMadePrivate;
+ }
+
+
+ public void generalizeReferencedClass(ReferenceValue referencedClass)
+ {
+ this.referencedClass = this.referencedClass != null ?
+ this.referencedClass.generalize(referencedClass) :
+ referencedClass;
+ }
+
+
+ public ReferenceValue getReferencedClass()
+ {
+ return referencedClass;
+ }
+
+
+ public void resetValue(Clazz clazz, Field field)
+ {
+ int accessFlags = field.getAccessFlags();
+
+ value = null;
+
+ // See if we can initialize a static field with a constant value.
+ if ((accessFlags & ClassConstants.ACC_STATIC) != 0)
+ {
+ field.accept(clazz, new AllAttributeVisitor(this));
+ }
+
+ // Otherwise initialize a non-final field with the default value.
+ // Conservatively, even a final field needs to be initialized with the
+ // default value, because it may be accessed before it is set.
+ if (value == null &&
+ (SideEffectInstructionChecker.OPTIMIZE_CONSERVATIVELY ||
+ (accessFlags & ClassConstants.ACC_FINAL) == 0))
+ {
+ value = INITIAL_VALUE_FACTORY.createValue(field.getDescriptor(clazz));
+ }
+ }
+
+
+ public void generalizeValue(Value value)
+ {
+ this.value = this.value != null ?
+ this.value.generalize(value) :
+ value;
+ }
+
+
+ public Value getValue()
+ {
+ return value;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ // Retrieve the initial static field value.
+ value = CONSTANT_VALUE_FACTORY.constantValue(clazz, constantValueAttribute.u2constantValueIndex);
+ }
+
+
+ // Small utility methods.
+
+ public static void setFieldOptimizationInfo(Clazz clazz, Field field)
+ {
+ field.setVisitorInfo(new FieldOptimizationInfo(clazz, field));
+ }
+
+
+ public static FieldOptimizationInfo getFieldOptimizationInfo(Field field)
+ {
+ Object visitorInfo = field.getVisitorInfo();
+
+ return visitorInfo instanceof FieldOptimizationInfo ?
+ (FieldOptimizationInfo)visitorInfo :
+ null;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstanceofClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstanceofClassFilter.java
new file mode 100644
index 0000000000..35d3b5d2c0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstanceofClassFilter.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are used in an 'instanceof' test.
+ *
+ * @see InstanceofClassMarker
+ * @author Eric Lafortune
+ */
+public class InstanceofClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public InstanceofClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (InstanceofClassMarker.isInstanceofed(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (InstanceofClassMarker.isInstanceofed(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstanceofClassMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstanceofClassMarker.java
new file mode 100644
index 0000000000..26cc9665af
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstanceofClassMarker.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This InstructionVisitor marks all classes that are used in an 'instanceof'
+ * test by any of the instructions that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class InstanceofClassMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ ClassVisitor
+{
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ if (constantInstruction.opcode == InstructionConstants.OP_INSTANCEOF)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ setInstanceofed(programClass);
+ }
+
+
+ // Small utility methods.
+
+ private static void setInstanceofed(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setInstanceofed();
+ }
+ }
+
+
+ public static boolean isInstanceofed(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.isInstanceofed();
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstantiationClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstantiationClassFilter.java
new file mode 100644
index 0000000000..804e9d0caf
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstantiationClassFilter.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are instantiated.
+ *
+ * @author Eric Lafortune
+ */
+public class InstantiationClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public InstantiationClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (InstantiationClassMarker.isInstantiated(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (InstantiationClassMarker.isInstantiated(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstantiationClassMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstantiationClassMarker.java
new file mode 100644
index 0000000000..610be97e48
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/InstantiationClassMarker.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This InstructionVisitor marks all classes that are instantiated by any of
+ * the instructions that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class InstantiationClassMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ ClassVisitor
+{
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ if (constantInstruction.opcode == InstructionConstants.OP_NEW)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ setInstantiated(programClass);
+ }
+
+
+ // Small utility methods.
+
+ private static void setInstantiated(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setInstantiated();
+ }
+ }
+
+
+ public static boolean isInstantiated(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.isInstantiated();
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MemberOptimizationInfoSetter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
new file mode 100644
index 0000000000..4a09e09edc
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
@@ -0,0 +1,59 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.KeepMarker;
+
+/**
+ * This MemberVisitor attaches a FieldOptimizationInfo instance to every field
+ * and a MethodOptimizationInfo instance to every method that is not being kept
+ * that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberOptimizationInfoSetter
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (!KeepMarker.isKept(programField))
+ {
+ FieldOptimizationInfo.setFieldOptimizationInfo(programClass,
+ programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (!KeepMarker.isKept(programMethod))
+ {
+ MethodOptimizationInfo.setMethodOptimizationInfo(programClass,
+ programMethod);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MethodInvocationMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MethodInvocationMarker.java
new file mode 100644
index 0000000000..2288669df6
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MethodInvocationMarker.java
@@ -0,0 +1,107 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This InstructionVisitor counts the number of times methods are invoked from
+ * the instructions that are visited.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodInvocationMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Mark the referenced method, if any.
+ stringConstant.referencedMemberAccept(this);
+ }
+
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Mark the referenced method.
+ refConstant.referencedMemberAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz Clazz, Member member) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ incrementInvocationCount(programMethod);
+ }
+
+
+ // Small utility methods.
+
+ private static void incrementInvocationCount(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.incrementInvocationCount();
+ }
+ }
+
+
+ /**
+ * Returns the number of times the given method was invoked by the
+ * instructions that were visited.
+ */
+ public static int getInvocationCount(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null ? info.getInvocationCount() :
+ Integer.MAX_VALUE;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MethodOptimizationInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MethodOptimizationInfo.java
new file mode 100644
index 0000000000..2e56910895
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/MethodOptimizationInfo.java
@@ -0,0 +1,336 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.evaluation.value.Value;
+
+/**
+ * This class stores some optimization information that can be attached to
+ * a method.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodOptimizationInfo
+{
+ private boolean hasNoSideEffects = false;
+ private boolean hasSideEffects = false;
+ private boolean canBeMadePrivate = true;
+ private boolean catchesExceptions = false;
+ private boolean branchesBackward = false;
+ private boolean invokesSuperMethods = false;
+ private boolean invokesDynamically = false;
+ private boolean accessesPrivateCode = false;
+ private boolean accessesPackageCode = false;
+ private boolean accessesProtectedCode = false;
+ private boolean returnsWithNonEmptyStack = false;
+ private int invocationCount = 0;
+ private int parameterSize = 0;
+ private long usedParameters = 0L;
+ private Value[] parameters;
+ private Value returnValue;
+
+
+ /**
+ * Creates a new MethodOptimizationInfo for the given method.
+ */
+ public MethodOptimizationInfo(Clazz clazz, Method method)
+ {
+ // Set up an array of the right size for storing information about the
+ // passed parameters.
+ int parameterCount =
+ ClassUtil.internalMethodParameterCount(method.getDescriptor(clazz));
+
+ if ((method.getAccessFlags() & ClassConstants.ACC_STATIC) == 0)
+ {
+ parameterCount++;
+ }
+
+ if (parameterCount > 0)
+ {
+ parameters = new Value[parameterCount];
+ }
+ }
+
+
+ public void setNoSideEffects()
+ {
+ hasNoSideEffects = true;
+ }
+
+
+ public boolean hasNoSideEffects()
+ {
+ return hasNoSideEffects;
+ }
+
+
+ public void setSideEffects()
+ {
+ hasSideEffects = true;
+ }
+
+
+ public boolean hasSideEffects()
+ {
+ return hasSideEffects;
+ }
+
+
+ public void setCanNotBeMadePrivate()
+ {
+ canBeMadePrivate = false;
+ }
+
+
+ public boolean canBeMadePrivate()
+ {
+ return canBeMadePrivate;
+ }
+
+
+ public void setCatchesExceptions()
+ {
+ catchesExceptions = true;
+ }
+
+
+ public boolean catchesExceptions()
+ {
+ return catchesExceptions;
+ }
+
+
+ public void setBranchesBackward()
+ {
+ branchesBackward = true;
+ }
+
+
+ public boolean branchesBackward()
+ {
+ return branchesBackward;
+ }
+
+
+ public void setInvokesSuperMethods()
+ {
+ invokesSuperMethods = true;
+ }
+
+
+ public boolean invokesSuperMethods()
+ {
+ return invokesSuperMethods;
+ }
+
+
+ public void setInvokesDynamically()
+ {
+ invokesDynamically = true;
+ }
+
+
+ public boolean invokesDynamically()
+ {
+ return invokesDynamically;
+ }
+
+
+ public void setAccessesPrivateCode()
+ {
+ accessesPrivateCode = true;
+ }
+
+
+ public boolean accessesPrivateCode()
+ {
+ return accessesPrivateCode;
+ }
+
+
+ public void setAccessesPackageCode()
+ {
+ accessesPackageCode = true;
+ }
+
+
+ public boolean accessesPackageCode()
+ {
+ return accessesPackageCode;
+ }
+
+
+ public void setAccessesProtectedCode()
+ {
+ accessesProtectedCode = true;
+ }
+
+
+ public boolean accessesProtectedCode()
+ {
+ return accessesProtectedCode;
+ }
+
+
+ public void setReturnsWithNonEmptyStack()
+ {
+ returnsWithNonEmptyStack = true;
+ }
+
+
+ public boolean returnsWithNonEmptyStack()
+ {
+ return returnsWithNonEmptyStack;
+ }
+
+
+ public void incrementInvocationCount()
+ {
+ invocationCount++;
+ }
+
+
+ public int getInvocationCount()
+ {
+ return invocationCount;
+ }
+
+
+ public void setParameterSize(int parameterSize)
+ {
+ this.parameterSize = parameterSize;
+ }
+
+
+ public int getParameterSize()
+ {
+ return parameterSize;
+ }
+
+
+ public void setParameterUsed(int parameterIndex)
+ {
+ usedParameters |= 1L << parameterIndex;
+ }
+
+
+ public void setUsedParameters(long usedParameters)
+ {
+ this.usedParameters = usedParameters;
+ }
+
+
+ public boolean isParameterUsed(int parameterIndex)
+ {
+ return parameterIndex >= 64 || (usedParameters & (1L << parameterIndex)) != 0;
+ }
+
+
+ public long getUsedParameters()
+ {
+ return usedParameters;
+ }
+
+
+ public void generalizeParameter(int parameterIndex, Value parameter)
+ {
+ parameters[parameterIndex] = parameters[parameterIndex] != null ?
+ parameters[parameterIndex].generalize(parameter) :
+ parameter;
+ }
+
+
+ public Value getParameter(int parameterIndex)
+ {
+ return parameters != null ?
+ parameters[parameterIndex] :
+ null;
+ }
+
+
+ public void generalizeReturnValue(Value returnValue)
+ {
+ this.returnValue = this.returnValue != null ?
+ this.returnValue.generalize(returnValue) :
+ returnValue;
+ }
+
+
+ public Value getReturnValue()
+ {
+ return returnValue;
+ }
+
+
+ // For setting enum return values.
+ public void setReturnValue(Value returnValue)
+ {
+ this.returnValue = returnValue;
+ }
+
+
+ public void merge(MethodOptimizationInfo other)
+ {
+ if (other != null)
+ {
+ this.hasNoSideEffects &= other.hasNoSideEffects;
+ this.hasSideEffects |= other.hasSideEffects;
+ //this.canBeMadePrivate &= other.canBeMadePrivate;
+ this.catchesExceptions |= other.catchesExceptions;
+ this.branchesBackward |= other.branchesBackward;
+ this.invokesSuperMethods |= other.invokesSuperMethods;
+ this.invokesDynamically |= other.invokesDynamically;
+ this.accessesPrivateCode |= other.accessesPrivateCode;
+ this.accessesPackageCode |= other.accessesPackageCode;
+ this.accessesProtectedCode |= other.accessesProtectedCode;
+ }
+ else
+ {
+ this.hasNoSideEffects = false;
+ this.hasSideEffects = true;
+ //this.canBeMadePrivate = false;
+ this.catchesExceptions = true;
+ this.branchesBackward = true;
+ this.invokesSuperMethods = true;
+ this.accessesPrivateCode = true;
+ this.accessesPackageCode = true;
+ this.accessesProtectedCode = true;
+ }
+ }
+
+
+ public static void setMethodOptimizationInfo(Clazz clazz, Method method)
+ {
+ MethodLinker.lastMember(method).setVisitorInfo(new MethodOptimizationInfo(clazz, method));
+ }
+
+
+ public static MethodOptimizationInfo getMethodOptimizationInfo(Method method)
+ {
+ Object visitorInfo = MethodLinker.lastMember(method).getVisitorInfo();
+
+ return visitorInfo instanceof MethodOptimizationInfo ?
+ (MethodOptimizationInfo)visitorInfo :
+ null;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NoSideEffectMethodMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NoSideEffectMethodMarker.java
new file mode 100644
index 0000000000..624b22a2ea
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NoSideEffectMethodMarker.java
@@ -0,0 +1,91 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor marks all methods that it visits as not having any side
+ * effects. It will make the SideEffectMethodMarker consider them as such
+ * without further analysis.
+ *
+ * @see SideEffectMethodMarker
+ * @author Eric Lafortune
+ */
+public class NoSideEffectMethodMarker
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ // A visitor info flag to indicate the visitor accepter is being kept,
+ // but that it doesn't have any side effects.
+ public static final Object KEPT_BUT_NO_SIDE_EFFECTS = new Object();
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz Clazz, Member member)
+ {
+ // Ignore any attempts to mark fields.
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ markNoSideEffects(programMethod);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ markNoSideEffects(libraryMethod);
+ }
+
+
+ // Small utility methods.
+
+ private static void markNoSideEffects(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setNoSideEffects();
+ }
+ else
+ {
+ MethodLinker.lastMember(method).setVisitorInfo(KEPT_BUT_NO_SIDE_EFFECTS);
+ }
+ }
+
+
+ public static boolean hasNoSideEffects(Method method)
+ {
+ if (MethodLinker.lastVisitorAccepter(method).getVisitorInfo() == KEPT_BUT_NO_SIDE_EFFECTS)
+ {
+ return true;
+ }
+
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null &&
+ info.hasNoSideEffects();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NonEmptyStackReturnMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NonEmptyStackReturnMarker.java
new file mode 100644
index 0000000000..12124126ca
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NonEmptyStackReturnMarker.java
@@ -0,0 +1,115 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.visitor.StackSizeComputer;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor marks all methods that return with a non-empty stack
+ * (other than the return value).
+ *
+ * @author Eric Lafortune
+ */
+public class NonEmptyStackReturnMarker
+extends SimplifiedVisitor
+implements InstructionVisitor
+{
+ private final StackSizeComputer stackSizeComputer;
+
+
+ /**
+ * Creates a new NonEmptyStackReturnMarker
+ * @param stackSizeComputer the stack size computer that can return the
+ * stack sizes at the instructions that are
+ * visited.
+ */
+ public NonEmptyStackReturnMarker(StackSizeComputer stackSizeComputer)
+ {
+ this.stackSizeComputer = stackSizeComputer;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ switch (simpleInstruction.opcode)
+ {
+ case InstructionConstants.OP_LRETURN:
+ case InstructionConstants.OP_DRETURN:
+ markReturnWithNonEmptyStack(method, offset, 2);
+ break;
+
+ case InstructionConstants.OP_IRETURN:
+ case InstructionConstants.OP_FRETURN:
+ case InstructionConstants.OP_ARETURN:
+ markReturnWithNonEmptyStack(method, offset, 1);
+ break;
+
+ case InstructionConstants.OP_RETURN:
+ markReturnWithNonEmptyStack(method, offset, 0);
+ break;
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given method if the stack before the given instruction offset
+ * has a size larger than the given size.
+ */
+ private void markReturnWithNonEmptyStack(Method method,
+ int offset,
+ int stackSize)
+ {
+ if (!stackSizeComputer.isReachable(offset) ||
+ stackSizeComputer.getStackSizeBefore(offset) > stackSize)
+ {
+ setReturnsWithNonEmptyStack(method);
+ }
+ }
+
+
+ private static void setReturnsWithNonEmptyStack(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setReturnsWithNonEmptyStack();
+ }
+ }
+
+
+ public static boolean returnsWithNonEmptyStack(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.returnsWithNonEmptyStack();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NonPrivateMemberMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NonPrivateMemberMarker.java
new file mode 100644
index 0000000000..99056083fe
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/NonPrivateMemberMarker.java
@@ -0,0 +1,171 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor marks all class members that can not be made private in the
+ * classes that it visits, and in the classes to which they refer.
+ *
+ * @author Eric Lafortune
+ */
+public class NonPrivateMemberMarker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ private final MethodImplementationFilter filteredMethodMarker = new MethodImplementationFilter(this);
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Mark all referenced class members in different classes.
+ programClass.constantPoolEntriesAccept(this);
+
+ // Explicitly mark the <clinit> method.
+ programClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT,
+ ClassConstants.METHOD_TYPE_CLINIT,
+ this);
+
+ // Explicitly mark the parameterless <init> method.
+ programClass.methodAccept(ClassConstants.METHOD_NAME_INIT,
+ ClassConstants.METHOD_TYPE_INIT,
+ this);
+
+ // Mark all methods that may have implementations.
+ programClass.methodsAccept(filteredMethodMarker);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Go over all methods.
+ libraryClass.methodsAccept(this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // The referenced class member, if any, can never be made private,
+ // even if it's in the same class.
+ stringConstant.referencedMemberAccept(this);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ Clazz referencedClass = refConstant.referencedClass;
+
+ // Is it referring to a class member in another class?
+ // The class member might be in another class, or
+ // it may be referenced through another class.
+ if (referencedClass != null &&
+ !referencedClass.equals(clazz) ||
+ !refConstant.getClassName(clazz).equals(clazz.getName()))
+ {
+ // The referenced class member can never be made private.
+ refConstant.referencedMemberAccept(this);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ markCanNotBeMadePrivate(programField);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ markCanNotBeMadePrivate(libraryField);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ markCanNotBeMadePrivate(programMethod);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ markCanNotBeMadePrivate(libraryMethod);
+ }
+
+
+ // Small utility methods.
+
+ private static void markCanNotBeMadePrivate(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ if (info != null)
+ {
+ info.setCanNotBeMadePrivate();
+ }
+ }
+
+
+ /**
+ * Returns whether the given field can be made private.
+ */
+ public static boolean canBeMadePrivate(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ return info != null &&
+ info.canBeMadePrivate();
+ }
+
+
+ private static void markCanNotBeMadePrivate(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setCanNotBeMadePrivate();
+ }
+ }
+
+
+ /**
+ * Returns whether the given method can be made private.
+ */
+ public static boolean canBeMadePrivate(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null &&
+ info.canBeMadePrivate();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
new file mode 100644
index 0000000000..6ac7b60c94
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
@@ -0,0 +1,85 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor marks all classes that contain package visible members.
+ *
+ * @author Eric Lafortune
+ */
+public class PackageVisibleMemberContainingClassMarker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ // Check the class itself.
+ if ((clazz.getAccessFlags() & ClassConstants.ACC_PUBLIC) == 0)
+ {
+ setPackageVisibleMembers(clazz);
+ }
+ else
+ {
+ // Check the members.
+ clazz.fieldsAccept(this);
+ clazz.methodsAccept(this);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ if ((member.getAccessFlags() &
+ (ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_PUBLIC)) == 0)
+ {
+ setPackageVisibleMembers(clazz);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void setPackageVisibleMembers(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setContainsPackageVisibleMembers();
+ }
+ }
+
+
+ public static boolean containsPackageVisibleMembers(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.containsPackageVisibleMembers();
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
new file mode 100644
index 0000000000..86ba808591
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
@@ -0,0 +1,129 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ConstantVisitor marks all classes that refer to package visible classes
+ * or class members.
+ *
+ * @author Eric Lafortune
+ */
+public class PackageVisibleMemberInvokingClassMarker
+extends SimplifiedVisitor
+implements ConstantVisitor,
+ ClassVisitor,
+ MemberVisitor
+{
+ private Clazz referencingClass;
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Check the referenced class and class member, if any.
+ if (stringConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ stringConstant.referencedClassAccept(this);
+ stringConstant.referencedMemberAccept(this);
+ }
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Check the referenced class and class member.
+ if (refConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ refConstant.referencedClassAccept(this);
+ refConstant.referencedMemberAccept(this);
+ }
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Check the referenced class.
+ if (classConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ classConstant.referencedClassAccept(this);
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ if ((clazz.getAccessFlags() &
+ ClassConstants.ACC_PUBLIC) == 0)
+ {
+ setInvokesPackageVisibleMembers(referencingClass);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ if ((member.getAccessFlags() &
+ (ClassConstants.ACC_PUBLIC |
+ ClassConstants.ACC_PRIVATE)) == 0)
+ {
+ setInvokesPackageVisibleMembers(referencingClass);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void setInvokesPackageVisibleMembers(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setInvokesPackageVisibleMembers();
+ }
+ }
+
+
+ public static boolean invokesPackageVisibleMembers(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.invokesPackageVisibleMembers();
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ParameterUsageMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ParameterUsageMarker.java
new file mode 100644
index 0000000000..85e348cc42
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ParameterUsageMarker.java
@@ -0,0 +1,285 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.evaluation.value.Value;
+import proguard.optimize.evaluation.PartialEvaluator;
+
+/**
+ * This MemberVisitor counts the parameters and marks the used parameters
+ * of the methods that it visits. It also marks the 'this' parameters of
+ * methods that have hierarchies.
+ *
+ * @author Eric Lafortune
+ */
+public class ParameterUsageMarker
+extends SimplifiedVisitor
+implements MemberVisitor,
+ AttributeVisitor,
+ InstructionVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ private final boolean markThisParameter;
+ private final boolean markAllParameters;
+ private final PartialEvaluator partialEvaluator = new PartialEvaluator();
+
+
+ /**
+ * Creates a new ParameterUsageMarker.
+ */
+ public ParameterUsageMarker()
+ {
+ this(false, false);
+ }
+
+
+ /**
+ * Creates a new ParameterUsageMarker that optionally marks all parameters.
+ * @param markThisParameter specifies whether all 'this' parameters should
+ * be marked as being used.
+ * @param markAllParameters specifies whether all other parameters should
+ * be marked as being used.
+ */
+ public ParameterUsageMarker(boolean markThisParameter,
+ boolean markAllParameters)
+ {
+ this.markThisParameter = markThisParameter;
+ this.markAllParameters = markAllParameters;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ int parameterSize =
+ ClassUtil.internalMethodParameterSize(programMethod.getDescriptor(programClass),
+ programMethod.getAccessFlags());
+
+ if (parameterSize > 0)
+ {
+ int accessFlags = programMethod.getAccessFlags();
+
+ // Must we mark the 'this' parameter?
+ if (markThisParameter &&
+ (accessFlags & ClassConstants.ACC_STATIC) == 0)
+ {
+ // Mark the 'this' parameter.
+ markParameterUsed(programMethod, 0);
+ }
+
+ // Must we mark all other parameters?
+ if (markAllParameters)
+ {
+ // Mark all parameters, without the 'this' parameter.
+ markUsedParameters(programMethod,
+ (accessFlags & ClassConstants.ACC_STATIC) != 0 ?
+ -1L : -2L);
+ }
+
+ // Is it a native method?
+ if ((accessFlags & ClassConstants.ACC_NATIVE) != 0)
+ {
+ // Mark all parameters.
+ markUsedParameters(programMethod, -1L);
+ }
+
+ // Is it an abstract method?
+ else if ((accessFlags & ClassConstants.ACC_ABSTRACT) != 0)
+ {
+ // Mark the 'this' parameter.
+ markParameterUsed(programMethod, 0);
+ }
+
+ // Is it a non-native, concrete method?
+ else
+ {
+ // Is the method not static, but synchronized, or can it have
+ // other implementations, or is it a class instance initializer?
+ if ((accessFlags & ClassConstants.ACC_STATIC) == 0 &&
+ ((accessFlags & ClassConstants.ACC_SYNCHRONIZED) != 0 ||
+ programClass.mayHaveImplementations(programMethod) ||
+ programMethod.getName(programClass).equals(ClassConstants.METHOD_NAME_INIT)))
+ {
+ // Mark the 'this' parameter.
+ markParameterUsed(programMethod, 0);
+ }
+
+ // Mark the parameters that are used by the code.
+ programMethod.attributesAccept(programClass, this);
+ }
+
+ if (DEBUG)
+ {
+ System.out.print("ParameterUsageMarker: ["+programClass.getName() +"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"]: ");
+ for (int index = 0; index < parameterSize; index++)
+ {
+ System.out.print(isParameterUsed(programMethod, index) ? '+' : '-');
+ }
+ System.out.println();
+ }
+
+ }
+
+ // Set the parameter size.
+ setParameterSize(programMethod, parameterSize);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ // Can the method have other implementations?
+ if (libraryClass.mayHaveImplementations(libraryMethod))
+ {
+ // All implementations must keep all parameters of this method,
+ // including the 'this' parameter.
+ markUsedParameters(libraryMethod, -1L);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Evaluate the code.
+ partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Mark the parameters that are used by the code.
+ codeAttribute.instructionsAccept(clazz, method, this);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ if (partialEvaluator.isTraced(offset) &&
+ variableInstruction.isLoad())
+ {
+ int parameterIndex = variableInstruction.variableIndex;
+ if (parameterIndex < codeAttribute.u2maxLocals)
+ {
+ Value producer =
+ partialEvaluator.getVariablesBefore(offset).getProducerValue(parameterIndex);
+ if (producer != null &&
+ producer.instructionOffsetValue().contains(PartialEvaluator.AT_METHOD_ENTRY))
+ {
+ // Mark the variable.
+ markParameterUsed(method, parameterIndex);
+
+ // Account for Category 2 instructions, which take up two entries.
+ if (variableInstruction.isCategory2())
+ {
+ markParameterUsed(method, parameterIndex + 1);
+ }
+ }
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Sets the total size of the parameters.
+ */
+ private static void setParameterSize(Method method, int parameterSize)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setParameterSize(parameterSize);
+ }
+ }
+
+
+ /**
+ * Returns the total size of the parameters.
+ */
+ public static int getParameterSize(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null ? info.getParameterSize() : 0;
+ }
+
+
+ /**
+ * Marks the given parameter as being used.
+ */
+ public static void markParameterUsed(Method method, int variableIndex)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setParameterUsed(variableIndex);
+ }
+ }
+
+
+ /**
+ * Marks the given parameters as being used.
+ */
+ public static void markUsedParameters(Method method, long usedParameters)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setUsedParameters(info.getUsedParameters() | usedParameters);
+ }
+ }
+
+
+ /**
+ * Returns whether the given parameter is being used.
+ */
+ public static boolean isParameterUsed(Method method, int variableIndex)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null ||
+ info.isParameterUsed(variableIndex);
+ }
+
+
+ /**
+ * Returns which parameters are being used.
+ */
+ public static long getUsedParameters(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null ? info.getUsedParameters() : -1L;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ReadWriteFieldMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ReadWriteFieldMarker.java
new file mode 100644
index 0000000000..472309d3c1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/ReadWriteFieldMarker.java
@@ -0,0 +1,163 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This InstructionVisitor marks all fields that are write-only.
+ *
+ * @author Eric Lafortune
+ */
+public class ReadWriteFieldMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ // Parameters for the visitor methods.
+ private boolean reading = true;
+ private boolean writing = true;
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ byte opcode = constantInstruction.opcode;
+
+ // Check for instructions that involve fields.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_LDC:
+ case InstructionConstants.OP_LDC_W:
+ // Mark the field, if any, as being read from and written to.
+ reading = true;
+ writing = true;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_GETFIELD:
+ // Mark the field as being read from.
+ reading = true;
+ writing = false;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_PUTFIELD:
+ // Mark the field as being written to.
+ reading = false;
+ writing = true;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Mark the referenced field, if any.
+ stringConstant.referencedMemberAccept(this);
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ // Mark the referenced field.
+ fieldrefConstant.referencedMemberAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz Clazz, Member member) {}
+
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Mark the field if it is being read from.
+ if (reading)
+ {
+ markAsRead(programField);
+ }
+
+ // Mark the field if it is being written to.
+ if (writing)
+ {
+ markAsWritten(programField);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void markAsRead(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ if (info != null)
+ {
+ info.setRead();
+ }
+ }
+
+
+ public static boolean isRead(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ return info == null ||
+ info.isRead();
+ }
+
+
+ private static void markAsWritten(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ if (info != null)
+ {
+ info.setWritten();
+ }
+ }
+
+
+ public static boolean isWritten(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ return info == null ||
+ info.isWritten();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectInstructionChecker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectInstructionChecker.java
new file mode 100644
index 0000000000..5374c4e0c4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectInstructionChecker.java
@@ -0,0 +1,375 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+import java.util.*;
+
+/**
+ * This class can tell whether an instruction has any side effects outside of
+ * its method. Return instructions and local field accesses can be included or
+ * not.
+ *
+ * @see ReadWriteFieldMarker
+ * @see StaticInitializerContainingClassMarker
+ * @see NoSideEffectMethodMarker
+ * @see SideEffectMethodMarker
+ * @author Eric Lafortune
+ */
+public class SideEffectInstructionChecker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ static final boolean OPTIMIZE_CONSERVATIVELY = System.getProperty("optimize.conservatively") != null;
+
+
+ private final boolean includeReturnInstructions;
+ private final boolean includeLocalFieldAccess;
+
+ // A return value for the visitor methods.
+ private boolean writingField;
+ private Clazz referencingClass;
+ private boolean hasSideEffects;
+
+
+ /**
+ * Creates a new SideEffectInstructionChecker
+ * @param includeReturnInstructions specifies whether return instructions
+ * count as side effects.
+ * @param includeLocalFieldAccess specifies whether reading or writing
+ * local fields counts as side effects.
+ */
+ public SideEffectInstructionChecker(boolean includeReturnInstructions,
+ boolean includeLocalFieldAccess)
+ {
+ this.includeReturnInstructions = includeReturnInstructions;
+ this.includeLocalFieldAccess = includeLocalFieldAccess;
+ }
+
+
+ /**
+ * Returns whether the given instruction has side effects outside of its
+ * method.
+ */
+ public boolean hasSideEffects(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int offset,
+ Instruction instruction)
+ {
+ hasSideEffects = false;
+
+ instruction.accept(clazz, method, codeAttribute, offset, this);
+
+ return hasSideEffects;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ byte opcode = simpleInstruction.opcode;
+
+ // Check for instructions that might cause side effects.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_IDIV:
+ case InstructionConstants.OP_LDIV:
+ case InstructionConstants.OP_IREM:
+ case InstructionConstants.OP_LREM:
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_LALOAD:
+ case InstructionConstants.OP_FALOAD:
+ case InstructionConstants.OP_DALOAD:
+ case InstructionConstants.OP_AALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+ case InstructionConstants.OP_NEWARRAY:
+ case InstructionConstants.OP_ARRAYLENGTH:
+ case InstructionConstants.OP_ANEWARRAY:
+ case InstructionConstants.OP_MULTIANEWARRAY:
+ // These instructions strictly taken may cause a side effect
+ // (ArithmeticException, NullPointerException,
+ // ArrayIndexOutOfBoundsException, NegativeArraySizeException).
+ hasSideEffects = OPTIMIZE_CONSERVATIVELY;
+ break;
+
+ case InstructionConstants.OP_IASTORE:
+ case InstructionConstants.OP_LASTORE:
+ case InstructionConstants.OP_FASTORE:
+ case InstructionConstants.OP_DASTORE:
+ case InstructionConstants.OP_AASTORE:
+ case InstructionConstants.OP_BASTORE:
+ case InstructionConstants.OP_CASTORE:
+ case InstructionConstants.OP_SASTORE:
+ case InstructionConstants.OP_ATHROW :
+ case InstructionConstants.OP_MONITORENTER:
+ case InstructionConstants.OP_MONITOREXIT:
+ // These instructions always cause a side effect.
+ hasSideEffects = true;
+ break;
+
+ case InstructionConstants.OP_IRETURN:
+ case InstructionConstants.OP_LRETURN:
+ case InstructionConstants.OP_FRETURN:
+ case InstructionConstants.OP_DRETURN:
+ case InstructionConstants.OP_ARETURN:
+ case InstructionConstants.OP_RETURN:
+ // These instructions may have a side effect.
+ hasSideEffects = includeReturnInstructions;
+ break;
+ }
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ byte opcode = variableInstruction.opcode;
+
+ // Check for instructions that might cause side effects.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_RET:
+ // This instruction may have a side effect.
+ hasSideEffects = includeReturnInstructions;
+ break;
+ }
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ byte opcode = constantInstruction.opcode;
+
+ // Check for instructions that might cause side effects.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_GETSTATIC:
+ // Check if accessing the field might cause any side effects.
+ writingField = false;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+
+ case InstructionConstants.OP_PUTSTATIC:
+ // Check if accessing the field might cause any side effects.
+ writingField = true;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+
+ case InstructionConstants.OP_GETFIELD:
+ if (OPTIMIZE_CONSERVATIVELY)
+ {
+ // These instructions strictly taken may cause a side effect
+ // (NullPointerException).
+ hasSideEffects = true;
+ }
+ else
+ {
+ // Check if the field is write-only or volatile.
+ writingField = false;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ break;
+
+ case InstructionConstants.OP_PUTFIELD:
+ if (OPTIMIZE_CONSERVATIVELY)
+ {
+ // These instructions strictly taken may cause a side effect
+ // (NullPointerException).
+ hasSideEffects = true;
+ }
+ else
+ {
+ // Check if the field is write-only or volatile.
+ writingField = true;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ break;
+
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ // Check if the invoked method is causing any side effects.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ if (OPTIMIZE_CONSERVATIVELY)
+ {
+ // These instructions strictly taken may cause a side effect
+ // (NullPointerException).
+ hasSideEffects = true;
+ }
+ else
+ {
+ // Check if the invoked method is causing any side effects.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ break;
+
+ case InstructionConstants.OP_ANEWARRAY:
+ case InstructionConstants.OP_CHECKCAST:
+ case InstructionConstants.OP_MULTIANEWARRAY:
+ // This instructions strictly taken may cause a side effect
+ // (ClassCastException, NegativeArraySizeException).
+ hasSideEffects = OPTIMIZE_CONSERVATIVELY;
+ break;
+ }
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ byte opcode = branchInstruction.opcode;
+
+ // Check for instructions that might cause side effects.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_JSR:
+ case InstructionConstants.OP_JSR_W:
+ hasSideEffects = includeReturnInstructions;
+ break;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // We'll have to assume invoking an unknown method has side effects.
+ hasSideEffects = true;
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ // Pass the referencing class.
+ referencingClass = clazz;
+
+ // We'll have to assume accessing an unknown field has side effects.
+ hasSideEffects = true;
+
+ // Check the referenced field, if known.
+ fieldrefConstant.referencedMemberAccept(this);
+ }
+
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Pass the referencing class.
+ referencingClass = clazz;
+
+ // We'll have to assume invoking an unknown method has side effects.
+ hasSideEffects = true;
+
+ // Check the referenced method, if known.
+ refConstant.referencedMemberAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ hasSideEffects =
+ (includeLocalFieldAccess || !programClass.equals(referencingClass)) &&
+ ((writingField && ReadWriteFieldMarker.isRead(programField)) ||
+ (programField.getAccessFlags() & ClassConstants.ACC_VOLATILE) != 0 ||
+ mayHaveSideEffects(referencingClass, programClass));
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Note that side effects already include synchronization of some
+ // implementation of the method.
+ hasSideEffects =
+ !NoSideEffectMethodMarker.hasNoSideEffects(programMethod) &&
+ (SideEffectMethodMarker.hasSideEffects(programMethod) ||
+ mayHaveSideEffects(referencingClass, programClass));
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ hasSideEffects = true;
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ hasSideEffects =
+ !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether a field reference or method invocation from the
+ * referencing class to the referenced class might have any side
+ * effects.
+ */
+ private boolean mayHaveSideEffects(Clazz referencingClass, Clazz referencedClass)
+ {
+ return
+ !referencedClass.equals(referencingClass) &&
+ !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(referencedClass));
+ }
+
+
+ /**
+ * Returns the set of superclasses and interfaces that are initialized.
+ */
+ private Set initializedSuperClasses(Clazz clazz)
+ {
+ Set set = new HashSet();
+
+ // Visit all superclasses and interfaces, collecting the ones that have
+ // static initializers.
+ clazz.hierarchyAccept(true, true, true, false,
+ new StaticInitializerContainingClassFilter(
+ new NamedMethodVisitor(ClassConstants.METHOD_NAME_CLINIT,
+ ClassConstants.METHOD_TYPE_CLINIT,
+ new SideEffectMethodFilter(
+ new MemberToClassVisitor(
+ new ClassCollector(set))))));
+
+ return set;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectMethodFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectMethodFilter.java
new file mode 100644
index 0000000000..2e38245378
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectMethodFilter.java
@@ -0,0 +1,73 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor delegates all its method calls to another MemberVisitor,
+ * but only for Method objects that are marked as having side effects.
+ *
+ * @see SideEffectMethodMarker
+ *
+ * @author Eric Lafortune
+ */
+public class SideEffectMethodFilter
+implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new SideEffectMethodFilter.
+ * @param memberVisitor the member visitor to which the visiting will be
+ * delegated.
+ */
+ public SideEffectMethodFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField) {}
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (SideEffectMethodMarker.hasSideEffects(programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (SideEffectMethodMarker.hasSideEffects(libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectMethodMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectMethodMarker.java
new file mode 100644
index 0000000000..091f9e22c0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SideEffectMethodMarker.java
@@ -0,0 +1,181 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassPoolVisitor marks all methods that have side effects.
+ *
+ * @see ReadWriteFieldMarker
+ * @see NoSideEffectMethodMarker
+ * @author Eric Lafortune
+ */
+public class SideEffectMethodMarker
+extends SimplifiedVisitor
+implements ClassPoolVisitor,
+ ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor
+{
+ // Reusable objects for checking whether instructions have side effects.
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(false, true);
+ private final SideEffectInstructionChecker initializerSideEffectInstructionChecker = new SideEffectInstructionChecker(false, false);
+
+ // Parameters and values for visitor methods.
+ private int newSideEffectCount;
+ private boolean hasSideEffects;
+
+
+ // Implementations for ClassPoolVisitor.
+
+ public void visitClassPool(ClassPool classPool)
+ {
+ // Go over all classes and their methods, marking if they have side
+ // effects, until no new cases can be found.
+ do
+ {
+ newSideEffectCount = 0;
+
+ // Go over all classes and their methods once.
+ classPool.classesAccept(this);
+ }
+ while (newSideEffectCount > 0);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Go over all methods.
+ programClass.methodsAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (!hasSideEffects(programMethod) &&
+ !NoSideEffectMethodMarker.hasNoSideEffects(programMethod))
+ {
+ // Initialize the return value.
+ hasSideEffects =
+ (programMethod.getAccessFlags() &
+ (ClassConstants.ACC_NATIVE |
+ ClassConstants.ACC_SYNCHRONIZED)) != 0;
+
+ // Look further if the method hasn't been marked yet.
+ if (!hasSideEffects)
+ {
+ // Investigate the actual code.
+ programMethod.attributesAccept(programClass, this);
+ }
+
+ // Mark the method depending on the return value.
+ if (hasSideEffects)
+ {
+ markSideEffects(programMethod);
+
+ newSideEffectCount++;
+ }
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Remember whether the code has any side effects.
+ hasSideEffects = hasSideEffects(clazz, method, codeAttribute);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the given code has any side effects.
+ */
+ private boolean hasSideEffects(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute)
+ {
+ byte[] code = codeAttribute.code;
+ int length = codeAttribute.u4codeLength;
+
+ SideEffectInstructionChecker checker =
+ method.getName(clazz).equals(ClassConstants.METHOD_NAME_CLINIT) ?
+ initializerSideEffectInstructionChecker :
+ sideEffectInstructionChecker;
+
+ // Go over all instructions.
+ int offset = 0;
+ do
+ {
+ // Get the current instruction.
+ Instruction instruction = InstructionFactory.create(code, offset);
+
+ // Check if it may be throwing exceptions.
+ if (checker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ instruction))
+ {
+ return true;
+ }
+
+ // Go to the next instruction.
+ offset += instruction.length(offset);
+ }
+ while (offset < length);
+
+ return false;
+ }
+
+
+ private static void markSideEffects(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setSideEffects();
+ }
+ }
+
+
+ public static boolean hasSideEffects(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null ||
+ info.hasSideEffects();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SimpleEnumFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SimpleEnumFilter.java
new file mode 100644
index 0000000000..9d05a9f2e7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SimpleEnumFilter.java
@@ -0,0 +1,96 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates its visits to one of two other given
+ * ClassVisitor instances, depending on whether the classes are marked
+ * as simple enums or not.
+ *
+ * @see SimpleEnumMarker
+ *
+ * @author Eric Lafortune
+ */
+public class SimpleEnumFilter
+implements ClassVisitor
+{
+ private final ClassVisitor simpleEnumClassVisitor;
+ private final ClassVisitor otherClassVisitor;
+
+
+ /**
+ * Creates a new SimpleEnumClassFilter.
+ *
+ * @param simpleEnumClassVisitor the class visitor to which visits to
+ * classes that are marked to be simpleEnum
+ * will be delegated.
+ */
+ public SimpleEnumFilter(ClassVisitor simpleEnumClassVisitor)
+ {
+ this(simpleEnumClassVisitor, null);
+ }
+
+
+ /**
+ * Creates a new SimpleEnumClassFilter.
+ *
+ * @param simpleEnumClassVisitor the class visitor to which visits to
+ * classes that are marked as simple enums
+ * will be delegated.
+ * @param otherClassVisitor the class visitor to which visits to
+ * classes that are not marked as simple
+ * enums will be delegated.
+ */
+ public SimpleEnumFilter(ClassVisitor simpleEnumClassVisitor,
+ ClassVisitor otherClassVisitor)
+ {
+ this.simpleEnumClassVisitor = simpleEnumClassVisitor;
+ this.otherClassVisitor = otherClassVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Is the class marked as a simple enum?
+ ClassVisitor classVisitor = SimpleEnumMarker.isSimpleEnum(programClass) ?
+ simpleEnumClassVisitor : otherClassVisitor;
+
+ if (classVisitor != null)
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // A library class can't be marked as a simple enum.
+ if (otherClassVisitor != null)
+ {
+ otherClassVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SimpleEnumMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SimpleEnumMarker.java
new file mode 100644
index 0000000000..6877f37aeb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SimpleEnumMarker.java
@@ -0,0 +1,75 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor marks all program classes that it visits with a given
+ * flag for simple enums.
+ *
+ * @author Eric Lafortune
+ */
+public class SimpleEnumMarker
+implements ClassVisitor
+{
+ private final boolean simple;
+
+
+ /**
+ * Creates a new SimpleEnumMarker that marks visited classes with the
+ * given flag.
+ */
+ public SimpleEnumMarker(boolean simple)
+ {
+ this.simple = simple;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ setSimpleEnum(programClass);
+ }
+
+
+ // Small utility methods.
+
+ private void setSimpleEnum(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setSimpleEnum(simple);
+ }
+ }
+
+
+ public static boolean isSimpleEnum(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info != null && info.isSimpleEnum();
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java
new file mode 100644
index 0000000000..0000b7d765
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are instantiated.
+ *
+ * @author Eric Lafortune
+ */
+public class StaticInitializerContainingClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public StaticInitializerContainingClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (StaticInitializerContainingClassMarker.containsStaticInitializer(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (StaticInitializerContainingClassMarker.containsStaticInitializer(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java
new file mode 100644
index 0000000000..49fb5432d1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor marks all classes that contain static initializers.
+ *
+ * @author Eric Lafortune
+ */
+public class StaticInitializerContainingClassMarker
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ if (clazz.findMethod(ClassConstants.METHOD_NAME_CLINIT,
+ ClassConstants.METHOD_TYPE_CLINIT) != null)
+ {
+ setStaticInitializer(clazz);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void setStaticInitializer(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setContainsStaticInitializer();
+ }
+ }
+
+
+ public static boolean containsStaticInitializer(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.containsStaticInitializer();
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SuperInvocationMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SuperInvocationMarker.java
new file mode 100644
index 0000000000..63e6225504
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/SuperInvocationMarker.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.RefConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor marks all methods that invoke super methods (other
+ * than initializers) from the instructions that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class SuperInvocationMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor
+{
+ private boolean invokesSuperMethods;
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ if (constantInstruction.opcode == InstructionConstants.OP_INVOKESPECIAL)
+ {
+ invokesSuperMethods = false;
+
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+
+ if (invokesSuperMethods)
+ {
+ setInvokesSuperMethods(method);
+ }
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ invokesSuperMethods =
+ !clazz.equals(refConstant.referencedClass) &&
+ !refConstant.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT);
+ }
+
+
+ // Small utility methods.
+
+ private static void setInvokesSuperMethods(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setInvokesSuperMethods();
+ }
+ }
+
+
+ public static boolean invokesSuperMethods(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.invokesSuperMethods();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/VariableUsageMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/VariableUsageMarker.java
new file mode 100644
index 0000000000..ba31ac4875
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/VariableUsageMarker.java
@@ -0,0 +1,96 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.info;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor marks the local variables that are used in the code
+ * attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableUsageMarker
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor
+{
+ private boolean[] variableUsed = new boolean[ClassConstants.TYPICAL_VARIABLES_SIZE];
+
+
+ /**
+ * Returns whether the given variable has been marked as being used.
+ */
+ public boolean isVariableUsed(int variableIndex)
+ {
+ return variableUsed[variableIndex];
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ int maxLocals = codeAttribute.u2maxLocals;
+
+ // Try to reuse the previous array.
+ if (variableUsed.length < maxLocals)
+ {
+ // Create a new array.
+ variableUsed = new boolean[maxLocals];
+ }
+ else
+ {
+ // Reset the array.
+ Arrays.fill(variableUsed, 0, maxLocals, false);
+ }
+
+ codeAttribute.instructionsAccept(clazz, method, this);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ // Mark the variable.
+ variableUsed[variableInstruction.variableIndex] = true;
+
+ // Account for Category 2 instructions, which take up two entries.
+ if (variableInstruction.isCategory2())
+ {
+ variableUsed[variableInstruction.variableIndex + 1] = true;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/package.html
new file mode 100644
index 0000000000..d16486e863
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/info/package.html
@@ -0,0 +1,4 @@
+<body>
+This package contains classes to collect additional information about classes
+and class members, which can then be used for optimization.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/package.html
new file mode 100644
index 0000000000..3ee1353222
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/package.html
@@ -0,0 +1,4 @@
+<body>
+This package contains visitors that assist with various optimizations of byte
+code.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ClassFinalizer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ClassFinalizer.java
new file mode 100644
index 0000000000..b0fe5a1dba
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ClassFinalizer.java
@@ -0,0 +1,84 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+import proguard.optimize.KeepMarker;
+
+/**
+ * This <code>ClassVisitor</code> makes the program classes that it visits
+ * final, if possible.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassFinalizer
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final ClassVisitor extraClassVisitor;
+
+
+ /**
+ * Creates a new ClassFinalizer.
+ */
+ public ClassFinalizer()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new ClassFinalizer.
+ * @param extraClassVisitor an optional extra visitor for all finalized
+ * classes.
+ */
+ public ClassFinalizer(ClassVisitor extraClassVisitor)
+ {
+ this.extraClassVisitor = extraClassVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // If the class is not final/interface/abstract,
+ // and it is not being kept,
+ // and it doesn't have any subclasses,
+ // then make it final.
+ if ((programClass.u2accessFlags & (ClassConstants.ACC_FINAL |
+ ClassConstants.ACC_INTERFACE |
+ ClassConstants.ACC_ABSTRACT)) == 0 &&
+ !KeepMarker.isKept(programClass) &&
+ programClass.subClasses == null)
+ {
+ programClass.u2accessFlags |= ClassConstants.ACC_FINAL;
+
+ // Visit the class, if required.
+ if (extraClassVisitor != null)
+ {
+ extraClassVisitor.visitProgramClass(programClass);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ClassMerger.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ClassMerger.java
new file mode 100644
index 0000000000..11ac0ca6a4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ClassMerger.java
@@ -0,0 +1,742 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AttributeNameFilter;
+import proguard.classfile.constant.visitor.*;
+import proguard.classfile.editor.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.optimize.KeepMarker;
+import proguard.optimize.info.*;
+import proguard.util.*;
+
+import java.util.*;
+
+/**
+ * This ClassVisitor inlines the classes that it visits in a given target class,
+ * whenever possible.
+ *
+ * @see RetargetedInnerClassAttributeRemover
+ * @see TargetClassChanger
+ * @see ClassReferenceFixer
+ * @see MemberReferenceFixer
+ * @see AccessFixer
+ * @author Eric Lafortune
+ */
+public class ClassMerger
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ private static final boolean DETAILS = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("cm") != null;
+ private static boolean DETAILS = System.getProperty("cmd") != null;
+ //*/
+
+
+ private final ProgramClass targetClass;
+ private final boolean allowAccessModification;
+ private final boolean mergeInterfacesAggressively;
+ private final ClassVisitor extraClassVisitor;
+
+ private final MemberVisitor fieldOptimizationInfoCopier = new FieldOptimizationInfoCopier();
+
+
+ /**
+ * Creates a new ClassMerger that will merge classes into the given target
+ * class.
+ * @param targetClass the class into which all visited
+ * classes will be merged.
+ * @param allowAccessModification specifies whether the access modifiers
+ * of classes can be changed in order to
+ * merge them.
+ * @param mergeInterfacesAggressively specifies whether interfaces may
+ * be merged aggressively.
+ */
+ public ClassMerger(ProgramClass targetClass,
+ boolean allowAccessModification,
+ boolean mergeInterfacesAggressively)
+ {
+ this(targetClass, allowAccessModification, mergeInterfacesAggressively, null);
+ }
+
+
+ /**
+ * Creates a new ClassMerger that will merge classes into the given target
+ * class.
+ * @param targetClass the class into which all visited
+ * classes will be merged.
+ * @param allowAccessModification specifies whether the access modifiers
+ * of classes can be changed in order to
+ * merge them.
+ * @param mergeInterfacesAggressively specifies whether interfaces may
+ * be merged aggressively.
+ * @param extraClassVisitor an optional extra visitor for all
+ * merged classes.
+ */
+ public ClassMerger(ProgramClass targetClass,
+ boolean allowAccessModification,
+ boolean mergeInterfacesAggressively,
+ ClassVisitor extraClassVisitor)
+ {
+ this.targetClass = targetClass;
+ this.allowAccessModification = allowAccessModification;
+ this.mergeInterfacesAggressively = mergeInterfacesAggressively;
+ this.extraClassVisitor = extraClassVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ //final String CLASS_NAME = "abc/Def";
+ //DEBUG = programClass.getName().equals(CLASS_NAME) ||
+ // targetClass.getName().equals(CLASS_NAME);
+
+ // TODO: Remove this when the class merger has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ visitProgramClass0(programClass);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while merging classes:");
+ System.err.println(" Class = ["+programClass.getName()+"]");
+ System.err.println(" Target class = ["+targetClass.getName()+"]");
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+
+ if (DEBUG)
+ {
+ programClass.accept(new ClassPrinter());
+ targetClass.accept(new ClassPrinter());
+ }
+
+ throw ex;
+ }
+ }
+
+ public void visitProgramClass0(ProgramClass programClass)
+ {
+ if (!programClass.equals(targetClass) &&
+
+ // Don't merge classes that must be preserved.
+ !KeepMarker.isKept(programClass) &&
+ !KeepMarker.isKept(targetClass) &&
+
+ // Only merge classes that haven't been retargeted yet.
+ getTargetClass(programClass) == null &&
+ getTargetClass(targetClass) == null &&
+
+ // Don't merge annotation classes, with all their introspection and
+ // infinite recursion.
+ (programClass.getAccessFlags() & ClassConstants.ACC_ANNOTATTION) == 0 &&
+
+ (!DETAILS || print(programClass, "Package visibility?")) &&
+
+ // Only merge classes if we can change the access permissions, or
+ // if they are in the same package, or
+ // if they are public and don't contain or invoke package visible
+ // class members.
+ (allowAccessModification ||
+ ((programClass.getAccessFlags() &
+ targetClass.getAccessFlags() &
+ ClassConstants.ACC_PUBLIC) != 0 &&
+ !PackageVisibleMemberContainingClassMarker.containsPackageVisibleMembers(programClass) &&
+ !PackageVisibleMemberInvokingClassMarker.invokesPackageVisibleMembers(programClass)) ||
+ ClassUtil.internalPackageName(programClass.getName()).equals(
+ ClassUtil.internalPackageName(targetClass.getName()))) &&
+
+ (!DETAILS || print(programClass, "Interface/abstract/single?")) &&
+
+ // Only merge two classes or two interfaces or two abstract classes,
+ // or a single implementation into its interface.
+ ((programClass.getAccessFlags() &
+ (ClassConstants.ACC_INTERFACE |
+ ClassConstants.ACC_ABSTRACT)) ==
+ (targetClass.getAccessFlags() &
+ (ClassConstants.ACC_INTERFACE |
+ ClassConstants.ACC_ABSTRACT)) ||
+ (isOnlySubClass(programClass, targetClass) &&
+ programClass.getSuperClass() != null &&
+ (programClass.getSuperClass().equals(targetClass) ||
+ programClass.getSuperClass().equals(targetClass.getSuperClass())))) &&
+
+ (!DETAILS || print(programClass, "Indirect implementation?")) &&
+
+ // One class must not implement the other class indirectly.
+ !indirectlyImplementedInterfaces(programClass).contains(targetClass) &&
+ !targetClass.extendsOrImplements(programClass) &&
+
+ (!DETAILS || print(programClass, "Interfaces same subinterfaces?")) &&
+
+ // Interfaces must have exactly the same subinterfaces, not
+ // counting themselves, to avoid any loops in the interface
+ // hierarchy.
+ ((programClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) == 0 ||
+ (targetClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) == 0 ||
+ subInterfaces(programClass, targetClass).equals(subInterfaces(targetClass, programClass))) &&
+
+ (!DETAILS || print(programClass, "Same initialized superclasses?")) &&
+
+ // The two classes must have the same superclasses and interfaces
+ // with static initializers.
+ initializedSuperClasses(programClass).equals(initializedSuperClasses(targetClass)) &&
+
+ (!DETAILS || print(programClass, "Same instanceofed superclasses?")) &&
+
+ // The two classes must have the same superclasses and interfaces
+ // that are tested with 'instanceof'.
+ instanceofedSuperClasses(programClass).equals(instanceofedSuperClasses(targetClass)) &&
+
+ (!DETAILS || print(programClass, "Same caught superclasses?")) &&
+
+ // The two classes must have the same superclasses that are caught
+ // as exceptions.
+ caughtSuperClasses(programClass).equals(caughtSuperClasses(targetClass)) &&
+
+ (!DETAILS || print(programClass, "Not .classed?")) &&
+
+ // The two classes must not both be part of a .class construct.
+ !(DotClassMarker.isDotClassed(programClass) &&
+ DotClassMarker.isDotClassed(targetClass)) &&
+
+ (!DETAILS || print(programClass, "No clashing fields?")) &&
+
+ // The classes must not have clashing fields.
+ !haveAnyIdenticalFields(programClass, targetClass) &&
+
+ (!DETAILS || print(programClass, "No unwanted fields?")) &&
+
+ // The two classes must not introduce any unwanted fields.
+ !introducesUnwantedFields(programClass, targetClass) &&
+ !introducesUnwantedFields(targetClass, programClass) &&
+
+ (!DETAILS || print(programClass, "No shadowed fields?")) &&
+
+ // The two classes must not shadow each others fields.
+ !shadowsAnyFields(programClass, targetClass) &&
+ !shadowsAnyFields(targetClass, programClass) &&
+
+ (!DETAILS || print(programClass, "No clashing methods?")) &&
+
+ // The classes must not have clashing methods.
+ !haveAnyIdenticalMethods(programClass, targetClass) &&
+
+ (!DETAILS || print(programClass, "No abstract methods?")) &&
+
+ // The classes must not introduce abstract methods, unless
+ // explicitly allowed.
+ (mergeInterfacesAggressively ||
+ (!introducesUnwantedAbstractMethods(programClass, targetClass) &&
+ !introducesUnwantedAbstractMethods(targetClass, programClass))) &&
+
+ (!DETAILS || print(programClass, "No overridden methods?")) &&
+
+ // The classes must not override each others concrete methods.
+ !overridesAnyMethods(programClass, targetClass) &&
+ !overridesAnyMethods(targetClass, programClass) &&
+
+ (!DETAILS || print(programClass, "No shadowed methods?")) &&
+
+ // The classes must not shadow each others non-private methods.
+ !shadowsAnyMethods(programClass, targetClass) &&
+ !shadowsAnyMethods(targetClass, programClass))
+ {
+ // We're not actually merging the classes, but only copying the
+ // contents from the source class to the target class. We'll
+ // then let all other classes point to it. The shrinking step
+ // will finally remove the source class.
+ if (DEBUG)
+ {
+ System.out.println("ClassMerger ["+programClass.getName()+"] -> ["+targetClass.getName()+"]");
+ System.out.println(" Source interface? ["+((programClass.getAccessFlags() & ClassConstants.ACC_INTERFACE)!=0)+"]");
+ System.out.println(" Target interface? ["+((targetClass.getAccessFlags() & ClassConstants.ACC_INTERFACE)!=0)+"]");
+ System.out.println(" Source subclasses ["+programClass.subClasses+"]");
+ System.out.println(" Target subclasses ["+targetClass.subClasses+"]");
+ System.out.println(" Source superclass ["+programClass.getSuperClass().getName()+"]");
+ System.out.println(" Target superclass ["+targetClass.getSuperClass().getName()+"]");
+
+ //System.out.println("=== Before ===");
+ //programClass.accept(new ClassPrinter());
+ //targetClass.accept(new ClassPrinter());
+ }
+
+ // Combine the access flags.
+ int targetAccessFlags = targetClass.getAccessFlags();
+ int sourceAccessFlags = programClass.getAccessFlags();
+
+ targetClass.u2accessFlags =
+ ((targetAccessFlags &
+ sourceAccessFlags) &
+ (ClassConstants.ACC_INTERFACE |
+ ClassConstants.ACC_ABSTRACT)) |
+ ((targetAccessFlags |
+ sourceAccessFlags) &
+ (ClassConstants.ACC_PUBLIC |
+ ClassConstants.ACC_SUPER |
+ ClassConstants.ACC_ANNOTATTION |
+ ClassConstants.ACC_ENUM));
+
+ // Copy over the superclass, if it's a non-interface class being
+ // merged into an interface class.
+ // However, we're currently never merging in a way that changes the
+ // superclass.
+ //if ((programClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) == 0 &&
+ // (targetClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) != 0)
+ //{
+ // targetClass.u2superClass =
+ // new ConstantAdder(targetClass).addConstant(programClass, programClass.u2superClass);
+ //}
+
+ // Copy over the interfaces that aren't present yet and that
+ // wouldn't cause loops in the class hierarchy.
+ // Note that the code shouldn't be iterating over the original
+ // list at this point. This is why we only add subclasses in
+ // a separate step.
+ programClass.interfaceConstantsAccept(
+ new ExceptClassConstantFilter(targetClass.getName(),
+ new ImplementedClassConstantFilter(targetClass,
+ new ImplementingClassConstantFilter(targetClass,
+ new InterfaceAdder(targetClass)))));
+
+ // Copy over the class members.
+ MemberAdder memberAdder =
+ new MemberAdder(targetClass, fieldOptimizationInfoCopier);
+
+ programClass.fieldsAccept(memberAdder);
+ programClass.methodsAccept(memberAdder);
+
+ // Copy over the other attributes.
+ programClass.attributesAccept(
+ new AttributeNameFilter(new NotMatcher(
+ new OrMatcher(new FixedStringMatcher(ClassConstants.ATTR_BootstrapMethods),
+ new OrMatcher(new FixedStringMatcher(ClassConstants.ATTR_SourceFile),
+ new OrMatcher(new FixedStringMatcher(ClassConstants.ATTR_InnerClasses),
+ new FixedStringMatcher(ClassConstants.ATTR_EnclosingMethod))))),
+ new AttributeAdder(targetClass, true)));
+
+ // Update the optimization information of the target class.
+ ClassOptimizationInfo info =
+ ClassOptimizationInfo.getClassOptimizationInfo(targetClass);
+ if (info != null)
+ {
+ info.merge(ClassOptimizationInfo.getClassOptimizationInfo(programClass));
+ }
+
+ // Remember to replace the inlined class by the target class.
+ setTargetClass(programClass, targetClass);
+
+ //if (DEBUG)
+ //{
+ // System.out.println("=== After ====");
+ // targetClass.accept(new ClassPrinter());
+ //}
+
+ // Visit the merged class, if required.
+ if (extraClassVisitor != null)
+ {
+ extraClassVisitor.visitProgramClass(programClass);
+ }
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Ignore attempts to merge with a library class.
+ }
+
+
+ private boolean print(ProgramClass programClass, String message)
+ {
+ System.out.println("Merge ["+targetClass.getName()+"] <- ["+programClass.getName()+"] "+message);
+
+ return true;
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether a given class is the only subclass of another given class.
+ */
+ private boolean isOnlySubClass(Clazz subClass,
+ ProgramClass clazz)
+ {
+ // TODO: The list of subclasses is not up to date.
+ return clazz.subClasses != null &&
+ clazz.subClasses.length == 1 &&
+ clazz.subClasses[0].equals(subClass);
+ }
+
+
+ /**
+ * Returns the set of indirectly implemented interfaces.
+ */
+ private Set indirectlyImplementedInterfaces(Clazz clazz)
+ {
+ Set set = new HashSet();
+
+ ReferencedClassVisitor referencedInterfaceCollector =
+ new ReferencedClassVisitor(
+ new ClassHierarchyTraveler(false, false, true, false,
+ new ClassCollector(set)));
+
+ // Visit all superclasses and collect their interfaces.
+ clazz.superClassConstantAccept(referencedInterfaceCollector);
+
+ // Visit all interfaces and collect their interfaces.
+ clazz.interfaceConstantsAccept(referencedInterfaceCollector);
+
+ return set;
+ }
+
+
+ /**
+ * Returns the set of interface subclasses, not including the given class.
+ */
+ private Set subInterfaces(Clazz clazz, Clazz exceptClass)
+ {
+ Set set = new HashSet();
+
+ // Visit all subclasses, collecting the interface classes.
+ clazz.hierarchyAccept(false, false, false, true,
+ new ClassAccessFilter(ClassConstants.ACC_INTERFACE, 0,
+ new ExceptClassesFilter(new Clazz[] { exceptClass },
+ new ClassCollector(set))));
+
+ return set;
+ }
+
+
+ /**
+ * Returns the set of superclasses and interfaces that are initialized.
+ */
+ private Set initializedSuperClasses(Clazz clazz)
+ {
+ Set set = new HashSet();
+
+ // Visit all superclasses and interfaces, collecting the ones that have
+ // static initializers.
+ clazz.hierarchyAccept(true, true, true, false,
+ new StaticInitializerContainingClassFilter(
+ new ClassCollector(set)));
+
+ return set;
+ }
+
+
+ /**
+ * Returns the set of superclasses and interfaces that are used in
+ * 'instanceof' tests.
+ */
+ private Set instanceofedSuperClasses(Clazz clazz)
+ {
+ Set set = new HashSet();
+
+ // Visit all superclasses and interfaces, collecting the ones that are
+ // used in an 'instanceof' test.
+ clazz.hierarchyAccept(true, true, true, false,
+ new InstanceofClassFilter(
+ new ClassCollector(set)));
+
+ return set;
+ }
+
+
+ /**
+ * Returns the set of superclasses that are caught as exceptions.
+ */
+ private Set caughtSuperClasses(Clazz clazz)
+ {
+ // Don't bother if this isn't an exception at all.
+ if (!clazz.extends_(ClassConstants.NAME_JAVA_LANG_THROWABLE))
+ {
+ return Collections.EMPTY_SET;
+ }
+
+ // Visit all superclasses, collecting the ones that are caught
+ // (plus java.lang.Object, in the current implementation).
+ Set set = new HashSet();
+
+ clazz.hierarchyAccept(true, true, false, false,
+ new CaughtClassFilter(
+ new ClassCollector(set)));
+
+ return set;
+ }
+
+
+ /**
+ * Returns whether the two given classes have fields with the same
+ * names and descriptors.
+ */
+ private boolean haveAnyIdenticalFields(Clazz clazz, Clazz targetClass)
+ {
+ MemberCounter counter = new MemberCounter();
+
+ // Visit all fields, counting the with the same name and descriptor in
+ // the target class.
+ clazz.fieldsAccept(new SimilarMemberVisitor(targetClass, true, false, false, false,
+ counter));
+
+ return counter.getCount() > 0;
+ }
+
+
+ /**
+ * Returns whether the given class would introduce any unwanted fields
+ * in the target class.
+ */
+ private boolean introducesUnwantedFields(ProgramClass programClass,
+ ProgramClass targetClass)
+ {
+ // It's ok if the target class is never instantiated, without any other
+ // subclasses except for maybe the source class.
+ if (!InstantiationClassMarker.isInstantiated(targetClass) &&
+ (targetClass.subClasses == null ||
+ isOnlySubClass(programClass, targetClass)))
+ {
+ return false;
+ }
+
+ MemberCounter counter = new MemberCounter();
+
+ // Count all non-static fields in the the source class.
+ programClass.fieldsAccept(new MemberAccessFilter(0, ClassConstants.ACC_STATIC,
+ counter));
+
+ return counter.getCount() > 0;
+ }
+
+
+ /**
+ * Returns whether the given class or its subclasses shadow any fields in
+ * the given target class.
+ */
+ private boolean shadowsAnyFields(Clazz clazz, Clazz targetClass)
+ {
+ MemberCounter counter = new MemberCounter();
+
+ // Visit all fields, counting the ones that are shadowing non-private
+ // fields in the class hierarchy of the target class.
+ clazz.hierarchyAccept(true, false, false, true,
+ new AllFieldVisitor(
+ new SimilarMemberVisitor(targetClass, true, true, true, false,
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE,
+ counter))));
+
+ return counter.getCount() > 0;
+ }
+
+
+ /**
+ * Returns whether the two given classes have class members with the same
+ * name and descriptor.
+ */
+ private boolean haveAnyIdenticalMethods(Clazz clazz, Clazz targetClass)
+ {
+ MemberCounter counter = new MemberCounter();
+
+ // Visit all non-abstract methods, counting the ones that are also
+ // present in the target class.
+ clazz.methodsAccept(new MemberAccessFilter(0, ClassConstants.ACC_ABSTRACT,
+ new SimilarMemberVisitor(targetClass, true, false, false, false,
+ new MemberAccessFilter(0, ClassConstants.ACC_ABSTRACT,
+ counter))));
+
+ return counter.getCount() > 0;
+ }
+
+
+ /**
+ * Returns whether the given class would introduce any abstract methods
+ * in the target class.
+ */
+ private boolean introducesUnwantedAbstractMethods(Clazz clazz,
+ ProgramClass targetClass)
+ {
+ // It's ok if the target class is already abstract and it has at most
+ // the class as a subclass.
+ if ((targetClass.getAccessFlags() &
+ (ClassConstants.ACC_ABSTRACT |
+ ClassConstants.ACC_INTERFACE)) != 0 &&
+ (targetClass.subClasses == null ||
+ isOnlySubClass(clazz, targetClass)))
+ {
+ return false;
+ }
+
+ MemberCounter counter = new MemberCounter();
+ Set targetSet = new HashSet();
+
+ // Collect all abstract methods, and similar abstract methods in the
+ // class hierarchy of the target class.
+ clazz.methodsAccept(new MemberAccessFilter(ClassConstants.ACC_ABSTRACT, 0,
+ new MultiMemberVisitor(new MemberVisitor[]
+ {
+ counter,
+ new SimilarMemberVisitor(targetClass, true, true, true, false,
+ new MemberAccessFilter(ClassConstants.ACC_ABSTRACT, 0,
+ new MemberCollector(targetSet)))
+ })));
+
+ return targetSet.size() < counter.getCount();
+ }
+
+
+ /**
+ * Returns whether the given class overrides any methods in the given
+ * target class.
+ */
+ private boolean overridesAnyMethods(Clazz clazz, Clazz targetClass)
+ {
+ MemberCounter counter = new MemberCounter();
+
+ // Visit all non-private non-static methods, counting the ones that are
+ // being overridden in the class hierarchy of the target class.
+ clazz.methodsAccept(new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC | ClassConstants.ACC_ABSTRACT,
+ new InitializerMethodFilter(null,
+ new SimilarMemberVisitor(targetClass, true, true, false, false,
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC | ClassConstants.ACC_ABSTRACT,
+ counter)))));
+
+ return counter.getCount() > 0;
+ }
+
+
+ /**
+ * Returns whether the given class or its subclasses shadow any methods in
+ * the given target class.
+ */
+ private boolean shadowsAnyMethods(Clazz clazz, Clazz targetClass)
+ {
+ MemberCounter counter = new MemberCounter();
+
+ // Visit all methods, counting the ones that are shadowing
+ // final methods in the class hierarchy of the target class.
+ clazz.hierarchyAccept(true, false, false, true,
+ new AllMethodVisitor(
+ new InitializerMethodFilter(null,
+ new SimilarMemberVisitor(targetClass, true, true, false, false,
+ new MemberAccessFilter(ClassConstants.ACC_FINAL, 0,
+ counter)))));
+
+ if (counter.getCount() > 0)
+ {
+ return true;
+ }
+
+ // Visit all private methods, counting the ones that are shadowing
+ // non-private methods in the class hierarchy of the target class.
+ clazz.hierarchyAccept(true, false, false, true,
+ new AllMethodVisitor(
+ new MemberAccessFilter(ClassConstants.ACC_PRIVATE, 0,
+ new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.METHOD_NAME_INIT)),
+ new SimilarMemberVisitor(targetClass, true, true, true, false,
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE,
+ counter))))));
+
+ if (counter.getCount() > 0)
+ {
+ return true;
+ }
+
+ // Visit all static methods, counting the ones that are shadowing
+ // non-private methods in the class hierarchy of the target class.
+ clazz.hierarchyAccept(true, false, false, true,
+ new AllMethodVisitor(
+ new MemberAccessFilter(ClassConstants.ACC_STATIC, 0,
+ new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.METHOD_NAME_CLINIT)),
+ new SimilarMemberVisitor(targetClass, true, true, true, false,
+ new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE,
+ counter))))));
+
+ return counter.getCount() > 0;
+ }
+
+
+ public static void setTargetClass(Clazz clazz, Clazz targetClass)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setTargetClass(targetClass);
+ }
+ }
+
+
+ public static Clazz getTargetClass(Clazz clazz)
+ {
+ Clazz targetClass = null;
+
+ // Return the last target class, if any.
+ while (true)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info == null)
+ {
+ return targetClass;
+ }
+
+ clazz = info.getTargetClass();
+ if (clazz == null)
+ {
+ return targetClass;
+ }
+
+ targetClass = clazz;
+ }
+ }
+
+
+ /**
+ * This MemberVisitor copies field optimization info from copied fields.
+ */
+ private static class FieldOptimizationInfoCopier
+ extends SimplifiedVisitor
+ implements MemberVisitor
+ {
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Copy the optimization info from the field that was just copied.
+ ProgramField copiedField = (ProgramField)programField.getVisitorInfo();
+ Object info = copiedField.getVisitorInfo();
+
+ programField.setVisitorInfo(info instanceof FieldOptimizationInfo ?
+ new FieldOptimizationInfo((FieldOptimizationInfo)info) :
+ info);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Linked methods share their optimization info.
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
new file mode 100644
index 0000000000..c1bf6bf234
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
@@ -0,0 +1,264 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.evaluation.BranchTargetFinder;
+
+/**
+ * This AttributeVisitor redirects unconditional branches so any common code
+ * is shared, and the code preceding the branch can be removed, in the code
+ * attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class GotoCommonCodeReplacer
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = true;
+ //*/
+
+
+ private final InstructionVisitor extraInstructionVisitor;
+
+ private final BranchTargetFinder branchTargetFinder = new BranchTargetFinder();
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(true, false);
+
+
+ /**
+ * Creates a new GotoCommonCodeReplacer.
+ * @param extraInstructionVisitor an optional extra visitor for all replaced
+ * goto instructions.
+ */
+ public GotoCommonCodeReplacer(InstructionVisitor extraInstructionVisitor)
+ {
+ this.extraInstructionVisitor = extraInstructionVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ // Mark all branch targets.
+ branchTargetFinder.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Reset the code attribute editor.
+ codeAttributeEditor.reset(codeAttribute.u4codeLength);
+
+ // Remap the variables of the instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
+
+ // Apply the code atribute editor.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ // Check if the instruction is an unconditional goto instruction that
+ // isn't the target of a branch itself.
+ byte opcode = branchInstruction.opcode;
+ if ((opcode == InstructionConstants.OP_GOTO ||
+ opcode == InstructionConstants.OP_GOTO_W) &&
+ !branchTargetFinder.isBranchTarget(offset))
+ {
+ int branchOffset = branchInstruction.branchOffset;
+ int targetOffset = offset + branchOffset;
+
+ // Get the number of common bytes.
+ int commonCount = commonByteCodeCount(codeAttribute, offset, targetOffset);
+
+ if (commonCount > 0 &&
+ !exceptionBoundary(codeAttribute, offset, targetOffset))
+ {
+ if (DEBUG)
+ {
+ System.out.println("GotoCommonCodeReplacer: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+" (["+(offset-commonCount)+"] - "+branchInstruction.toString(offset)+" -> "+targetOffset+")");
+ }
+
+ // Delete the common instructions.
+ for (int delta = 0; delta <= commonCount; delta++)
+ {
+ int deleteOffset = offset - delta;
+ if (branchTargetFinder.isInstruction(deleteOffset))
+ {
+ codeAttributeEditor.clearModifications(deleteOffset);
+ codeAttributeEditor.deleteInstruction(deleteOffset);
+ }
+ }
+
+ // Redirect the goto instruction, if it is still necessary.
+ int newBranchOffset = branchOffset - commonCount;
+ if (newBranchOffset != branchInstruction.length(offset))
+ {
+ Instruction newGotoInstruction =
+ new BranchInstruction(opcode, newBranchOffset).shrink();
+ codeAttributeEditor.replaceInstruction(offset,
+ newGotoInstruction);
+ }
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ extraInstructionVisitor.visitBranchInstruction(clazz, method, codeAttribute, offset, branchInstruction);
+ }
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns the number of common bytes preceding the given offsets,
+ * avoiding branches and exception blocks.
+ */
+ private int commonByteCodeCount(CodeAttribute codeAttribute, int offset1, int offset2)
+ {
+ // Find the block of common instructions preceding it.
+ byte[] code = codeAttribute.code;
+
+ int successfulDelta = 0;
+
+ for (int delta = 1;
+ delta <= offset1 &&
+ delta <= offset2 &&
+ offset2 - delta != offset1;
+ delta++)
+ {
+ int newOffset1 = offset1 - delta;
+ int newOffset2 = offset2 - delta;
+
+ // Is the code identical at both offsets?
+ if (code[newOffset1] != code[newOffset2])
+ {
+ break;
+ }
+
+ // Are there instructions at either offset but not both?
+ if (branchTargetFinder.isInstruction(newOffset1) ^
+ branchTargetFinder.isInstruction(newOffset2))
+ {
+ break;
+ }
+
+ // Are there instructions at both offsets?
+ if (branchTargetFinder.isInstruction(newOffset1) &&
+ branchTargetFinder.isInstruction(newOffset2))
+ {
+ // Are the offsets involved in some branches?
+ // Note that the preverifier doesn't like initializer
+ // invocations to be moved around.
+ // Also note that the preverifier doesn't like pop instructions
+ // that work on different operands.
+ if (branchTargetFinder.isBranchOrigin(newOffset1) ||
+ branchTargetFinder.isBranchTarget(newOffset1) ||
+ branchTargetFinder.isExceptionStart(newOffset1) ||
+ branchTargetFinder.isExceptionEnd(newOffset1) ||
+ branchTargetFinder.isInitializer(newOffset1) ||
+ branchTargetFinder.isExceptionStart(newOffset2) ||
+ branchTargetFinder.isExceptionEnd(newOffset2) ||
+ isPop(code[newOffset1]))
+ {
+ break;
+ }
+
+ // Make sure the new branch target was a branch target before,
+ // in order not to introduce new entries in the stack map table.
+ if (branchTargetFinder.isBranchTarget(newOffset2))
+ {
+ successfulDelta = delta;
+ }
+
+ if (branchTargetFinder.isBranchTarget(newOffset1))
+ {
+ break;
+ }
+ }
+ }
+
+ return successfulDelta;
+ }
+
+
+ /**
+ * Returns whether the given opcode represents a pop instruction that must
+ * get a consistent type (pop, pop2, arraylength).
+ */
+ private boolean isPop(byte opcode)
+ {
+ return opcode == InstructionConstants.OP_POP ||
+ opcode == InstructionConstants.OP_POP2 ||
+ opcode == InstructionConstants.OP_ARRAYLENGTH;
+ }
+
+
+ /**
+ * Returns the whether there is a boundary of an exception block between
+ * the given offsets (including both).
+ */
+ private boolean exceptionBoundary(CodeAttribute codeAttribute, int offset1, int offset2)
+ {
+ // Swap the offsets if the second one is smaller than the first one.
+ if (offset2 < offset1)
+ {
+ int offset = offset1;
+ offset1 = offset2;
+ offset2 = offset;
+ }
+
+ // Check if there is a boundary of an exception block.
+ for (int offset = offset1; offset <= offset2; offset++)
+ {
+ if (branchTargetFinder.isExceptionStart(offset) ||
+ branchTargetFinder.isExceptionEnd(offset))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoGotoReplacer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoGotoReplacer.java
new file mode 100644
index 0000000000..de31a69dc4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoGotoReplacer.java
@@ -0,0 +1,115 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor simplifies unconditional branches to other
+ * unconditional branches.
+ *
+ * @author Eric Lafortune
+ */
+public class GotoGotoReplacer
+extends SimplifiedVisitor
+implements InstructionVisitor
+{
+ private final CodeAttributeEditor codeAttributeEditor;
+ private final InstructionVisitor extraInstructionVisitor;
+
+
+ /**
+ * Creates a new GotoGotoReplacer.
+ * @param codeAttributeEditor a code editor that can be used for
+ * accumulating changes to the code.
+ */
+ public GotoGotoReplacer(CodeAttributeEditor codeAttributeEditor)
+ {
+ this(codeAttributeEditor, null);
+ }
+
+
+ /**
+ * Creates a new GotoGotoReplacer.
+ * @param codeAttributeEditor a code editor that can be used for
+ * accumulating changes to the code.
+ * @param extraInstructionVisitor an optional extra visitor for all replaced
+ * goto instructions.
+ */
+ public GotoGotoReplacer(CodeAttributeEditor codeAttributeEditor,
+ InstructionVisitor extraInstructionVisitor)
+ {
+ this.codeAttributeEditor = codeAttributeEditor;
+ this.extraInstructionVisitor = extraInstructionVisitor;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ // Check if the instruction is an unconditional goto instruction.
+ byte opcode = branchInstruction.opcode;
+ if (opcode == InstructionConstants.OP_GOTO ||
+ opcode == InstructionConstants.OP_GOTO_W)
+ {
+ // Check if the goto instruction points to another simple goto
+ // instruction.
+ int branchOffset = branchInstruction.branchOffset;
+ int targetOffset = offset + branchOffset;
+
+ if (branchOffset != 0 &&
+ branchOffset != branchInstruction.length(offset) &&
+ !codeAttributeEditor.isModified(offset) &&
+ !codeAttributeEditor.isModified(targetOffset))
+ {
+ Instruction targetInstruction =
+ InstructionFactory.create(codeAttribute.code, targetOffset);
+
+ if (targetInstruction.opcode == InstructionConstants.OP_GOTO)
+ {
+ // Simplify the goto instruction.
+ int targetBranchOffset = ((BranchInstruction)targetInstruction).branchOffset;
+
+ Instruction newBranchInstruction =
+ new BranchInstruction(opcode,
+ (branchOffset + targetBranchOffset));
+ codeAttributeEditor.replaceInstruction(offset,
+ newBranchInstruction);
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ extraInstructionVisitor.visitBranchInstruction(clazz, method, codeAttribute, offset, branchInstruction);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoReturnReplacer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoReturnReplacer.java
new file mode 100644
index 0000000000..9cf8b64ee0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/GotoReturnReplacer.java
@@ -0,0 +1,115 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor replaces unconditional branches to return instructions
+ * by these same return instructions.
+ *
+ * @author Eric Lafortune
+ */
+public class GotoReturnReplacer
+extends SimplifiedVisitor
+implements InstructionVisitor
+{
+ private final CodeAttributeEditor codeAttributeEditor;
+ private final InstructionVisitor extraInstructionVisitor;
+
+
+ /**
+ * Creates a new GotoReturnReplacer.
+ * @param codeAttributeEditor a code editor that can be used for
+ * accumulating changes to the code.
+ */
+ public GotoReturnReplacer(CodeAttributeEditor codeAttributeEditor)
+ {
+ this(codeAttributeEditor, null);
+ }
+
+
+ /**
+ * Creates a new GotoReturnReplacer.
+ * @param codeAttributeEditor a code editor that can be used for
+ * accumulating changes to the code.
+ * @param extraInstructionVisitor an optional extra visitor for all replaced
+ * goto instructions.
+ */
+ public GotoReturnReplacer(CodeAttributeEditor codeAttributeEditor,
+ InstructionVisitor extraInstructionVisitor)
+ {
+ this.codeAttributeEditor = codeAttributeEditor;
+ this.extraInstructionVisitor = extraInstructionVisitor;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ // Check if the instruction is an unconditional goto instruction.
+ byte opcode = branchInstruction.opcode;
+ if (opcode == InstructionConstants.OP_GOTO ||
+ opcode == InstructionConstants.OP_GOTO_W)
+ {
+ // Check if the goto instruction points to a return instruction.
+ int targetOffset = offset + branchInstruction.branchOffset;
+
+ if (!codeAttributeEditor.isModified(offset) &&
+ !codeAttributeEditor.isModified(targetOffset))
+ {
+ Instruction targetInstruction = InstructionFactory.create(codeAttribute.code,
+ targetOffset);
+ switch (targetInstruction.opcode)
+ {
+ case InstructionConstants.OP_IRETURN:
+ case InstructionConstants.OP_LRETURN:
+ case InstructionConstants.OP_FRETURN:
+ case InstructionConstants.OP_DRETURN:
+ case InstructionConstants.OP_ARETURN:
+ case InstructionConstants.OP_RETURN:
+ // Replace the goto instruction by the return instruction.
+ Instruction returnInstruction =
+ new SimpleInstruction(targetInstruction.opcode);
+ codeAttributeEditor.replaceInstruction(offset,
+ returnInstruction);
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ extraInstructionVisitor.visitBranchInstruction(clazz, method, codeAttribute, offset, branchInstruction);
+ }
+
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/HorizontalClassMerger.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/HorizontalClassMerger.java
new file mode 100644
index 0000000000..8f57574853
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/HorizontalClassMerger.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.ProgramClass;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor inlines siblings in the program classes that it visits,
+ * whenever possible.
+ *
+ * @see ClassMerger
+ * @author Eric Lafortune
+ */
+public class HorizontalClassMerger
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final boolean allowAccessModification;
+ private final boolean mergeInterfacesAggressively;
+ private final ClassVisitor extraClassVisitor;
+
+
+ /**
+ * Creates a new HorizontalClassMerger.
+ * @param allowAccessModification specifies whether the access modifiers
+ * of classes can be changed in order to
+ * merge them.
+ * @param mergeInterfacesAggressively specifies whether interfaces may
+ * be merged aggressively.
+ */
+ public HorizontalClassMerger(boolean allowAccessModification,
+ boolean mergeInterfacesAggressively)
+ {
+ this(allowAccessModification, mergeInterfacesAggressively, null);
+ }
+
+
+ /**
+ * Creates a new VerticalClassMerger.
+ * @param allowAccessModification specifies whether the access modifiers
+ * of classes can be changed in order to
+ * merge them.
+ * @param mergeInterfacesAggressively specifies whether interfaces may
+ * be merged aggressively.
+ * @param extraClassVisitor an optional extra visitor for all
+ * merged classes.
+ */
+ public HorizontalClassMerger(boolean allowAccessModification,
+ boolean mergeInterfacesAggressively,
+ ClassVisitor extraClassVisitor)
+ {
+ this.allowAccessModification = allowAccessModification;
+ this.mergeInterfacesAggressively = mergeInterfacesAggressively;
+ this.extraClassVisitor = extraClassVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ programClass.superClassConstantAccept(new ReferencedClassVisitor(
+ new SubclassTraveler(
+ new ClassMerger(programClass,
+ allowAccessModification,
+ mergeInterfacesAggressively,
+ extraClassVisitor))));
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequenceConstants.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequenceConstants.java
new file mode 100644
index 0000000000..bbeb10130a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequenceConstants.java
@@ -0,0 +1,5128 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.util.ClassReferenceInitializer;
+import proguard.classfile.visitor.ClassPrinter;
+
+/**
+ * This class contains a set of instruction sequences and their suggested
+ * replacements.
+ *
+ * @see InstructionSequencesReplacer
+ * @see InstructionSequenceReplacer
+ * @author Eric Lafortune
+ */
+public class InstructionSequenceConstants
+{
+ private static final int X = InstructionSequenceReplacer.X;
+ private static final int Y = InstructionSequenceReplacer.Y;
+ private static final int Z = InstructionSequenceReplacer.Z;
+
+ private static final int A = InstructionSequenceReplacer.A;
+ private static final int B = InstructionSequenceReplacer.B;
+ private static final int C = InstructionSequenceReplacer.C;
+ private static final int D = InstructionSequenceReplacer.D;
+
+ private static final int STRING_A_LENGTH = InstructionSequenceReplacer.STRING_A_LENGTH;
+ private static final int BOOLEAN_A_STRING = InstructionSequenceReplacer.BOOLEAN_A_STRING;
+ private static final int CHAR_A_STRING = InstructionSequenceReplacer.CHAR_A_STRING;
+ private static final int INT_A_STRING = InstructionSequenceReplacer.INT_A_STRING;
+ private static final int LONG_A_STRING = InstructionSequenceReplacer.LONG_A_STRING;
+ private static final int FLOAT_A_STRING = InstructionSequenceReplacer.FLOAT_A_STRING;
+ private static final int DOUBLE_A_STRING = InstructionSequenceReplacer.DOUBLE_A_STRING;
+ private static final int STRING_A_STRING = InstructionSequenceReplacer.STRING_A_STRING;
+ private static final int BOOLEAN_B_STRING = InstructionSequenceReplacer.BOOLEAN_B_STRING;
+ private static final int CHAR_B_STRING = InstructionSequenceReplacer.CHAR_B_STRING;
+ private static final int INT_B_STRING = InstructionSequenceReplacer.INT_B_STRING;
+ private static final int LONG_B_STRING = InstructionSequenceReplacer.LONG_B_STRING;
+ private static final int FLOAT_B_STRING = InstructionSequenceReplacer.FLOAT_B_STRING;
+ private static final int DOUBLE_B_STRING = InstructionSequenceReplacer.DOUBLE_B_STRING;
+ private static final int STRING_B_STRING = InstructionSequenceReplacer.STRING_B_STRING;
+
+ private static final int I_32768 = 0;
+ private static final int I_65536 = 1;
+ private static final int I_16777216 = 2;
+
+// private static final int I_0x000000ff
+ private static final int I_0x0000ff00 = 3;
+ private static final int I_0x00ff0000 = 4;
+ private static final int I_0xff000000 = 5;
+ private static final int I_0x0000ffff = 6;
+ private static final int I_0xffff0000 = 7;
+
+ private static final int L_M1 = 8;
+ private static final int L_2 = 9;
+ private static final int L_4 = 10;
+ private static final int L_8 = 11;
+ private static final int L_16 = 12;
+ private static final int L_32 = 13;
+ private static final int L_64 = 14;
+ private static final int L_128 = 15;
+ private static final int L_256 = 16;
+ private static final int L_512 = 17;
+ private static final int L_1024 = 18;
+ private static final int L_2048 = 19;
+ private static final int L_4096 = 20;
+ private static final int L_8192 = 21;
+ private static final int L_16384 = 22;
+ private static final int L_32768 = 23;
+ private static final int L_65536 = 24;
+ private static final int L_16777216 = 25;
+ private static final int L_4294967296 = 26;
+
+ private static final int L_0x00000000ffffffff = 27;
+ private static final int L_0xffffffff00000000 = 28;
+
+ private static final int F_M1 = 29;
+
+ private static final int D_M1 = 30;
+
+ private static final int STRING_EMPTY = 31;
+
+ private static final int FIELD_I = 32; // Implicitly uses X and Y.
+ private static final int FIELD_L = 33; // Implicitly uses X and Y.
+ private static final int FIELD_F = 34; // Implicitly uses X and Y.
+ private static final int FIELD_D = 35; // Implicitly uses X and Y.
+
+ private static final int METHOD_STRING_EQUALS = 36;
+ private static final int METHOD_STRING_LENGTH = 37;
+ private static final int METHOD_STRING_VALUEOF_Z = 38;
+ private static final int METHOD_STRING_VALUEOF_C = 39;
+ private static final int METHOD_STRING_VALUEOF_I = 40;
+ private static final int METHOD_STRING_VALUEOF_J = 41;
+ private static final int METHOD_STRING_VALUEOF_F = 42;
+ private static final int METHOD_STRING_VALUEOF_D = 43;
+ private static final int METHOD_STRING_VALUEOF_OBJECT = 44;
+ private static final int METHOD_STRINGBUFFER_INIT = 45;
+ private static final int METHOD_STRINGBUFFER_INIT_STRING = 46;
+ private static final int METHOD_STRINGBUFFER_APPEND_Z = 47;
+ private static final int METHOD_STRINGBUFFER_APPEND_C = 48;
+ private static final int METHOD_STRINGBUFFER_APPEND_I = 49;
+ private static final int METHOD_STRINGBUFFER_APPEND_J = 50;
+ private static final int METHOD_STRINGBUFFER_APPEND_F = 51;
+ private static final int METHOD_STRINGBUFFER_APPEND_D = 52;
+ private static final int METHOD_STRINGBUFFER_APPEND_STRING = 53;
+ private static final int METHOD_STRINGBUFFER_APPEND_OBJECT = 54;
+ private static final int METHOD_STRINGBUFFER_LENGTH = 55;
+ private static final int METHOD_STRINGBUFFER_TOSTRING = 56;
+ private static final int METHOD_STRINGBUILDER_INIT = 57;
+ private static final int METHOD_STRINGBUILDER_INIT_STRING = 58;
+ private static final int METHOD_STRINGBUILDER_APPEND_Z = 59;
+ private static final int METHOD_STRINGBUILDER_APPEND_C = 60;
+ private static final int METHOD_STRINGBUILDER_APPEND_I = 61;
+ private static final int METHOD_STRINGBUILDER_APPEND_J = 62;
+ private static final int METHOD_STRINGBUILDER_APPEND_F = 63;
+ private static final int METHOD_STRINGBUILDER_APPEND_D = 64;
+ private static final int METHOD_STRINGBUILDER_APPEND_STRING = 65;
+ private static final int METHOD_STRINGBUILDER_APPEND_OBJECT = 66;
+ private static final int METHOD_STRINGBUILDER_LENGTH = 67;
+ private static final int METHOD_STRINGBUILDER_TOSTRING = 68;
+
+ private static final int CLASS_STRING = 69;
+ private static final int CLASS_STRINGBUFFER = 70;
+ private static final int CLASS_STRINGBUILDER = 71;
+
+ private static final int NAME_AND_TYPE_I = 72; // Implicitly uses Y.
+ private static final int NAME_AND_TYPE_L = 73; // Implicitly uses Y.
+ private static final int NAME_AND_TYPE_F = 74; // Implicitly uses Y.
+ private static final int NAME_AND_TYPE_D = 75; // Implicitly uses Y.
+
+ private static final int NAME_AND_TYPE_EQUALS = 76;
+ private static final int NAME_AND_TYPE_LENGTH = 77;
+ private static final int NAME_AND_TYPE_VALUEOF_Z = 78;
+ private static final int NAME_AND_TYPE_VALUEOF_C = 79;
+ private static final int NAME_AND_TYPE_VALUEOF_I = 80;
+ private static final int NAME_AND_TYPE_VALUEOF_J = 81;
+ private static final int NAME_AND_TYPE_VALUEOF_F = 82;
+ private static final int NAME_AND_TYPE_VALUEOF_D = 83;
+ private static final int NAME_AND_TYPE_VALUEOF_OBJECT = 84;
+ private static final int NAME_AND_TYPE_INIT = 85;
+ private static final int NAME_AND_TYPE_INIT_STRING = 86;
+ private static final int NAME_AND_TYPE_APPEND_Z_STRINGBUFFER = 87;
+ private static final int NAME_AND_TYPE_APPEND_C_STRINGBUFFER = 88;
+ private static final int NAME_AND_TYPE_APPEND_I_STRINGBUFFER = 89;
+ private static final int NAME_AND_TYPE_APPEND_J_STRINGBUFFER = 90;
+ private static final int NAME_AND_TYPE_APPEND_F_STRINGBUFFER = 91;
+ private static final int NAME_AND_TYPE_APPEND_D_STRINGBUFFER = 92;
+ private static final int NAME_AND_TYPE_APPEND_STRING_STRINGBUFFER = 93;
+ private static final int NAME_AND_TYPE_APPEND_OBJECT_STRINGBUFFER = 94;
+ private static final int NAME_AND_TYPE_APPEND_Z_STRINGBUILDER = 95;
+ private static final int NAME_AND_TYPE_APPEND_C_STRINGBUILDER = 96;
+ private static final int NAME_AND_TYPE_APPEND_I_STRINGBUILDER = 97;
+ private static final int NAME_AND_TYPE_APPEND_J_STRINGBUILDER = 98;
+ private static final int NAME_AND_TYPE_APPEND_F_STRINGBUILDER = 99;
+ private static final int NAME_AND_TYPE_APPEND_D_STRINGBUILDER = 100;
+ private static final int NAME_AND_TYPE_APPEND_STRING_STRINGBUILDER = 101;
+ private static final int NAME_AND_TYPE_APPEND_OBJECT_STRINGBUILDER = 102;
+ private static final int NAME_AND_TYPE_TOSTRING = 103;
+
+ private static final int UTF8_EMPTY = 104;
+ private static final int UTF8_I = 105;
+ private static final int UTF8_L = 106;
+ private static final int UTF8_F = 107;
+ private static final int UTF8_D = 108;
+ private static final int UTF8_STRING = 109;
+ private static final int UTF8_STRINGBUFFER = 110;
+ private static final int UTF8_STRINGBUILDER = 111;
+ private static final int UTF8_EQUALS = 112;
+ private static final int UTF8_OBJECT_Z = 113;
+ private static final int UTF8_LENGTH = 114;
+ private static final int UTF8__I = 115;
+ private static final int UTF8_VALUEOF = 116;
+ private static final int UTF8_Z_STRING = 117;
+ private static final int UTF8_C_STRING = 118;
+ private static final int UTF8_I_STRING = 119;
+ private static final int UTF8_J_STRING = 120;
+ private static final int UTF8_F_STRING = 121;
+ private static final int UTF8_D_STRING = 122;
+ private static final int UTF8_OBJECT_STRING = 123;
+ private static final int UTF8_INIT = 124;
+ private static final int UTF8__VOID = 125;
+ private static final int UTF8_STRING_VOID = 126;
+ private static final int UTF8_TOSTRING = 127;
+ private static final int UTF8__STRING = 128;
+ private static final int UTF8_APPEND = 129;
+ private static final int UTF8_Z_STRINGBUFFER = 130;
+ private static final int UTF8_C_STRINGBUFFER = 131;
+ private static final int UTF8_I_STRINGBUFFER = 132;
+ private static final int UTF8_J_STRINGBUFFER = 133;
+ private static final int UTF8_F_STRINGBUFFER = 134;
+ private static final int UTF8_D_STRINGBUFFER = 135;
+ private static final int UTF8_STRING_STRINGBUFFER = 136;
+ private static final int UTF8_OBJECT_STRINGBUFFER = 137;
+ private static final int UTF8_Z_STRINGBUILDER = 138;
+ private static final int UTF8_C_STRINGBUILDER = 139;
+ private static final int UTF8_I_STRINGBUILDER = 140;
+ private static final int UTF8_J_STRINGBUILDER = 141;
+ private static final int UTF8_F_STRINGBUILDER = 142;
+ private static final int UTF8_D_STRINGBUILDER = 143;
+ private static final int UTF8_STRING_STRINGBUILDER = 144;
+ private static final int UTF8_OBJECT_STRINGBUILDER = 145;
+
+ private static final int SENTINEL = 146;
+
+ // The arrays with constants and instructions used to be static,
+ // but now they are initialized with references to classes and
+ // class members, inside an instance of this class. As an added
+ // benefit, they can be garbage collected after they have been used.
+
+ public final Constant[] CONSTANTS = new Constant[]
+ {
+ new IntegerConstant(32768),
+ new IntegerConstant(65536),
+ new IntegerConstant(16777216),
+
+ new IntegerConstant(0x0000ff00),
+ new IntegerConstant(0x00ff0000),
+ new IntegerConstant(0xff000000),
+ new IntegerConstant(0x0000ffff),
+ new IntegerConstant(0xffff0000),
+
+ new LongConstant(-1L),
+ new LongConstant(2L),
+ new LongConstant(4L),
+ new LongConstant(8L),
+ new LongConstant(16L),
+ new LongConstant(32L),
+ new LongConstant(64L),
+ new LongConstant(128L),
+ new LongConstant(256L),
+ new LongConstant(512L),
+ new LongConstant(1024L),
+ new LongConstant(2048L),
+ new LongConstant(4096L),
+ new LongConstant(8192L),
+ new LongConstant(16384L),
+ new LongConstant(32768L),
+ new LongConstant(65536L),
+ new LongConstant(16777216L),
+ new LongConstant(4294967296L),
+
+ new LongConstant(0x00000000ffffffffL),
+ new LongConstant(0xffffffff00000000L),
+
+ new FloatConstant(-1f),
+
+ new DoubleConstant(-1d),
+
+ new StringConstant(UTF8_EMPTY, null, null),
+
+ new FieldrefConstant(X, NAME_AND_TYPE_I, null, null),
+ new FieldrefConstant(X, NAME_AND_TYPE_L, null, null),
+ new FieldrefConstant(X, NAME_AND_TYPE_F, null, null),
+ new FieldrefConstant(X, NAME_AND_TYPE_D, null, null),
+
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_EQUALS, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_LENGTH, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_Z, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_C, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_I, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_J, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_F, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_D, null, null),
+ new MethodrefConstant(CLASS_STRING, NAME_AND_TYPE_VALUEOF_OBJECT, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_INIT, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_INIT_STRING, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_Z_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_C_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_I_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_J_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_F_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_D_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_STRING_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_APPEND_OBJECT_STRINGBUFFER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_LENGTH, null, null),
+ new MethodrefConstant(CLASS_STRINGBUFFER, NAME_AND_TYPE_TOSTRING, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_INIT, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_INIT_STRING, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_Z_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_C_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_I_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_J_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_F_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_D_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_STRING_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_APPEND_OBJECT_STRINGBUILDER, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_LENGTH, null, null),
+ new MethodrefConstant(CLASS_STRINGBUILDER, NAME_AND_TYPE_TOSTRING, null, null),
+
+ new ClassConstant(UTF8_STRING, null),
+ new ClassConstant(UTF8_STRINGBUFFER, null),
+ new ClassConstant(UTF8_STRINGBUILDER, null),
+
+ new NameAndTypeConstant(Y, UTF8_I),
+ new NameAndTypeConstant(Y, UTF8_L),
+ new NameAndTypeConstant(Y, UTF8_F),
+ new NameAndTypeConstant(Y, UTF8_D),
+ new NameAndTypeConstant(UTF8_EQUALS, UTF8_OBJECT_Z),
+ new NameAndTypeConstant(UTF8_LENGTH, UTF8__I),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_Z_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_C_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_I_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_J_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_F_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_D_STRING),
+ new NameAndTypeConstant(UTF8_VALUEOF, UTF8_OBJECT_STRING),
+ new NameAndTypeConstant(UTF8_INIT, UTF8__VOID),
+ new NameAndTypeConstant(UTF8_INIT, UTF8_STRING_VOID),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_Z_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_C_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_I_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_J_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_F_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_D_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_STRING_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_OBJECT_STRINGBUFFER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_Z_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_C_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_I_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_J_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_F_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_D_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_STRING_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_APPEND, UTF8_OBJECT_STRINGBUILDER),
+ new NameAndTypeConstant(UTF8_TOSTRING, UTF8__STRING),
+
+ new Utf8Constant(""),
+ new Utf8Constant("I"),
+ new Utf8Constant("J"),
+ new Utf8Constant("F"),
+ new Utf8Constant("D"),
+ new Utf8Constant(ClassConstants.NAME_JAVA_LANG_STRING),
+ new Utf8Constant(ClassConstants.NAME_JAVA_LANG_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.NAME_JAVA_LANG_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.METHOD_NAME_EQUALS),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_EQUALS),
+ new Utf8Constant(ClassConstants.METHOD_NAME_LENGTH),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_LENGTH),
+ new Utf8Constant(ClassConstants.METHOD_NAME_VALUEOF),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_BOOLEAN),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_CHAR),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_INT),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_LONG),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_FLOAT),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_DOUBLE),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_OBJECT),
+ new Utf8Constant(ClassConstants.METHOD_NAME_INIT),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_INIT),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_STRING_VOID),
+ new Utf8Constant(ClassConstants.METHOD_NAME_TOSTRING),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_TOSTRING),
+ new Utf8Constant(ClassConstants.METHOD_NAME_APPEND),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_BOOLEAN_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_CHAR_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_INT_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_LONG_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_FLOAT_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_DOUBLE_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_STRING_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_OBJECT_STRING_BUFFER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_BOOLEAN_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_CHAR_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_INT_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_LONG_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_FLOAT_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_DOUBLE_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_STRING_STRING_BUILDER),
+ new Utf8Constant(ClassConstants.METHOD_TYPE_OBJECT_STRING_BUILDER),
+ };
+
+ public final Instruction[][][] VARIABLE = new Instruction[][][]
+ {
+ { // nop = nothing
+ {
+ new SimpleInstruction(InstructionConstants.OP_NOP),
+ },{
+ // Nothing.
+ },
+ },
+ { // iload/pop = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // lload/pop2 = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_LLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },{
+ // Nothing.
+ },
+ },
+ { // fload/pop = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // dload/pop2 = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },{
+ // Nothing.
+ },
+ },
+ { // aload/pop = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // i = i = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // l = l = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_LLOAD, X),
+ new VariableInstruction(InstructionConstants.OP_LSTORE, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // f = f = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ new VariableInstruction(InstructionConstants.OP_FSTORE, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // d = d = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ new VariableInstruction(InstructionConstants.OP_DSTORE, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // a = a = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+ new VariableInstruction(InstructionConstants.OP_ASTORE, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // istore/istore = pop/istore
+ {
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },
+ },
+ { // lstore/lstore = pop2/lstore
+ {
+ new VariableInstruction(InstructionConstants.OP_LSTORE, X),
+ new VariableInstruction(InstructionConstants.OP_LSTORE, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ new VariableInstruction(InstructionConstants.OP_LSTORE, X),
+ },
+ },
+ { // fstore/fstore = pop/fstore
+ {
+ new VariableInstruction(InstructionConstants.OP_FSTORE, X),
+ new VariableInstruction(InstructionConstants.OP_FSTORE, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ new VariableInstruction(InstructionConstants.OP_FSTORE, X),
+ },
+ },
+ { // dstore/dstore = pop2/dstore
+ {
+ new VariableInstruction(InstructionConstants.OP_DSTORE, X),
+ new VariableInstruction(InstructionConstants.OP_DSTORE, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ new VariableInstruction(InstructionConstants.OP_DSTORE, X),
+ },
+ },
+ { // astore/astore = pop/astore
+ {
+ new VariableInstruction(InstructionConstants.OP_ASTORE, X),
+ new VariableInstruction(InstructionConstants.OP_ASTORE, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ new VariableInstruction(InstructionConstants.OP_ASTORE, X),
+ },
+ },
+ { // istore/iload = dup/istore
+ {
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },
+ },
+ { // lstore/lload = dup2/lstore
+ {
+ new VariableInstruction(InstructionConstants.OP_LSTORE, X),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_DUP2),
+ new VariableInstruction(InstructionConstants.OP_LSTORE, X),
+ },
+ },
+ { // fstore/fload = dup/fstore
+ {
+ new VariableInstruction(InstructionConstants.OP_FSTORE, X),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new VariableInstruction(InstructionConstants.OP_FSTORE, X),
+ },
+ },
+ { // dstore/dload = dup2/dstore
+ {
+ new VariableInstruction(InstructionConstants.OP_DSTORE, X),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_DUP2),
+ new VariableInstruction(InstructionConstants.OP_DSTORE, X),
+ },
+ },
+ { // astore/aload = dup/astore
+ {
+ new VariableInstruction(InstructionConstants.OP_ASTORE, X),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new VariableInstruction(InstructionConstants.OP_ASTORE, X),
+ },
+ },
+ };
+
+ public static final Instruction[][][] ARITHMETIC = new Instruction[][][]
+ {
+ { // c + i = i + c
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ },
+ },
+ { // b + i = i + b
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, A),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, A),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ },
+ },
+ { // s + i = i + s
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ },
+ },
+ { // c + i = i + c
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ },
+ },
+ { // c * i = i * c
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },
+ },
+ { // b * i = i * b
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, A),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, A),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },
+ },
+ { // s * i = i * s
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },
+ },
+ { // c * i = i * c
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },
+ },
+ { // c + l = l + c
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_LADD),
+ },{
+ new VariableInstruction(InstructionConstants.OP_LLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_LADD),
+ },
+ },
+ { // c + l = l + c
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_LADD),
+ },{
+ new VariableInstruction(InstructionConstants.OP_LLOAD, X),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new SimpleInstruction(InstructionConstants.OP_LADD),
+ },
+ },
+ { // c * l = l * c
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new VariableInstruction(InstructionConstants.OP_LLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },
+ },
+ { // c + f = f + c
+ {
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_FADD),
+ },{
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_FADD),
+ },
+ },
+ { // c + f = f + c
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_FADD),
+ },{
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new SimpleInstruction(InstructionConstants.OP_FADD),
+ },
+ },
+ { // c * f = f * c
+ {
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_FMUL),
+ },{
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_FMUL),
+ },
+ },
+ { // c * f = f * c
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new VariableInstruction(InstructionConstants.OP_FLOAD, X),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },
+ },
+ { // c + d = d + c
+ {
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_DADD),
+ },{
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_DADD),
+ },
+ },
+ { // c + d = d + c
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_DADD),
+ },{
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new SimpleInstruction(InstructionConstants.OP_DADD),
+ },
+ },
+ { // c * d = d * c
+ {
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_DMUL),
+ },{
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new SimpleInstruction(InstructionConstants.OP_DMUL),
+ },
+ },
+ { // c * d = d * c
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_DMUL),
+ },{
+ new VariableInstruction(InstructionConstants.OP_DLOAD, X),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new SimpleInstruction(InstructionConstants.OP_DMUL),
+ },
+ },
+ { // i = i + c = i += c
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_IINC, X, A),
+ },
+ },
+ { // i = i + b = i += b
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, A),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_IINC, X, A),
+ },
+ },
+ { // i = i + s = i += s
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_IINC, X, A),
+ },
+ },
+ { // i = i - -1 = i++
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new SimpleInstruction(InstructionConstants.OP_ISUB),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_IINC, X, 1),
+ },
+ },
+ { // i = i - 1 = i--
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new SimpleInstruction(InstructionConstants.OP_ISUB),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_IINC, X, -1),
+ },
+ },
+ { // i = i - 2 = i -= 2
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+ new SimpleInstruction(InstructionConstants.OP_ISUB),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_IINC, X, -2),
+ },
+ },
+ { // i = i - 3 = i -= 3
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_3),
+ new SimpleInstruction(InstructionConstants.OP_ISUB),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_IINC, X, -3),
+ },
+ },
+ { // i = i - 4 = i -= 4
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_4),
+ new SimpleInstruction(InstructionConstants.OP_ISUB),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_IINC, X, -4),
+ },
+ },
+ { // i = i - 5 = i -= 5
+ {
+ new VariableInstruction(InstructionConstants.OP_ILOAD, X),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_5),
+ new SimpleInstruction(InstructionConstants.OP_ISUB),
+ new VariableInstruction(InstructionConstants.OP_ISTORE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_IINC, X, -5),
+ },
+ },
+ { // ... + 0 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... + 0L = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0),
+ new SimpleInstruction(InstructionConstants.OP_LADD),
+ },{
+ // Nothing.
+ },
+ },
+ // Not valid for -0.0.
+// { // ... + 0f = ...
+// {
+// new SimpleInstruction(InstructionConstants.OP_FCONST_0),
+// new SimpleInstruction(InstructionConstants.OP_FADD),
+// },{
+// // Nothing.
+// },
+// },
+// { // ... + 0d = ...
+// {
+// new SimpleInstruction(InstructionConstants.OP_DCONST_0),
+// new SimpleInstruction(InstructionConstants.OP_DADD),
+// },{
+// // Nothing.
+// },
+// },
+ { // ... - 0 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_ISUB),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... - 0L = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0),
+ new SimpleInstruction(InstructionConstants.OP_LSUB),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... - 0f = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0),
+ new SimpleInstruction(InstructionConstants.OP_FSUB),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... - 0d = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0),
+ new SimpleInstruction(InstructionConstants.OP_DSUB),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... * -1 = -...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_INEG),
+ },
+ },
+ { // ... * 0 = 0
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ },
+ },
+ { // ... * 1 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... * 2 = ... << 1
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 4 = ... << 2
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_4),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 8 = ... << 3
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 8),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_ICONST_3),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 16 = ... << 4
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 4),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 32 = ... << 5
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 32),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 5),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 64 = ... << 6
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 64),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 6),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 128 = ... << 7
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 128),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 7),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 256 = ... << 8
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 256),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 8),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 512 = ... << 9
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 512),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 9),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 1024 = ... << 10
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 1024),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 10),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 2048 = ... << 11
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 2048),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 11),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 4096 = ... << 12
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 4096),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 12),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 8192 = ... << 13
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 8192),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 13),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 16384 = ... << 14
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 16384),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 14),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 32768 = ... << 15
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_32768),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 15),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 65536 = ... << 16
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_65536),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * 16777216 = ... << 24
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_16777216),
+ new SimpleInstruction(InstructionConstants.OP_IMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },
+ },
+ { // ... * -1L = -...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_M1),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_LNEG),
+ },
+ },
+ { // ... * 0L = 0L
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0),
+ },
+ },
+ { // ... * 1L = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_1),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... * 2L = ... << 1
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_2),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 4L = ... << 2
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_4),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 8L = ... << 3
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_8),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_ICONST_3),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 16L = ... << 4
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_16),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 4),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 32L = ... << 5
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_32),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 5),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 64L = ... << 6
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_64),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 6),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 128L = ... << 7
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_128),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 7),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 256L = ... << 8
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_256),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 8),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 512L = ... << 9
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_512),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 9),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 1024L = ... << 10
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_1024),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 10),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 2048L = ... << 11
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_2048),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 11),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 4096L = ... << 12
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_4096),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 12),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 8192L = ... << 13
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_8192),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 13),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 16384L = ... << 14
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_16384),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 14),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 32768L = ... << 15
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_32768),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 15),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 65536LL = ... << 16
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_65536),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 16777216L = ... << 24
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_16777216),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * 4294967296L = ... << 32
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_4294967296),
+ new SimpleInstruction(InstructionConstants.OP_LMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 32),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },
+ },
+ { // ... * -1f = -...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, F_M1),
+ new SimpleInstruction(InstructionConstants.OP_FMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_FNEG),
+ },
+ },
+ // Not valid for -0.0 and for NaN.
+// { // ... * 0f = 0f
+// {
+// new SimpleInstruction(InstructionConstants.OP_FCONST_0),
+// new SimpleInstruction(InstructionConstants.OP_FMUL),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_POP),
+// new SimpleInstruction(InstructionConstants.OP_FCONST_0),
+// },
+// },
+ { // ... * 1f = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_FCONST_1),
+ new SimpleInstruction(InstructionConstants.OP_FMUL),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... * -1d = -...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, D_M1),
+ new SimpleInstruction(InstructionConstants.OP_DMUL),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_DNEG),
+ },
+ },
+ // Not valid for -0.0 and for NaN.
+// { // ... * 0d = 0d
+// {
+// new SimpleInstruction(InstructionConstants.OP_DCONST_0),
+// new SimpleInstruction(InstructionConstants.OP_DMUL),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_POP2),
+// new SimpleInstruction(InstructionConstants.OP_DCONST_0),
+// },
+// },
+ { // ... * 1d = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_DCONST_1),
+ new SimpleInstruction(InstructionConstants.OP_DMUL),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... / -1 = -...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new SimpleInstruction(InstructionConstants.OP_IDIV),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_INEG),
+ },
+ },
+ { // ... / 1 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new SimpleInstruction(InstructionConstants.OP_IDIV),
+ },{
+ // Nothing.
+ },
+ },
+ // Not valid for negative values.
+// { // ... / 2 = ... >> 1
+// {
+// new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 4 = ... >> 2
+// {
+// new SimpleInstruction(InstructionConstants.OP_ICONST_4),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 8 = ... >> 3
+// {
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 8),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_ICONST_3),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 16 = ... >> 4
+// {
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 4),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 32 = ... >> 5
+// {
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 32),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 5),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 64 = ... >> 6
+// {
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 64),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 6),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 128 = ... >> 7
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 128),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 7),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 256 = ... >> 8
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 256),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 8),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 512 = ... >> 9
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 512),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 9),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 1024 = ... >> 10
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 1024),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 10),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 2048 = ... >> 11
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 2048),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 11),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 4096 = ... >> 12
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 4096),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 12),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 8192 = ... >> 13
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 8192),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 13),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 16384 = ... >> 14
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 16384),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 14),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 32768 = ... >> 15
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, I_32768),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 15),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 65536 = ... >> 16
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, I_65536),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+// { // ... / 16777216 = ... >> 24
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC, I_16777216),
+// new SimpleInstruction(InstructionConstants.OP_IDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+// new SimpleInstruction(InstructionConstants.OP_ISHR),
+// },
+// },
+ { // ... / -1L = -...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_M1),
+ new SimpleInstruction(InstructionConstants.OP_LDIV),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_LNEG),
+ },
+ },
+ { // ... / 1L = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_1),
+ new SimpleInstruction(InstructionConstants.OP_LDIV),
+ },{
+ // Nothing.
+ },
+ },
+ // Not valid for negative values.
+// { // ... / 2L = ... >> 1
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_2),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 4L = ... >> 2
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_4),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 8L = ... >> 3
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_8),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_ICONST_3),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 16L = ... >> 4
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_16),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 4),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 32L = ... >> 5
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_32),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 5),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 64L = ... >> 6
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_64),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 6),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 128L = ... >> 7
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_128),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 7),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 256L = ... >> 8
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_256),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 8),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 512L = ... >> 9
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_512),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 9),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 1024L = ... >> 10
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_1024),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 10),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 2048L = ... >> 11
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_2048),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 11),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 4096L = ... >> 12
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_4096),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 12),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 8192L = ... >> 13
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_8192),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 13),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 16384L = ... >> 14
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_16384),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 14),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 32768L = ... >> 15
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_32768),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 15),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 65536LL = ... >> 16
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_65536),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 16777216L = ... >> 24
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_16777216),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+// { // ... / 4294967296L = ... >> 32
+// {
+// new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_4294967296),
+// new SimpleInstruction(InstructionConstants.OP_LDIV),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 32),
+// new SimpleInstruction(InstructionConstants.OP_LSHR),
+// },
+// },
+ { // ... / -1f = -...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, F_M1),
+ new SimpleInstruction(InstructionConstants.OP_FDIV),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_FNEG),
+ },
+ },
+ { // ... / 1f = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_FCONST_1),
+ new SimpleInstruction(InstructionConstants.OP_FDIV),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... / -1d = -...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, D_M1),
+ new SimpleInstruction(InstructionConstants.OP_DDIV),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_DNEG),
+ },
+ },
+ { // ... / 1d = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_DCONST_1),
+ new SimpleInstruction(InstructionConstants.OP_DDIV),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... % 1 = 0
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new SimpleInstruction(InstructionConstants.OP_IREM),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ },
+ },
+ // Not valid for negative values.
+// { // ... % 2 = ... & 0x1
+// {
+// new SimpleInstruction(InstructionConstants.OP_ICONST_2),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 4 = ... & 0x3
+// {
+// new SimpleInstruction(InstructionConstants.OP_ICONST_4),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_ICONST_3),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 8 = ... & 0x07
+// {
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 8),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 0x07),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 16 = ... & 0x0f
+// {
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 0x0f),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 32 = ... & 0x1f
+// {
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 32),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 0x1f),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 64 = ... & 0x3f
+// {
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 64),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 0x3f),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 128 = ... & 0x7f
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 128),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BIPUSH, 0x7f),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 256 = ... & 0x00ff
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 256),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0x00ff),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 512 = ... & 0x01ff
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 512),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0x01ff),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 1024 = ... & 0x03ff
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 1024),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0x03ff),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 2048 = ... & 0x07ff
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 2048),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0x07ff),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 4096 = ... & 0x0fff
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 4096),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0x0fff),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 8192 = ... & 0x1fff
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 8192),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0x1fff),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+// { // ... % 16384 = ... & 0x3fff
+// {
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 16384),
+// new SimpleInstruction(InstructionConstants.OP_IREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0x3fff),
+// new SimpleInstruction(InstructionConstants.OP_IAND),
+// },
+// },
+ { // ... % 1L = 0L
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_1),
+ new SimpleInstruction(InstructionConstants.OP_LREM),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0),
+ },
+ },
+// { // ... % 1f = 0f
+// {
+// new SimpleInstruction(InstructionConstants.OP_FCONST_1),
+// new SimpleInstruction(InstructionConstants.OP_FREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_POP),
+// new SimpleInstruction(InstructionConstants.OP_FCONST_0),
+// },
+// },
+// { // ... % 1d = 0d
+// {
+// new SimpleInstruction(InstructionConstants.OP_DCONST_1),
+// new SimpleInstruction(InstructionConstants.OP_DREM),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_POP2),
+// new SimpleInstruction(InstructionConstants.OP_DCONST_0),
+// },
+// },
+ { // -(-...) = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_INEG),
+ new SimpleInstruction(InstructionConstants.OP_INEG),
+ },{
+ // Nothing.
+ },
+ },
+ { // -(-...) = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_LNEG),
+ new SimpleInstruction(InstructionConstants.OP_LNEG),
+ },{
+ // Nothing.
+ },
+ },
+ { // -(-...) = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_FNEG),
+ new SimpleInstruction(InstructionConstants.OP_FNEG),
+ },{
+ // Nothing.
+ },
+ },
+ { // -(-...) = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_DNEG),
+ new SimpleInstruction(InstructionConstants.OP_DNEG),
+ },{
+ // Nothing.
+ },
+ },
+ { // +(-...) = -...
+ {
+ new SimpleInstruction(InstructionConstants.OP_INEG),
+ new SimpleInstruction(InstructionConstants.OP_IADD),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_ISUB),
+ },
+ },
+ { // +(-...) = -...
+ {
+ new SimpleInstruction(InstructionConstants.OP_LNEG),
+ new SimpleInstruction(InstructionConstants.OP_LADD),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_LSUB),
+ },
+ },
+ { // +(-...) = -...
+ {
+ new SimpleInstruction(InstructionConstants.OP_FNEG),
+ new SimpleInstruction(InstructionConstants.OP_FADD),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_FSUB),
+ },
+ },
+ { // +(-...) = -...
+ {
+ new SimpleInstruction(InstructionConstants.OP_DNEG),
+ new SimpleInstruction(InstructionConstants.OP_DADD),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_DSUB),
+ },
+ },
+ { // ... << 0 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... << 0 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... >> 0 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... >> 0 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_LSHR),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... >>> 0 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... >>> 0 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_LUSHR),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... & -1 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... & 0 = 0
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ },
+ },
+ { // ... & -1L = ...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_M1),
+ new SimpleInstruction(InstructionConstants.OP_LAND),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... & 0L = 0L
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0),
+ new SimpleInstruction(InstructionConstants.OP_LAND),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0),
+ },
+ },
+ { // ... | -1 = -1
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new SimpleInstruction(InstructionConstants.OP_IOR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ },
+ },
+ { // ... | 0 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_IOR),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... | -1L = -1L
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_M1),
+ new SimpleInstruction(InstructionConstants.OP_LAND),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_M1),
+ },
+ },
+ { // ... | 0L = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0),
+ new SimpleInstruction(InstructionConstants.OP_LOR),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... ^ 0 = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new SimpleInstruction(InstructionConstants.OP_IXOR),
+ },{
+ // Nothing.
+ },
+ },
+ { // ... ^ 0L = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0),
+ new SimpleInstruction(InstructionConstants.OP_LXOR),
+ },{
+ // Nothing.
+ },
+ },
+ { // (... & 0x0000ff00) >> 8 = (... >> 8) & 0xff
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_0x0000ff00),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 8),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 8),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0xff),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ },
+ },
+ { // (... & 0x0000ff00) >>> 8 = (... >>> 8) & 0xff
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_0x0000ff00),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 8),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 8),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0xff),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ },
+ },
+ { // (... & 0x00ff0000) >> 16 = (... >> 16) & 0xff
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_0x00ff0000),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0xff),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ },
+ },
+ { // (... & 0x00ff0000) >>> 16 = (... >>> 16) & 0xff
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_0x00ff0000),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0xff),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ },
+ },
+ { // (... & 0xff000000) >> 24 = ... >> 24
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_0xff000000),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },
+ },
+ { // (... & 0xffff0000) >> 16 = ... >> 16
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_0xffff0000),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },
+ },
+ { // (... & 0xffff0000) >>> 16 = ... >>> 16
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_0xffff0000),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ },
+ },
+ { // (... >> 24) & 0xff = ... >>> 24
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0xff),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ },
+ },
+ { // (... >>> 24) & 0xff = ... >>> 24
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0xff),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ },
+ },
+ { // (byte)(... & 0x000000ff) = (byte)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, 0xff),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },
+ },
+ { // (char)(... & 0x0000ffff) = (char)...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_0x0000ffff),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ },
+ },
+ { // (short)(... & 0x0000ffff) = (short)...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, I_0x0000ffff),
+ new SimpleInstruction(InstructionConstants.OP_IAND),
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ },
+ },
+ { // (byte)(... >> 24) = ... >> 24
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },
+ },
+ { // (byte)(... >>> 24) = ... >> 24
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },
+ },
+ { // (char)(... >> 16) = ... >>> 16
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ },
+ },
+ { // (char)(... >>> 16) = ... >>> 16
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ },
+ },
+ { // (short)(... >> 16) = ... >> 16
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },
+ },
+ { // (short)(... >>> 16) = ... >> 16
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },
+ },
+ { // ... << 24 >> 24 = (byte)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 24),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },
+ },
+ { // ... << 16 >>> 16 = (char)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_IUSHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ },
+ },
+ { // ... << 16 >> 16 = (short)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHL),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 16),
+ new SimpleInstruction(InstructionConstants.OP_ISHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ },
+ },
+ { // ... << 32 >> 32 = (long)(int)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 32),
+ new SimpleInstruction(InstructionConstants.OP_LSHL),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 32),
+ new SimpleInstruction(InstructionConstants.OP_LSHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_L2I),
+ new SimpleInstruction(InstructionConstants.OP_I2L),
+ },
+ },
+ { // (int)(... & 0x00000000ffffffffL) = (int)...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_0x00000000ffffffff),
+ new SimpleInstruction(InstructionConstants.OP_LAND),
+ new SimpleInstruction(InstructionConstants.OP_L2I),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_L2I),
+ },
+ },
+ { // (... & 0xffffffff00000000L) >> 32 = ... >> 32
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_0xffffffff00000000),
+ new SimpleInstruction(InstructionConstants.OP_LAND),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 32),
+ new SimpleInstruction(InstructionConstants.OP_LSHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 32),
+ new SimpleInstruction(InstructionConstants.OP_LSHR),
+ },
+ },
+ { // (... & 0xffffffff00000000L) >>> 32 = ... >>> 32
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_0xffffffff00000000),
+ new SimpleInstruction(InstructionConstants.OP_LAND),
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 32),
+ new SimpleInstruction(InstructionConstants.OP_LUSHR),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, 32),
+ new SimpleInstruction(InstructionConstants.OP_LUSHR),
+ },
+ },
+ { // ... += 0 = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_IINC, X, 0),
+ },{
+ // Nothing.
+ },
+ },
+ };
+
+ public static final Instruction[][][] FIELD = new Instruction[][][]
+ {
+ { // getfield/putfield = nothing
+ {
+ new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Y),
+ new ConstantInstruction(InstructionConstants.OP_PUTFIELD, Y),
+ },{
+ // Nothing.
+ },
+ },
+// { // putfield_L/putfield_L = pop2_x1/putfield
+// {
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, FIELD_L),
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, FIELD_L),
+// },{
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new SimpleInstruction(InstructionConstants.OP_POP2),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, FIELD_L),
+// },
+// },
+// { // putfield_D/putfield_D = pop2_x1/putfield
+// {
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, FIELD_D),
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, FIELD_D),
+// },{
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new SimpleInstruction(InstructionConstants.OP_POP2),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, FIELD_D),
+// },
+// },
+// { // putfield/putfield = pop_x1/putfield
+// {
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, Y),
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, Y),
+// },{
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new SimpleInstruction(InstructionConstants.OP_POP),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, Y),
+// },
+// },
+// { // putfield_L/getfield_L = dup2_x1/putfield
+// {
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, FIELD_L),
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// new ConstantInstruction(InstructionConstants.OP_GETFIELD, FIELD_L),
+// },{
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new SimpleInstruction(InstructionConstants.OP_DUP2_X1),
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, FIELD_L),
+// },
+// },
+// { // putfield_D/getfield_D = dup2_x1/putfield
+// {
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, FIELD_D),
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// new ConstantInstruction(InstructionConstants.OP_GETFIELD, FIELD_D),
+// },{
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new SimpleInstruction(InstructionConstants.OP_DUP2_X1),
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, FIELD_D),
+// },
+// },
+// { // putfield/getfield = dup_x1/putfield
+// {
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, Y),
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// new ConstantInstruction(InstructionConstants.OP_GETFIELD, Y),
+// },{
+// new VariableInstruction(InstructionConstants.OP_ALOAD, X),
+// // ...
+// new SimpleInstruction(InstructionConstants.OP_DUP_X1),
+// new ConstantInstruction(InstructionConstants.OP_PUTFIELD, Y),
+// },
+// },
+ { // getstatic/putstatic = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, X),
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // putstatic_L/putstatic_L = pop2/putstatic
+ {
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, FIELD_L),
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, FIELD_L),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, FIELD_L),
+ },
+ },
+ { // putstatic_D/putstatic_D = pop2/putstatic
+ {
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, FIELD_D),
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, FIELD_D),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, FIELD_D),
+ },
+ },
+ { // putstatic/putstatic = pop/putstatic
+ {
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, X),
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, X),
+ },
+ },
+ { // putstatic_L/getstatic_L = dup2/putstatic
+ {
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, FIELD_L),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, FIELD_L),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_DUP2),
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, FIELD_L),
+ },
+ },
+ { // putstatic_D/getstatic_D = dup2/putstatic
+ {
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, FIELD_D),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, FIELD_D),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_DUP2),
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, FIELD_D),
+ },
+ },
+ { // putstatic/getstatic = dup/putstatic
+ {
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, X),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, X),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_PUTSTATIC, X),
+ },
+ },
+ };
+
+ public static final Instruction[][][] CAST = new Instruction[][][]
+ {
+ { // (byte)(byte)... = (byte)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },
+ },
+ { // (byte)(char)... = (byte)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },
+ },
+ { // (byte)(short)... = (byte)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },
+ },
+ { // (char)(char)... = (char)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ },
+ },
+ { // (char)(short)... = (char)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ },
+ },
+ { // (short)(byte)... = (byte)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2B),
+ },
+ },
+ { // (short)(char)... = (short)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_I2C),
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ },
+ },
+ { // (short)(short)... = (short)...
+ {
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_I2S),
+ },
+ },
+ { // (int)(long)... = ...
+ {
+ new SimpleInstruction(InstructionConstants.OP_I2L),
+ new SimpleInstruction(InstructionConstants.OP_L2I),
+ },{
+ // Nothing.
+ },
+ },
+ { // (X)(X)... = (X)...
+ {
+ new ConstantInstruction(InstructionConstants.OP_CHECKCAST, X),
+ new ConstantInstruction(InstructionConstants.OP_CHECKCAST, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_CHECKCAST, X),
+ },
+ },
+ // Not handled correctly in all cases by VMs prior to Java 6...
+// { // (byte)bytes[...] = bytes[...]
+// {
+// new SimpleInstruction(InstructionConstants.OP_BALOAD),
+// new SimpleInstruction(InstructionConstants.OP_I2B),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BALOAD),
+// },
+// },
+// { // (short)bytes[...] = bytes[...]
+// {
+// new SimpleInstruction(InstructionConstants.OP_BALOAD),
+// new SimpleInstruction(InstructionConstants.OP_I2S),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BALOAD),
+// },
+// },
+// { // (char)chars[...] = chars[...]
+// {
+// new SimpleInstruction(InstructionConstants.OP_CALOAD),
+// new SimpleInstruction(InstructionConstants.OP_I2C),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_CALOAD),
+// },
+// },
+// { // (short)shorts[...] = shorts[...]
+// {
+// new SimpleInstruction(InstructionConstants.OP_SALOAD),
+// new SimpleInstruction(InstructionConstants.OP_I2S),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_SALOAD),
+// },
+// },
+// { // bytes[...] = (byte)... = bytes[...] = ...
+// {
+// new SimpleInstruction(InstructionConstants.OP_I2B),
+// new SimpleInstruction(InstructionConstants.OP_BASTORE),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_BASTORE),
+// },
+// },
+// { // chars[...] = (char)... = chars[...] = ...
+// {
+// new SimpleInstruction(InstructionConstants.OP_I2C),
+// new SimpleInstruction(InstructionConstants.OP_CASTORE),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_CASTORE),
+// },
+// },
+// { // shorts[...] = (short)... = shorts[...] = ...
+// {
+// new SimpleInstruction(InstructionConstants.OP_I2S),
+// new SimpleInstruction(InstructionConstants.OP_SASTORE),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_SASTORE),
+// },
+// },
+ };
+
+ public static final Instruction[][][] BRANCH = new Instruction[][][]
+ {
+ { // goto +3 = nothing
+ {
+ new BranchInstruction(InstructionConstants.OP_GOTO, 3),
+ },{
+ // Nothing.
+ },
+ },
+ { // ifeq +3 = pop
+ {
+ new BranchInstruction(InstructionConstants.OP_IFEQ, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // ifne +3 = pop
+ {
+ new BranchInstruction(InstructionConstants.OP_IFNE, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // iflt +3 = pop
+ {
+ new BranchInstruction(InstructionConstants.OP_IFLT, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // ifge +3 = pop
+ {
+ new BranchInstruction(InstructionConstants.OP_IFGE, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // ifgt +3 = pop
+ {
+ new BranchInstruction(InstructionConstants.OP_IFGT, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // ifle +3 = pop
+ {
+ new BranchInstruction(InstructionConstants.OP_IFLE, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // ificmpeq +3 = pop2
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPEQ, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },
+ },
+ { // ificmpne +3 = pop2
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPNE, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },
+ },
+ { // ificmplt +3 = pop2
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },
+ },
+ { // ificmpge +3 = pop2
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },
+ },
+ { // ificmpgt +3 = pop2
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },
+ },
+ { // ificmple +3 = pop2
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },
+ },
+ { // ifacmpeq +3 = pop2
+ {
+ new BranchInstruction(InstructionConstants.OP_IFACMPEQ, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },
+ },
+ { // ifacmpne +3 = pop2
+ {
+ new BranchInstruction(InstructionConstants.OP_IFACMPNE, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP2),
+ },
+ },
+ { // ifnull +3 = pop
+ {
+ new BranchInstruction(InstructionConstants.OP_IFNULL, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // ifnonnull +3 = pop
+ {
+ new BranchInstruction(InstructionConstants.OP_IFNONNULL, 3),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // if (... == 0) = ifeq
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFICMPEQ, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFEQ, X),
+ },
+ },
+ { // if (0 == i) = iload/ifeq
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPEQ, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFEQ, X),
+ },
+ },
+ { // if (0 == i) = getstatic/ifeq
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPEQ, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFEQ, X),
+ },
+ },
+ { // if (0 == i) = getfield/ifeq
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPEQ, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFEQ, X),
+ },
+ },
+ { // if (... != 0) = ifne
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFICMPNE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFNE, X),
+ },
+ },
+ { // if (0 != i) = iload/ifeq
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPNE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFNE, X),
+ },
+ },
+ { // if (0 != i) = getstatic/ifeq
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPNE, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFNE, X),
+ },
+ },
+ { // if (0 != i) = getfield/ifeq
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPNE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFNE, X),
+ },
+ },
+ { // if (... < 0) = iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
+ { // if (... < 1) = ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
+ { // if (0 > i) = iload/iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
+ { // if (1 > i) = iload/ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
+ { // if (0 > i) = getstatic/iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
+ { // if (1 > i) = getstatic/ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
+ { // if (0 > i) = getfield/iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
+ { // if (1 > i) = getfield/ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
+ { // if (... >= 0) = ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
+ { // if (... >= 1) = ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
+ { // if (0 <= i) = iload/ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
+ { // if (1 <= i) = iload/ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
+ { // if (0 <= i) = getstatic/ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
+ { // if (1 <= i) = getstatic/ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
+ { // if (0 <= i) = getfield/ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
+ { // if (1 <= i) = getfield/ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
+ { // if (... > 0) = ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
+ { // if (... > -1) = ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
+ { // if (0 < i) = iload/ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
+ { // if (-1 < i) = iload/ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
+ { // if (0 < i) = getstatic/ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
+ { // if (-1 < i) = getstatic/ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
+ { // if (0 < i) = getfield/ifgt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
+ { // if (-1 < i) = getfield/ifge
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
+ { // if (... <= 0) = ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
+ { // if (... <= -1) = iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
+ { // if (0 >= i) = iload/ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
+ { // if (-1 >= i) = iload/iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
+ { // if (0 >= i) = getstatic/ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
+ { // if (-1 >= i) = getstatic/iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
+ { // if (0 >= i) = getfield/ifle
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
+ { // if (-1 >= i) = getfield/iflt
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_M1),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
+ { // if (... == null) = ifnull
+ {
+ new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
+ new BranchInstruction(InstructionConstants.OP_IFACMPEQ, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFNULL, X),
+ },
+ },
+ { // if (null == a) = aload/ifnull
+ {
+ new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFACMPEQ, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFNULL, X),
+ },
+ },
+ { // if (null == a) = getstatic/ifnull
+ {
+ new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFACMPEQ, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFNULL, X),
+ },
+ },
+ { // if (null == a) = getfield/ifnull
+ {
+ new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFACMPEQ, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFNULL, X),
+ },
+ },
+ { // if (... != null) = ifnonnull
+ {
+ new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
+ new BranchInstruction(InstructionConstants.OP_IFACMPNE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFNONNULL, X),
+ },
+ },
+ { // if (null != a) = aload/ifnonnull
+ {
+ new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFACMPNE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new BranchInstruction(InstructionConstants.OP_IFNONNULL, X),
+ },
+ },
+ { // if (null != a) = getstatic/ifnonnull
+ {
+ new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFACMPNE, X),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_GETSTATIC, Y),
+ new BranchInstruction(InstructionConstants.OP_IFNONNULL, X),
+ },
+ },
+ { // if (null != a) = getfield/ifnonnull
+ {
+ new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFACMPNE, X),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, Y),
+ new ConstantInstruction(InstructionConstants.OP_GETFIELD, Z),
+ new BranchInstruction(InstructionConstants.OP_IFNONNULL, X),
+ },
+ },
+ { // iconst_0/ifeq = goto
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFEQ, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },
+ },
+ { // iconst/ifeq = nothing
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new BranchInstruction(InstructionConstants.OP_IFEQ, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // bipush/ifeq = nothing
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, A),
+ new BranchInstruction(InstructionConstants.OP_IFEQ, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // sipush/ifeq = nothing
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
+ new BranchInstruction(InstructionConstants.OP_IFEQ, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // iconst_0/ifne = nothing
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFNE, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // iconst/ifne = goto
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new BranchInstruction(InstructionConstants.OP_IFNE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },
+ },
+ { // bipush/ifne = goto
+ {
+ new SimpleInstruction(InstructionConstants.OP_BIPUSH, A),
+ new BranchInstruction(InstructionConstants.OP_IFNE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },
+ },
+ { // sipush/ifne = goto
+ {
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, A),
+ new BranchInstruction(InstructionConstants.OP_IFNE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },
+ },
+ { // iconst_0/iflt = nothing
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // iconst_0/ifge = goto
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },
+ },
+ { // iconst_0/ifgt = nothing
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // iconst_0/ifle = goto
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0),
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },
+ },
+ { // aconst_null/ifnull = goto
+ {
+ new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
+ new BranchInstruction(InstructionConstants.OP_IFNULL, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },
+ },
+ { // aconst_null/ifnonnul = nothing
+ {
+ new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
+ new BranchInstruction(InstructionConstants.OP_IFNONNULL, X),
+ },{
+ // Nothing.
+ },
+ },
+ { // ifeq/goto = ifne
+ {
+ new BranchInstruction(InstructionConstants.OP_IFEQ, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFNE, X),
+ },
+ },
+ { // ifne/goto = ifeq
+ {
+ new BranchInstruction(InstructionConstants.OP_IFNE, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFEQ, X),
+ },
+ },
+ { // iflt/goto = ifge
+ {
+ new BranchInstruction(InstructionConstants.OP_IFLT, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFGE, X),
+ },
+ },
+ { // ifge/goto = iflt
+ {
+ new BranchInstruction(InstructionConstants.OP_IFGE, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFLT, X),
+ },
+ },
+ { // ifgt/goto = ifle
+ {
+ new BranchInstruction(InstructionConstants.OP_IFGT, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFLE, X),
+ },
+ },
+ { // ifle/goto = ifgt
+ {
+ new BranchInstruction(InstructionConstants.OP_IFLE, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFGT, X),
+ },
+ },
+ { // ificmpeq/goto = ificmpne
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPEQ, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFICMPNE, X),
+ },
+ },
+ { // ificmpne/goto = ificmpeq
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPNE, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFICMPEQ, X),
+ },
+ },
+ { // ificmplt/goto = ificmpge
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, X),
+ },
+ },
+ { // ificmpge/goto = ificmplt
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPGE, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFICMPLT, X),
+ },
+ },
+ { // ificmpgt/goto = ificmple
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, X),
+ },
+ },
+ { // ificmple/goto = ificmpgt
+ {
+ new BranchInstruction(InstructionConstants.OP_IFICMPLE, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFICMPGT, X),
+ },
+ },
+ { // ifacmpeq/goto = ifacmpne
+ {
+ new BranchInstruction(InstructionConstants.OP_IFACMPEQ, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFACMPNE, X),
+ },
+ },
+ { // ifacmpne/goto = ifacmpeq
+ {
+ new BranchInstruction(InstructionConstants.OP_IFACMPNE, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFACMPEQ, X),
+ },
+ },
+ { // ifnull/goto = ifnonnull
+ {
+ new BranchInstruction(InstructionConstants.OP_IFNULL, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFNONNULL, X),
+ },
+ },
+ { // ifnonnull/goto = ifnull
+ {
+ new BranchInstruction(InstructionConstants.OP_IFNONNULL, 6),
+ new BranchInstruction(InstructionConstants.OP_GOTO, X),
+ },{
+ new BranchInstruction(InstructionConstants.OP_IFNULL, X),
+ },
+ },
+// { // switch (...) { default: ... } = pop/goto ...
+// {
+// new TableSwitchInstruction(InstructionConstants.OP_TABLESWITCH, A, X, Y, 0, new int[0]),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_POP),
+// new BranchInstruction(InstructionConstants.OP_GOTO, A),
+// },
+// },
+// { // switch (...) { default: ... } = pop/goto ...
+// {
+// new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, A, 0, new int[0], new int[0]),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_POP),
+// new BranchInstruction(InstructionConstants.OP_GOTO, A),
+// },
+// },
+ { // switch (...) { case/case/default: ... } = switch (...) { case/default: ... }
+ {
+ new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, A, new int[] { X, Y }, new int[] { A, B }),
+ },{
+ new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, A, new int[] { Y }, new int[] { B }),
+ },
+ },
+ { // switch (...) { case/case/default: ... } = switch (...) { case/default: ... }
+ {
+ new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, B, new int[] { X, Y }, new int[] { A, B }),
+ },{
+ new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, B, new int[] { X }, new int[] { A }),
+ },
+ },
+ { // switch (...) { case/case/case/default: ... } = switch (...) { case/case/default: ... }
+ {
+ new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, A, new int[] { X, Y, Z }, new int[] { A, B, C }),
+ },{
+ new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, A, new int[] { Y, Z }, new int[] { B, C }),
+ },
+ },
+ { // switch (...) { case/case/case/default: ... } = switch (...) { case/case/default: ... }
+ {
+ new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, B, new int[] { X, Y, Z }, new int[] { A, B, C }),
+ },{
+ new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, B, new int[] { X, Z }, new int[] { A, C }),
+ },
+ },
+ { // switch (...) { case/case/case/default: ... } = switch (...) { case/case/default: ... }
+ {
+ new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, C, new int[] { X, Y, Z }, new int[] { A, B, C }),
+ },{
+ new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, C, new int[] { X, Y }, new int[] { A, B }),
+ },
+ },
+// { // switch (...) { case ...: ... default: ... }
+// // = if (... == ...) ... else ...
+// {
+// new TableSwitchInstruction(InstructionConstants.OP_TABLESWITCH, A, X, Y, 1, new int[] { B }),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, X),
+// new BranchInstruction(InstructionConstants.OP_IFICMPNE, A),
+// new BranchInstruction(InstructionConstants.OP_GOTO, B),
+// },
+// },
+// { // switch (...) { case ...: ... default: ... }
+// // = if (... == ...) ... else ...
+// {
+// new LookUpSwitchInstruction(InstructionConstants.OP_LOOKUPSWITCH, A, 1, new int[] { X }, new int[] { B }),
+// },{
+// new SimpleInstruction(InstructionConstants.OP_SIPUSH, X),
+// new BranchInstruction(InstructionConstants.OP_IFICMPNE, A),
+// new BranchInstruction(InstructionConstants.OP_GOTO, B),
+// },
+// }
+ };
+
+ public static final Instruction[][][] STRING = new Instruction[][][]
+ {
+ { // "...".equals("...") = true
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRING_EQUALS),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_ICONST_1),
+ },
+ },
+ { // "...".length() = ...
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRING_LENGTH),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, STRING_A_LENGTH),
+ },
+ },
+ { // String.valueOf(Z) = "....
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, BOOLEAN_A_STRING),
+ },
+ },
+ { // String.valueOf(C) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ },
+ },
+ { // String.valueOf(Cc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ },
+ },
+ { // String.valueOf(I) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ },
+ },
+ { // String.valueOf(Ic) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ },
+ },
+ { // String.valueOf(J) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ },
+ },
+ { // String.valueOf(Jc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ },
+ },
+ { // String.valueOf(F) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ },
+ },
+ { // String.valueOf(Fc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ },
+ },
+ { // String.valueOf(D) = "...."
+ {
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ },
+ },
+ { // String.valueOf(Dc) = "...."
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ },
+ },
+
+ { // new StringBuffer("...").toString() = "..." (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ },
+ },
+ { // new StringBuffer(string).toString() = string (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuffer("...").length() = length
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_LENGTH),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, STRING_A_LENGTH),
+ },
+ },
+ { // new StringBuffer() (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...") (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer()/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...")/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(z)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(c)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(i)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(l)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(f)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(d)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer("...").append(s)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // StringBuffer#toString()/pop = pop
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // StringBuffer#append("") = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_EMPTY),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuffer().append(Z) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, BOOLEAN_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(C) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Cc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(I) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Ic) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(J) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Jc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(F) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Fc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(D) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append(Dc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer().append("...") = new StringBuffer("...")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Z) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(C) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Cc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(I) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Ic) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(J) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Jc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(F) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Fc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(D) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append(Dc) = new StringBuffer("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // new StringBuffer("...").append("...") = new StringBuffer("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Z) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(C) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Cc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(I) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Ic) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(J) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Jc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(F) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Fc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(D) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append(Dc) = StringBuffer#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // StringBuffer#append("...").append("...") = StringBuffer#append("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ },
+ },
+ { // new StringBuffer().append(z).toString() = String.valueOf(z)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_Z),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_Z),
+ },
+ },
+ { // new StringBuffer().append(c).toString() = String.valueOf(c)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_C),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },
+ },
+ { // new StringBuffer().append(i).toString() = String.valueOf(i)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_I),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },
+ },
+ { // new StringBuffer().append(j).toString() = String.valueOf(j)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_J),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },
+ },
+ { // new StringBuffer().append(f).toString() = String.valueOf(f)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_F),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },
+ },
+ { // new StringBuffer().append(d).toString() = String.valueOf(d)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_D),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },
+ },
+ { // new StringBuffer().append(string).toString() = string
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuffer().append(object).toString() = String.valueOf(object)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUFFER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUFFER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_APPEND_OBJECT),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUFFER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_OBJECT),
+ },
+ },
+
+ { // new StringBuilder("...").toString() = "..." (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ },
+ },
+ { // new StringBuilder(string).toString() = string (ignoring identity)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuilder("...").length() = length
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_LENGTH),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_SIPUSH, STRING_A_LENGTH),
+ },
+ },
+ { // new StringBuilder() (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...") (without dup) = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder()/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...")/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(z)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(c)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(i)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(l)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(f)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(d)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder("...").append(s)/pop = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ // Nothing.
+ },
+ },
+ { // StringBuilder#toString()/pop = pop
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },{
+ new SimpleInstruction(InstructionConstants.OP_POP),
+ },
+ },
+ { // StringBuilder#append("") = nothing
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_EMPTY),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ // Nothing.
+ },
+ },
+ { // new StringBuilder().append(Z) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, BOOLEAN_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(C) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Cc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, CHAR_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(I) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Ic) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, INT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(J) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Jc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, LONG_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(F) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Fc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, FLOAT_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(D) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append(Dc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, DOUBLE_A_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder().append("...") = new StringBuilder("...")
+ {
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Z) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(C) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Cc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(I) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Ic) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(J) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Jc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(F) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Fc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(D) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append(Dc) = new StringBuilder("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // new StringBuilder("...").append("...") = new StringBuilder("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Z) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | BOOLEAN_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(C) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Cc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | CHAR_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(I) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_ICONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Ic) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | INT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(J) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_LCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Jc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | LONG_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(F) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_FCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Fc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | FLOAT_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(D) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new SimpleInstruction(InstructionConstants.OP_DCONST_0, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append(Dc) = StringBuilder#append("....")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC2_W, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | DOUBLE_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // StringBuilder#append("...").append("...") = StringBuilder#append("......")
+ {
+ new ConstantInstruction(InstructionConstants.OP_LDC, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_LDC, B),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },{
+ new ConstantInstruction(InstructionConstants.OP_LDC, STRING_A_STRING | STRING_B_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ },
+ },
+ { // new StringBuilder().append(z).toString() = String.valueOf(z)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_Z),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_Z),
+ },
+ },
+ { // new StringBuilder().append(c).toString() = String.valueOf(c)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_C),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_C),
+ },
+ },
+ { // new StringBuilder().append(i).toString() = String.valueOf(i)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_I),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ILOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_I),
+ },
+ },
+ { // new StringBuilder().append(j).toString() = String.valueOf(j)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_J),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_LLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_J),
+ },
+ },
+ { // new StringBuilder().append(f).toString() = String.valueOf(f)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_F),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_FLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_F),
+ },
+ },
+ { // new StringBuilder().append(d).toString() = String.valueOf(d)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_D),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_DLOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_D),
+ },
+ },
+ { // new StringBuilder().append(string).toString() = string
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_STRING),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ },
+ },
+ { // new StringBuilder().append(object).toString() = String.valueOf(object)
+ {
+ new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_STRINGBUILDER),
+ new SimpleInstruction(InstructionConstants.OP_DUP),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_STRINGBUILDER_INIT),
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_APPEND_OBJECT),
+ new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, METHOD_STRINGBUILDER_TOSTRING),
+ },{
+ new VariableInstruction(InstructionConstants.OP_ALOAD, A),
+ new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, METHOD_STRING_VALUEOF_OBJECT),
+ },
+ },
+ };
+
+
+ /**
+ * Creates a new instance of InstructionSequenceConstants, with constants
+ * that reference the given class pools.
+ */
+ public InstructionSequenceConstants(ClassPool programClassPool,
+ ClassPool libraryClassPool)
+ {
+ // Initialize the references in the constants.
+ ClassReferenceInitializer initializer =
+ new ClassReferenceInitializer(programClassPool,
+ libraryClassPool,
+ null, null, null, null);
+
+ // We'll have to create a dummy class for the initializer.
+ ProgramClass dummyClass = new ProgramClass();
+ dummyClass.constantPool = CONSTANTS;
+ dummyClass.u2constantPoolCount = CONSTANTS.length;
+
+ // We'll have to go over the method reference constants and class
+ // constants that don't contain wildcard indices.
+ for (int index = METHOD_STRING_EQUALS; index < NAME_AND_TYPE_I; index++)
+ {
+ dummyClass.constantPoolEntryAccept(index, initializer);
+ }
+ }
+
+
+ /**
+ * Prints out the constants and the instruction sequences.
+ */
+ public static void main(String[] args)
+ {
+ InstructionSequenceConstants constants =
+ new InstructionSequenceConstants(new ClassPool(),
+ new ClassPool());
+
+ Constant[] CONSTANTS = constants.CONSTANTS;
+
+ ProgramClass clazz = new ProgramClass();
+ clazz.constantPool = CONSTANTS;
+
+ ClassPrinter printer = new ClassPrinter();
+
+ for (int index = 0; index < CONSTANTS.length; index++)
+ {
+ System.out.print("["+index+"] ");
+ try
+ {
+ CONSTANTS[index].accept(clazz, printer);
+ }
+ catch (Exception e)
+ {
+ System.out.println("("+e.getClass().getName()+")");
+ }
+ }
+
+ if (CONSTANTS.length != SENTINEL)
+ {
+ throw new IllegalStateException("Constants length ["+CONSTANTS.length+"] different from number of constant names ["+SENTINEL+"]");
+ }
+
+ Instruction[][][] sequences = STRING;
+
+ for (int sequence = 0; sequence < sequences.length; sequence++)
+ {
+ System.out.println();
+ Instruction[] instructions = sequences[sequence][0];
+ for (int index = 0; index < instructions.length; index++)
+ {
+ Instruction instruction = instructions[index];
+ try
+ {
+ instruction.accept(clazz, null, null, index, new ClassPrinter());
+ }
+ catch (Exception e) {}
+ }
+
+ System.out.println("=>");
+ instructions = sequences[sequence][1];
+ for (int index = 0; index < instructions.length; index++)
+ {
+ Instruction instruction = instructions[index];
+ try
+ {
+ instruction.accept(clazz, null, null, index, new ClassPrinter());
+ }
+ catch (Exception e) {}
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequenceReplacer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
new file mode 100644
index 0000000000..ae2496bcd5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
@@ -0,0 +1,422 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.evaluation.BranchTargetFinder;
+
+/**
+ * This InstructionVisitor replaces a given pattern instruction sequence by
+ * another given replacement instruction sequence. The arguments of the
+ * instruction sequences can be wildcards that are matched and replaced.
+ *
+ * @see InstructionSequenceMatcher
+ * @author Eric Lafortune
+ */
+public class InstructionSequenceReplacer
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ public static boolean DEBUG = true;
+ //*/
+
+ public static final int X = InstructionSequenceMatcher.X;
+ public static final int Y = InstructionSequenceMatcher.Y;
+ public static final int Z = InstructionSequenceMatcher.Z;
+
+ public static final int A = InstructionSequenceMatcher.A;
+ public static final int B = InstructionSequenceMatcher.B;
+ public static final int C = InstructionSequenceMatcher.C;
+ public static final int D = InstructionSequenceMatcher.D;
+
+ private static final int BOOLEAN_STRING = 0x1;
+ private static final int CHAR_STRING = 0x2;
+ private static final int INT_STRING = 0x3;
+ private static final int LONG_STRING = 0x4;
+ private static final int FLOAT_STRING = 0x5;
+ private static final int DOUBLE_STRING = 0x6;
+ private static final int STRING_STRING = 0x7;
+
+ public static final int STRING_A_LENGTH = 0x20000000;
+ public static final int BOOLEAN_A_STRING = 0x20000001;
+ public static final int CHAR_A_STRING = 0x20000002;
+ public static final int INT_A_STRING = 0x20000003;
+ public static final int LONG_A_STRING = 0x20000004;
+ public static final int FLOAT_A_STRING = 0x20000005;
+ public static final int DOUBLE_A_STRING = 0x20000006;
+ public static final int STRING_A_STRING = 0x20000007;
+ public static final int BOOLEAN_B_STRING = 0x20000010;
+ public static final int CHAR_B_STRING = 0x20000020;
+ public static final int INT_B_STRING = 0x20000030;
+ public static final int LONG_B_STRING = 0x20000040;
+ public static final int FLOAT_B_STRING = 0x20000050;
+ public static final int DOUBLE_B_STRING = 0x20000060;
+ public static final int STRING_B_STRING = 0x20000070;
+
+
+ private final InstructionSequenceMatcher instructionSequenceMatcher;
+ private final Constant[] patternConstants;
+ private final Instruction[] replacementInstructions;
+ private final BranchTargetFinder branchTargetFinder;
+ private final CodeAttributeEditor codeAttributeEditor;
+ private final InstructionVisitor extraInstructionVisitor;
+
+ private final MyReplacementInstructionFactory replacementInstructionFactory = new MyReplacementInstructionFactory();
+
+
+ /**
+ * Creates a new InstructionSequenceReplacer.
+ * @param patternConstants any constants referenced by the pattern
+ * instruction.
+ * @param patternInstructions the pattern instruction sequence.
+ * @param replacementInstructions the replacement instruction sequence.
+ * @param branchTargetFinder a branch target finder that has been
+ * initialized to indicate branch targets
+ * in the visited code.
+ * @param codeAttributeEditor a code editor that can be used for
+ * accumulating changes to the code.
+ */
+ public InstructionSequenceReplacer(Constant[] patternConstants,
+ Instruction[] patternInstructions,
+ Instruction[] replacementInstructions,
+ BranchTargetFinder branchTargetFinder,
+ CodeAttributeEditor codeAttributeEditor)
+ {
+ this(patternConstants,
+ patternInstructions,
+ replacementInstructions,
+ branchTargetFinder,
+ codeAttributeEditor,
+ null);
+ }
+
+
+ /**
+ * Creates a new InstructionSequenceReplacer.
+ * @param patternConstants any constants referenced by the pattern
+ * instruction.
+ * @param branchTargetFinder a branch target finder that has been
+ * initialized to indicate branch targets
+ * in the visited code.
+ * @param codeAttributeEditor a code editor that can be used for
+ * accumulating changes to the code.
+ * @param extraInstructionVisitor an optional extra visitor for all deleted
+ * load instructions.
+ */
+ public InstructionSequenceReplacer(Constant[] patternConstants,
+ Instruction[] patternInstructions,
+ Instruction[] replacementInstructions,
+ BranchTargetFinder branchTargetFinder,
+ CodeAttributeEditor codeAttributeEditor,
+ InstructionVisitor extraInstructionVisitor)
+ {
+ this.instructionSequenceMatcher = new InstructionSequenceMatcher(patternConstants, patternInstructions);
+ this.patternConstants = patternConstants;
+ this.replacementInstructions = replacementInstructions;
+ this.branchTargetFinder = branchTargetFinder;
+ this.codeAttributeEditor = codeAttributeEditor;
+ this.extraInstructionVisitor = extraInstructionVisitor;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ // Reset the instruction sequence matcher if the instruction is a branch
+ // target or if it has already been modified.
+ if ((branchTargetFinder != null &&
+ branchTargetFinder.isTarget(offset)) ||
+ codeAttributeEditor.isModified(offset))
+ {
+ instructionSequenceMatcher.reset();
+ }
+
+ // Try to match the instruction.
+ instruction.accept(clazz, method, codeAttribute, offset, instructionSequenceMatcher);
+
+ // Did the instruction sequence match and is it still unmodified?
+ if (instructionSequenceMatcher.isMatching() &&
+ matchedInstructionsUnmodified())
+ {
+ if (DEBUG)
+ {
+ System.out.println("InstructionSequenceReplacer: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ System.out.println(" Matched:");
+ for (int index = 0; index < instructionSequenceMatcher.instructionCount(); index++)
+ {
+ int matchedOffset = instructionSequenceMatcher.matchedInstructionOffset(index);
+ System.out.println(" "+InstructionFactory.create(codeAttribute.code, matchedOffset).toString(matchedOffset));
+ }
+ System.out.println(" Replacement:");
+ for (int index = 0; index < replacementInstructions.length; index++)
+ {
+ int matchedOffset = instructionSequenceMatcher.matchedInstructionOffset(index);
+ System.out.println(" "+replacementInstructionFactory.create(clazz, index).shrink().toString(matchedOffset));
+ }
+ }
+
+ // Replace the instruction sequence.
+ for (int index = 0; index < replacementInstructions.length; index++)
+ {
+ codeAttributeEditor.replaceInstruction(instructionSequenceMatcher.matchedInstructionOffset(index),
+ replacementInstructionFactory.create(clazz, index));
+ }
+
+ // Delete any remaining instructions in the from sequence.
+ for (int index = replacementInstructions.length; index < instructionSequenceMatcher.instructionCount(); index++)
+ {
+ codeAttributeEditor.deleteInstruction(instructionSequenceMatcher.matchedInstructionOffset(index));
+ }
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ instruction.accept(clazz,
+ method,
+ codeAttribute,
+ offset,
+ extraInstructionVisitor);
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the matched pattern instructions haven't been modified
+ * before.
+ */
+ private boolean matchedInstructionsUnmodified()
+ {
+ for (int index = 0; index < instructionSequenceMatcher.instructionCount(); index++)
+ {
+ if (codeAttributeEditor.isModified(instructionSequenceMatcher.matchedInstructionOffset(index)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * This class creates replacement instructions for matched sequences, with
+ * any matched arguments filled out.
+ */
+ private class MyReplacementInstructionFactory
+ implements InstructionVisitor
+ {
+ private Instruction replacementInstruction;
+
+
+ /**
+ * Creates the replacement instruction for the given index in the
+ * instruction sequence.
+ */
+ public Instruction create(Clazz clazz, int index)
+ {
+ // Create the instruction.
+ replacementInstructions[index].accept(clazz,
+ null,
+ null,
+ instructionSequenceMatcher.matchedInstructionOffset(index),
+ this);
+
+ // Return it.
+ return replacementInstruction;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ replacementInstruction =
+ new SimpleInstruction(simpleInstruction.opcode,
+ matchedArgument(clazz, simpleInstruction.constant));
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ replacementInstruction =
+ new VariableInstruction(variableInstruction.opcode,
+ instructionSequenceMatcher.matchedArgument(variableInstruction.variableIndex),
+ instructionSequenceMatcher.matchedArgument(variableInstruction.constant));
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ replacementInstruction =
+ new ConstantInstruction(constantInstruction.opcode,
+ matchedConstantIndex((ProgramClass)clazz,
+ constantInstruction.constantIndex),
+ instructionSequenceMatcher.matchedArgument(constantInstruction.constant));
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ replacementInstruction =
+ new BranchInstruction(branchInstruction.opcode,
+ instructionSequenceMatcher.matchedBranchOffset(offset,
+ branchInstruction.branchOffset));
+ }
+
+
+ public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
+ {
+ replacementInstruction =
+ new TableSwitchInstruction(tableSwitchInstruction.opcode,
+ instructionSequenceMatcher.matchedBranchOffset(offset, tableSwitchInstruction.defaultOffset),
+ instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.lowCase),
+ instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.highCase),
+ instructionSequenceMatcher.matchedJumpOffsets(offset,
+ tableSwitchInstruction.jumpOffsets));
+
+ }
+
+
+ public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
+ {
+ replacementInstruction =
+ new LookUpSwitchInstruction(lookUpSwitchInstruction.opcode,
+ instructionSequenceMatcher.matchedBranchOffset(offset, lookUpSwitchInstruction.defaultOffset),
+ instructionSequenceMatcher.matchedArguments(lookUpSwitchInstruction.cases),
+ instructionSequenceMatcher.matchedJumpOffsets(offset, lookUpSwitchInstruction.jumpOffsets));
+ }
+
+
+ /**
+ * Returns the matched argument for the given pattern argument.
+ */
+ private int matchedArgument(Clazz clazz, int argument)
+ {
+ // Special case: do we have to compute the string length?
+ if (argument == STRING_A_LENGTH)
+ {
+ // Return the string length.
+ return clazz.getStringString(instructionSequenceMatcher.matchedArgument(A)).length();
+ }
+
+ // Otherwise, just return the matched argument.
+ return instructionSequenceMatcher.matchedArgument(argument);
+ }
+
+
+ /**
+ * Returns the matched or newly created constant index for the given
+ * pattern constant index.
+ */
+ private int matchedConstantIndex(ProgramClass programClass, int constantIndex)
+ {
+ // Special case: do we have to create a concatenated string?
+ if (constantIndex >= BOOLEAN_A_STRING &&
+ constantIndex <= (STRING_A_STRING | STRING_B_STRING))
+ {
+ // Create a new string constant and return its index.
+ return new ConstantPoolEditor(programClass).addStringConstant(
+ argumentAsString(programClass, constantIndex & 0xf, A) +
+ argumentAsString(programClass, (constantIndex >>> 4) & 0xf, B),
+ null,
+ null);
+ }
+
+ int matchedConstantIndex =
+ instructionSequenceMatcher.matchedConstantIndex(constantIndex);
+
+ // Do we have a matched constant index?
+ if (matchedConstantIndex > 0)
+ {
+ // Return its index.
+ return matchedConstantIndex;
+ }
+
+ // Otherwise, we still have to create a new constant.
+ // This currently only works for constants without any wildcards.
+ ProgramClass dummyClass = new ProgramClass();
+ dummyClass.constantPool = patternConstants;
+
+ return new ConstantAdder(programClass).addConstant(dummyClass, constantIndex);
+ }
+
+
+ private String argumentAsString(ProgramClass programClass,
+ int valueType,
+ int argument)
+ {
+ switch (valueType)
+ {
+ case BOOLEAN_STRING:
+ return Boolean.toString((instructionSequenceMatcher.wasConstant(argument) ?
+ ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument)) != 0);
+
+ case CHAR_STRING:
+ return Character.toString((char)(instructionSequenceMatcher.wasConstant(argument) ?
+ ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument)));
+
+ case INT_STRING:
+ return Integer.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case LONG_STRING:
+ return Long.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((LongConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case FLOAT_STRING:
+ return Float.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((FloatConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case DOUBLE_STRING:
+ return Double.toString(instructionSequenceMatcher.wasConstant(argument) ?
+ ((DoubleConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
+ instructionSequenceMatcher.matchedArgument(argument));
+
+ case STRING_STRING:
+ return
+ programClass.getStringString(instructionSequenceMatcher.matchedConstantIndex(argument));
+
+ default:
+ return "";
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequencesReplacer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
new file mode 100644
index 0000000000..3b52654e0f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
@@ -0,0 +1,139 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.constant.Constant;
+import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.instruction.Instruction;
+import proguard.classfile.instruction.visitor.*;
+import proguard.evaluation.BranchTargetFinder;
+
+/**
+ * This InstructionVisitor replaces multiple instruction sequences at once.
+ *
+ * @see InstructionSequenceReplacer
+ * @author Eric Lafortune
+ */
+public class InstructionSequencesReplacer
+extends MultiInstructionVisitor
+implements InstructionVisitor
+{
+ private static final int PATTERN_INDEX = 0;
+ private static final int REPLACEMENT_INDEX = 1;
+
+
+ /**
+ * Creates a new InstructionSequencesReplacer.
+ * @param patternConstants any constants referenced by the pattern
+ * instruction.
+ * @param instructionSequences the instruction sequences to be replaced,
+ * with subsequently the sequence pair index,
+ * the patten/replacement index (0 or 1),
+ * and the instruction index in the sequence.
+ * @param branchTargetFinder a branch target finder that has been
+ * initialized to indicate branch targets
+ * in the visited code.
+ * @param codeAttributeEditor a code editor that can be used for
+ * accumulating changes to the code.
+ */
+ public InstructionSequencesReplacer(Constant[] patternConstants,
+ Instruction[][][] instructionSequences,
+ BranchTargetFinder branchTargetFinder,
+ CodeAttributeEditor codeAttributeEditor)
+ {
+ this(patternConstants,
+ instructionSequences,
+ branchTargetFinder,
+ codeAttributeEditor,
+ null);
+ }
+
+
+ /**
+ * Creates a new InstructionSequenceReplacer.
+ * @param patternConstants any constants referenced by the pattern
+ * instruction.
+ * @param instructionSequences the instruction sequences to be replaced,
+ * with subsequently the sequence pair index,
+ * the patten/replacement index (0 or 1),
+ * and the instruction index in the sequence.
+ * @param branchTargetFinder a branch target finder that has been
+ * initialized to indicate branch targets
+ * in the visited code.
+ * @param codeAttributeEditor a code editor that can be used for
+ * accumulating changes to the code.
+ * @param extraInstructionVisitor an optional extra visitor for all deleted
+ * load instructions.
+ */
+ public InstructionSequencesReplacer(Constant[] patternConstants,
+ Instruction[][][] instructionSequences,
+ BranchTargetFinder branchTargetFinder,
+ CodeAttributeEditor codeAttributeEditor,
+ InstructionVisitor extraInstructionVisitor)
+ {
+ super(createInstructionSequenceReplacers(patternConstants,
+ instructionSequences,
+ branchTargetFinder,
+ codeAttributeEditor,
+ extraInstructionVisitor));
+ }
+
+
+ /**
+ * Creates an array of InstructionSequenceReplacer instances.
+ * @param patternConstants any constants referenced by the pattern
+ * instruction.
+ * @param instructionSequences the instruction sequences to be replaced,
+ * with subsequently the sequence pair index,
+ * the from/to index (0 or 1), and the
+ * instruction index in the sequence.
+ * @param branchTargetFinder a branch target finder that has been
+ * initialized to indicate branch targets
+ * in the visited code.
+ * @param codeAttributeEditor a code editor that can be used for
+ * accumulating changes to the code.
+ * @param extraInstructionVisitor an optional extra visitor for all deleted
+ * load instructions.
+ */
+ private static InstructionVisitor[] createInstructionSequenceReplacers(Constant[] patternConstants,
+ Instruction[][][] instructionSequences,
+ BranchTargetFinder branchTargetFinder,
+ CodeAttributeEditor codeAttributeEditor,
+ InstructionVisitor extraInstructionVisitor)
+ {
+ InstructionVisitor[] instructionSequenceReplacers =
+ new InstructionSequenceReplacer[instructionSequences.length];
+
+ for (int index = 0; index < instructionSequenceReplacers.length; index++)
+ {
+ Instruction[][] instructionSequencePair = instructionSequences[index];
+ instructionSequenceReplacers[index] =
+ new InstructionSequenceReplacer(patternConstants,
+ instructionSequencePair[PATTERN_INDEX],
+ instructionSequencePair[REPLACEMENT_INDEX],
+ branchTargetFinder,
+ codeAttributeEditor,
+ extraInstructionVisitor);
+ }
+
+ return instructionSequenceReplacers;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/LineNumberLinearizer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/LineNumberLinearizer.java
new file mode 100644
index 0000000000..f7bba03633
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/LineNumberLinearizer.java
@@ -0,0 +1,250 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+import java.util.*;
+
+/**
+ * This ClassVisitor disambiguates line numbers, in the classes that it
+ * visits. It shifts line numbers that originate from different classes
+ * (e.g. due to method inlining or class merging) to blocks that don't
+ * overlap with the main line numbers and with each other. The line numbers
+ * then uniquely identify the inlined and merged code in the classes.
+ *
+ * @author Eric Lafortune
+ */
+public class LineNumberLinearizer
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor,
+ LineNumberInfoVisitor
+{
+ private static final boolean DEBUG = false;
+
+ public static final int SHIFT_ROUNDING = 1000;
+ private static final int SHIFT_ROUNDING_LIMIT = 50000;
+
+
+ private Stack enclosingLineNumbers = new Stack();
+ private LineNumberInfo previousLineNumberInfo;
+ private int highestUsedLineNumber;
+ private int currentLineNumberShift;
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Find the highest line number in the entire class.
+ LineNumberRangeFinder lineNumberRangeFinder =
+ new LineNumberRangeFinder();
+
+ programClass.methodsAccept(new AllAttributeVisitor(true,
+ new AllLineNumberInfoVisitor(
+ lineNumberRangeFinder)));
+
+ // Are there any inlined line numbers?
+ if (lineNumberRangeFinder.hasSource())
+ {
+ // Remember the minimum initial shift.
+ highestUsedLineNumber = lineNumberRangeFinder.getHighestLineNumber();
+
+ // Shift the inlined line numbers.
+ programClass.methodsAccept(this);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ programMethod.attributesAccept(programClass, this);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ if (DEBUG)
+ {
+ System.out.println("LineNumberLinearizer ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]:");
+ }
+
+ enclosingLineNumbers.clear();
+ previousLineNumberInfo = null;
+
+ // Process all line numbers.
+ lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ // Implementations for LineNumberInfoVisitor.
+
+ public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
+ {
+ String source = lineNumberInfo.getSource();
+
+ if (DEBUG)
+ {
+ System.out.print(" [" + lineNumberInfo.u2startPC + "] line " + lineNumberInfo.u2lineNumber + (source == null ? "" : " [" + source + "]"));
+ }
+
+ // Is it an inlined line number?
+ if (source != null)
+ {
+ ExtendedLineNumberInfo extendedLineNumberInfo =
+ (ExtendedLineNumberInfo)lineNumberInfo;
+
+ int lineNumber = extendedLineNumberInfo.u2lineNumber;
+
+ // Are we entering or exiting a new inlined block?
+ if (previousLineNumberInfo == null ||
+ previousLineNumberInfo.getSource() != source)
+ {
+ // Are we entering a new inlined block?
+ if (lineNumber != MethodInliner.INLINED_METHOD_END_LINE_NUMBER)
+ {
+ // Remember information about the inlined block.
+ enclosingLineNumbers.push(previousLineNumberInfo != null ?
+ new MyLineNumberBlock(currentLineNumberShift,
+ previousLineNumberInfo.u2lineNumber,
+ previousLineNumberInfo.getSource()) :
+ new MyLineNumberBlock(0, 0, null));
+
+ // Parse the end line number from the source string,
+ // so we know how large a block this will be.
+ int separatorIndex1 = source.indexOf(':');
+ int separatorIndex2 = source.indexOf(':', separatorIndex1 + 1);
+
+ int startLineNumber = Integer.parseInt(source.substring(separatorIndex1 + 1, separatorIndex2));
+ int endLineNumber = Integer.parseInt(source.substring(separatorIndex2 + 1));
+
+ // Start shifting, if necessary, so the block ends up beyond
+ // the highest used line number. We're striving for rounded
+ // shifts, unless we've reached a given limit, to avoid
+ // running out of line numbers too quickly.
+ currentLineNumberShift =
+ highestUsedLineNumber > SHIFT_ROUNDING_LIMIT ?
+ highestUsedLineNumber - startLineNumber + 1 :
+ startLineNumber > highestUsedLineNumber ? 0 :
+ (highestUsedLineNumber - startLineNumber + SHIFT_ROUNDING)
+ / SHIFT_ROUNDING * SHIFT_ROUNDING;
+
+ highestUsedLineNumber = endLineNumber + currentLineNumberShift;
+
+ if (DEBUG)
+ {
+ System.out.print(" (enter with shift "+currentLineNumberShift+")");
+ }
+
+ // Apply the shift.
+ lineNumberInfo.u2lineNumber += currentLineNumberShift;
+ }
+
+ // TODO: There appear to be cases where the stack is empty at this point, so we've added a check.
+ else if (enclosingLineNumbers.isEmpty())
+ {
+ if (DEBUG)
+ {
+ System.err.println("Problem linearizing line numbers for optimized code ("+clazz.getName()+"."+method.getName(clazz)+")");
+ }
+ }
+
+ // Are we exiting an inlined block?
+ else
+ {
+ // Pop information about the enclosing line number.
+ MyLineNumberBlock lineNumberBlock =
+ (MyLineNumberBlock)enclosingLineNumbers.pop();
+
+ // Set this end of the block to the line at which it was
+ // inlined.
+ extendedLineNumberInfo.u2lineNumber = lineNumberBlock.enclosingLineNumber;
+ extendedLineNumberInfo.source = lineNumberBlock.enclosingSource;
+
+ // Reset the shift to the shift of the block.
+ currentLineNumberShift = lineNumberBlock.lineNumberShift;
+
+ if (DEBUG)
+ {
+ System.out.print(" (exit to shift "+currentLineNumberShift+")");
+ }
+ }
+ }
+ else
+ {
+ if (DEBUG)
+ {
+ System.out.print(" (apply shift "+currentLineNumberShift+")");
+ }
+
+ // Apply the shift.
+ lineNumberInfo.u2lineNumber += currentLineNumberShift;
+ }
+ }
+
+ previousLineNumberInfo = lineNumberInfo;
+
+ if (DEBUG)
+ {
+ System.out.println(" -> line " + lineNumberInfo.u2lineNumber);
+ }
+ }
+
+
+ /**
+ * This class represents a block of line numbers that originates from the
+ * same inlined method.
+ */
+ private static class MyLineNumberBlock
+ {
+ public final int lineNumberShift;
+ public final int enclosingLineNumber;
+ public final String enclosingSource;
+
+ public MyLineNumberBlock(int lineNumberShift,
+ int enclosingLineNumber,
+ String enclosingSource)
+ {
+ this.lineNumberShift = lineNumberShift;
+ this.enclosingLineNumber = enclosingLineNumber;
+ this.enclosingSource = enclosingSource;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MemberPrivatizer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MemberPrivatizer.java
new file mode 100644
index 0000000000..223ab59215
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MemberPrivatizer.java
@@ -0,0 +1,103 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.editor.MethodInvocationFixer;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.info.NonPrivateMemberMarker;
+
+/**
+ * This MemberVisitor makes all class members that it visits private, unless
+ * they have been marked by a NonPrivateMemberMarker. The invocations of
+ * privatized methods still have to be fixed.
+ *
+ * @see NonPrivateMemberMarker
+ * @see MethodInvocationFixer
+ * @author Eric Lafortune
+ */
+public class MemberPrivatizer
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final MemberVisitor extraMemberVisitor;
+
+
+ /**
+ * Creates a new MemberPrivatizer.
+ */
+ public MemberPrivatizer()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new MemberPrivatizer.
+ * @param extraMemberVisitor an optional extra visitor for all privatized
+ * class members.
+ */
+ public MemberPrivatizer(MemberVisitor extraMemberVisitor)
+ {
+ this.extraMemberVisitor = extraMemberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Is the field unmarked?
+ if (NonPrivateMemberMarker.canBeMadePrivate(programField))
+ {
+ // Make the field private.
+ programField.u2accessFlags =
+ AccessUtil.replaceAccessFlags(programField.u2accessFlags,
+ ClassConstants.ACC_PRIVATE);
+
+ // Visit the field, if required.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Is the method unmarked?
+ if (NonPrivateMemberMarker.canBeMadePrivate(programMethod))
+ {
+ // Make the method private and no longer final.
+ programMethod.u2accessFlags =
+ AccessUtil.replaceAccessFlags(programMethod.u2accessFlags,
+ ClassConstants.ACC_PRIVATE);
+
+ // Visit the method, if required.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MethodFinalizer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MethodFinalizer.java
new file mode 100644
index 0000000000..9ad158520c
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MethodFinalizer.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.KeepMarker;
+
+/**
+ * This <code>MemberVisitor</code> makes the program methods that it visits
+ * final, if possible.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodFinalizer
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ private final MemberVisitor extraMemberVisitor;
+
+ private final MemberFinder memberFinder = new MemberFinder();
+
+
+ /**
+ * Creates a new ClassFinalizer.
+ */
+ public MethodFinalizer()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new ClassFinalizer.
+ * @param extraMemberVisitor an optional extra visitor for all finalized
+ * methods.
+ */
+ public MethodFinalizer(MemberVisitor extraMemberVisitor)
+ {
+ this.extraMemberVisitor = extraMemberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ String name = programMethod.getName(programClass);
+
+ // If the method is not already private/static/final/abstract,
+ // and it is not a constructor,
+ // and its class is final,
+ // or it is not being kept and it is not overridden,
+ // then make it final.
+ if ((programMethod.u2accessFlags & (ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC |
+ ClassConstants.ACC_FINAL |
+ ClassConstants.ACC_ABSTRACT)) == 0 &&
+ !name.equals(ClassConstants.METHOD_NAME_INIT) &&
+ ((programClass.u2accessFlags & ClassConstants.ACC_FINAL) != 0 ||
+ (!KeepMarker.isKept(programMethod) &&
+ (programClass.subClasses == null ||
+ !memberFinder.isOverriden(programClass, programMethod)))))
+ {
+ programMethod.u2accessFlags |= ClassConstants.ACC_FINAL;
+
+ // Visit the method, if required.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MethodInliner.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MethodInliner.java
new file mode 100644
index 0000000000..13d1e9963d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/MethodInliner.java
@@ -0,0 +1,712 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+import proguard.optimize.KeepMarker;
+import proguard.optimize.info.*;
+
+import java.util.*;
+
+/**
+ * This AttributeVisitor inlines short methods or methods that are only invoked
+ * once, in the code attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodInliner
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor,
+ LineNumberInfoVisitor
+{
+ static final int METHOD_DUMMY_START_LINE_NUMBER = 0;
+ static final int INLINED_METHOD_END_LINE_NUMBER = -1;
+
+ private static final int MAXIMUM_INLINED_CODE_LENGTH = Integer.parseInt(System.getProperty("maximum.inlined.code.length", "8"));
+ private static final int MAXIMUM_RESULTING_CODE_LENGTH_JSE = Integer.parseInt(System.getProperty("maximum.resulting.code.length", "7000"));
+ private static final int MAXIMUM_RESULTING_CODE_LENGTH_JME = Integer.parseInt(System.getProperty("maximum.resulting.code.length", "2000"));
+
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = true;
+ //*/
+
+
+ private final boolean microEdition;
+ private final boolean allowAccessModification;
+ private final boolean inlineSingleInvocations;
+ private final InstructionVisitor extraInlinedInvocationVisitor;
+
+ private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
+ private final AccessMethodMarker accessMethodMarker = new AccessMethodMarker();
+ private final CatchExceptionMarker catchExceptionMarker = new CatchExceptionMarker();
+ private final StackSizeComputer stackSizeComputer = new StackSizeComputer();
+
+ private ProgramClass targetClass;
+ private ProgramMethod targetMethod;
+ private ConstantAdder constantAdder;
+ private ExceptionInfoAdder exceptionInfoAdder;
+ private int estimatedResultingCodeLength;
+ private boolean inlining;
+ private Stack inliningMethods = new Stack();
+ private boolean emptyInvokingStack;
+ private int uninitializedObjectCount;
+ private int variableOffset;
+ private boolean inlined;
+ private boolean inlinedAny;
+ private boolean copiedLineNumbers;
+ private String source;
+ private int minimumLineNumberIndex;
+
+
+ /**
+ * Creates a new MethodInliner.
+ * @param microEdition indicates whether the resulting code is
+ * targeted at Java Micro Edition.
+ * @param allowAccessModification indicates whether the access modifiers of
+ * classes and class members can be changed
+ * in order to inline methods.
+ * @param inlineSingleInvocations indicates whether the single invocations
+ * should be inlined, or, alternatively,
+ * short methods.
+ */
+ public MethodInliner(boolean microEdition,
+ boolean allowAccessModification,
+ boolean inlineSingleInvocations)
+ {
+ this(microEdition,
+ allowAccessModification,
+ inlineSingleInvocations,
+ null);
+ }
+
+
+ /**
+ * Creates a new MethodInliner.
+ * @param microEdition indicates whether the resulting code is
+ * targeted at Java Micro Edition.
+ * @param allowAccessModification indicates whether the access modifiers of
+ * classes and class members can be changed
+ * in order to inline methods.
+ * @param inlineSingleInvocations indicates whether the single invocations
+ * should be inlined, or, alternatively,
+ * short methods.
+ * @param extraInlinedInvocationVisitor an optional extra visitor for all
+ * inlined invocation instructions.
+ */
+ public MethodInliner(boolean microEdition,
+ boolean allowAccessModification,
+ boolean inlineSingleInvocations,
+ InstructionVisitor extraInlinedInvocationVisitor)
+ {
+ this.microEdition = microEdition;
+ this.allowAccessModification = allowAccessModification;
+ this.inlineSingleInvocations = inlineSingleInvocations;
+ this.extraInlinedInvocationVisitor = extraInlinedInvocationVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // TODO: Remove this when the method inliner has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while inlining method:");
+ System.err.println(" Target class = ["+targetClass.getName()+"]");
+ System.err.println(" Target method = ["+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]");
+ if (inlining)
+ {
+ System.err.println(" Inlined class = ["+clazz.getName()+"]");
+ System.err.println(" Inlined method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ }
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+
+ ex.printStackTrace();
+ System.err.println("Not inlining this method");
+
+ if (DEBUG)
+ {
+ targetMethod.accept(targetClass, new ClassPrinter());
+ if (inlining)
+ {
+ method.accept(clazz, new ClassPrinter());
+ }
+
+ throw ex;
+ }
+ }
+ }
+
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (!inlining)
+ {
+// codeAttributeComposer.DEBUG = DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ targetClass = (ProgramClass)clazz;
+ targetMethod = (ProgramMethod)method;
+ constantAdder = new ConstantAdder(targetClass);
+ exceptionInfoAdder = new ExceptionInfoAdder(targetClass, codeAttributeComposer);
+ estimatedResultingCodeLength = codeAttribute.u4codeLength;
+ inliningMethods.clear();
+ uninitializedObjectCount = method.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT) ? 1 : 0;
+ inlinedAny = false;
+ codeAttributeComposer.reset();
+ stackSizeComputer.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Append the body of the code.
+ copyCode(clazz, method, codeAttribute);
+
+ targetClass = null;
+ targetMethod = null;
+ constantAdder = null;
+
+ // Update the code attribute if any code has been inlined.
+ if (inlinedAny)
+ {
+ codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Update the accessing flags.
+ codeAttribute.instructionsAccept(clazz, method, accessMethodMarker);
+
+ // Update the exception catching flags.
+ catchExceptionMarker.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
+
+ // Only inline the method if it is invoked once or if it is short.
+ else if ((inlineSingleInvocations ?
+ MethodInvocationMarker.getInvocationCount(method) == 1 :
+ codeAttribute.u4codeLength <= MAXIMUM_INLINED_CODE_LENGTH) &&
+ estimatedResultingCodeLength + codeAttribute.u4codeLength <
+ (microEdition ?
+ MAXIMUM_RESULTING_CODE_LENGTH_JME :
+ MAXIMUM_RESULTING_CODE_LENGTH_JSE))
+ {
+ if (DEBUG)
+ {
+ System.out.println("MethodInliner: inlining ["+
+ clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] in ["+
+ targetClass.getName()+"."+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]");
+ }
+
+ // Ignore the removal of the original method invocation,
+ // the addition of the parameter setup, and
+ // the modification of a few inlined instructions.
+ estimatedResultingCodeLength += codeAttribute.u4codeLength;
+
+ // Append instructions to store the parameters.
+ storeParameters(clazz, method);
+
+ // Inline the body of the code.
+ copyCode(clazz, method, codeAttribute);
+
+ inlined = true;
+ inlinedAny = true;
+ }
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ // Remember the source if we're inlining a method.
+ source = inlining ?
+ clazz.getName() + '.' +
+ method.getName(clazz) +
+ method.getDescriptor(clazz) + ':' +
+ lineNumberTableAttribute.getLowestLineNumber() + ':' +
+ lineNumberTableAttribute.getHighestLineNumber() :
+ null;
+
+ // Insert all line numbers, possibly partly before previously inserted
+ // line numbers.
+ lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
+
+ copiedLineNumbers = true;
+ }
+
+
+ /**
+ * Appends instructions to pop the parameters for the given method, storing
+ * them in new local variables.
+ */
+ private void storeParameters(Clazz clazz, Method method)
+ {
+ String descriptor = method.getDescriptor(clazz);
+
+ boolean isStatic =
+ (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0;
+
+ // Count the number of parameters, taking into account their categories.
+ int parameterCount = ClassUtil.internalMethodParameterCount(descriptor);
+ int parameterSize = ClassUtil.internalMethodParameterSize(descriptor);
+ int parameterOffset = isStatic ? 0 : 1;
+
+ // Store the parameter types.
+ String[] parameterTypes = new String[parameterSize];
+
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(descriptor);
+
+ for (int parameterIndex = 0; parameterIndex < parameterSize; parameterIndex++)
+ {
+ String parameterType = internalTypeEnumeration.nextType();
+ parameterTypes[parameterIndex] = parameterType;
+ if (ClassUtil.internalTypeSize(parameterType) == 2)
+ {
+ parameterIndex++;
+ }
+ }
+
+ codeAttributeComposer.beginCodeFragment(parameterSize+1);
+
+ // Go over the parameter types backward, storing the stack entries
+ // in their corresponding variables.
+ for (int parameterIndex = parameterSize-1; parameterIndex >= 0; parameterIndex--)
+ {
+ String parameterType = parameterTypes[parameterIndex];
+ if (parameterType != null)
+ {
+ byte opcode;
+ switch (parameterType.charAt(0))
+ {
+ case ClassConstants.TYPE_BOOLEAN:
+ case ClassConstants.TYPE_BYTE:
+ case ClassConstants.TYPE_CHAR:
+ case ClassConstants.TYPE_SHORT:
+ case ClassConstants.TYPE_INT:
+ opcode = InstructionConstants.OP_ISTORE;
+ break;
+
+ case ClassConstants.TYPE_LONG:
+ opcode = InstructionConstants.OP_LSTORE;
+ break;
+
+ case ClassConstants.TYPE_FLOAT:
+ opcode = InstructionConstants.OP_FSTORE;
+ break;
+
+ case ClassConstants.TYPE_DOUBLE:
+ opcode = InstructionConstants.OP_DSTORE;
+ break;
+
+ default:
+ opcode = InstructionConstants.OP_ASTORE;
+ break;
+ }
+
+ codeAttributeComposer.appendInstruction(parameterSize-parameterIndex-1,
+ new VariableInstruction(opcode, variableOffset + parameterOffset + parameterIndex));
+ }
+ }
+
+ // Put the 'this' reference in variable 0 (plus offset).
+ if (!isStatic)
+ {
+ codeAttributeComposer.appendInstruction(parameterSize,
+ new VariableInstruction(InstructionConstants.OP_ASTORE, variableOffset));
+ }
+
+ codeAttributeComposer.endCodeFragment();
+ }
+
+
+ /**
+ * Appends the code of the given code attribute.
+ */
+ private void copyCode(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // The code may expand, due to expanding constant and variable
+ // instructions.
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
+
+ // Copy the instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
+
+ // Append a label just after the code.
+ codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
+
+ // Copy the exceptions.
+ codeAttribute.exceptionsAccept(clazz, method, exceptionInfoAdder);
+
+ // Copy the line numbers.
+ copiedLineNumbers = false;
+
+ // The line numbers need to be inserted sequentially.
+ minimumLineNumberIndex = 0;
+
+ codeAttribute.attributesAccept(clazz, method, this);
+
+ // Make sure we at least have some entry at the start of the method.
+ if (!copiedLineNumbers)
+ {
+ String source = inlining ?
+ clazz.getName() + '.' +
+ method.getName(clazz) +
+ method.getDescriptor(clazz) +
+ ":0:0" :
+ null;
+
+ minimumLineNumberIndex =
+ codeAttributeComposer.insertLineNumber(minimumLineNumberIndex,
+ new ExtendedLineNumberInfo(0,
+ METHOD_DUMMY_START_LINE_NUMBER,
+ source)) + 1;
+ }
+
+ // Add a marker at the end of an inlined method.
+ // The marker will be corrected in LineNumberLinearizer,
+ // so it points to the line of the enclosing method.
+ if (inlining)
+ {
+ String source =
+ clazz.getName() + '.' +
+ method.getName(clazz) +
+ method.getDescriptor(clazz) +
+ ":0:0";
+
+ minimumLineNumberIndex =
+ codeAttributeComposer.insertLineNumber(minimumLineNumberIndex,
+ new ExtendedLineNumberInfo(codeAttribute.u4codeLength,
+ INLINED_METHOD_END_LINE_NUMBER,
+ source)) + 1;
+ }
+
+ codeAttributeComposer.endCodeFragment();
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ codeAttributeComposer.appendInstruction(offset, instruction);
+ }
+
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ // Are we inlining this instruction?
+ if (inlining)
+ {
+ // Replace any return instructions by branches to the end of the code.
+ switch (simpleInstruction.opcode)
+ {
+ case InstructionConstants.OP_IRETURN:
+ case InstructionConstants.OP_LRETURN:
+ case InstructionConstants.OP_FRETURN:
+ case InstructionConstants.OP_DRETURN:
+ case InstructionConstants.OP_ARETURN:
+ case InstructionConstants.OP_RETURN:
+ // Are we not at the last instruction?
+ if (offset < codeAttribute.u4codeLength-1)
+ {
+ // Replace the return instruction by a branch instruction.
+ Instruction branchInstruction =
+ new BranchInstruction(InstructionConstants.OP_GOTO_W,
+ codeAttribute.u4codeLength - offset);
+
+ codeAttributeComposer.appendInstruction(offset,
+ branchInstruction);
+ }
+ else
+ {
+ // Just leave out the instruction, but put in a label,
+ // for the sake of any other branch instructions.
+ codeAttributeComposer.appendLabel(offset);
+ }
+
+ return;
+ }
+ }
+
+ codeAttributeComposer.appendInstruction(offset, simpleInstruction);
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ // Are we inlining this instruction?
+ if (inlining)
+ {
+ // Update the variable index.
+ variableInstruction.variableIndex += variableOffset;
+ }
+
+ codeAttributeComposer.appendInstruction(offset, variableInstruction);
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ // Is it a method invocation?
+ switch (constantInstruction.opcode)
+ {
+ case InstructionConstants.OP_NEW:
+ uninitializedObjectCount++;
+ break;
+
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ // See if we can inline it.
+ inlined = false;
+
+ // Append a label, in case the invocation will be inlined.
+ codeAttributeComposer.appendLabel(offset);
+
+ emptyInvokingStack =
+ !inlining &&
+ stackSizeComputer.isReachable(offset) &&
+ stackSizeComputer.getStackSizeAfter(offset) == 0;
+
+ variableOffset += codeAttribute.u2maxLocals;
+
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+
+ variableOffset -= codeAttribute.u2maxLocals;
+
+ // Was the method inlined?
+ if (inlined)
+ {
+ if (extraInlinedInvocationVisitor != null)
+ {
+ extraInlinedInvocationVisitor.visitConstantInstruction(clazz, method, codeAttribute, offset, constantInstruction);
+ }
+
+ // The invocation itself is no longer necessary.
+ return;
+ }
+
+ break;
+ }
+
+ // Are we inlining this instruction?
+ if (inlining)
+ {
+ // Make sure the constant is present in the constant pool of the
+ // target class.
+ constantInstruction.constantIndex =
+ constantAdder.addConstant(clazz, constantInstruction.constantIndex);
+ }
+
+ codeAttributeComposer.appendInstruction(offset, constantInstruction);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ refConstant.referencedMemberAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz Clazz, Member member) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ int accessFlags = programMethod.getAccessFlags();
+
+ if (// Don't inline methods that must be preserved.
+ !KeepMarker.isKept(programMethod) &&
+
+ // Only inline the method if it is private, static, or final.
+ // This currently precludes default interface methods, because
+ // they can't be final.
+ (accessFlags & (ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC |
+ ClassConstants.ACC_FINAL)) != 0 &&
+
+ // Only inline the method if it is not synchronized, etc.
+ (accessFlags & (ClassConstants.ACC_SYNCHRONIZED |
+ ClassConstants.ACC_NATIVE |
+ ClassConstants.ACC_ABSTRACT)) == 0 &&
+
+ // Don't inline an <init> method, except in an <init> method in the
+ // same class.
+// (!programMethod.getName(programClass).equals(ClassConstants.METHOD_NAME_INIT) ||
+// (programClass.equals(targetClass) &&
+// targetMethod.getName(targetClass).equals(ClassConstants.METHOD_NAME_INIT))) &&
+ !programMethod.getName(programClass).equals(ClassConstants.METHOD_NAME_INIT) &&
+
+ // Don't inline a method into itself.
+ (!programMethod.equals(targetMethod) ||
+ !programClass.equals(targetClass)) &&
+
+ // Only inline the method if it isn't recursing.
+ !inliningMethods.contains(programMethod) &&
+
+ // Only inline the method if its target class has at least the
+ // same version number as the source class, in order to avoid
+ // introducing incompatible constructs.
+ targetClass.u4version >= programClass.u4version &&
+
+ // Only inline the method if it doesn't invoke a super method or a
+ // dynamic method, or if it is in the same class.
+ (!SuperInvocationMarker.invokesSuperMethods(programMethod) &&
+ !DynamicInvocationMarker.invokesDynamically(programMethod) ||
+ programClass.equals(targetClass)) &&
+
+ // Only inline the method if it doesn't branch backward while there
+ // are uninitialized objects.
+ (!BackwardBranchMarker.branchesBackward(programMethod) ||
+ uninitializedObjectCount == 0) &&
+
+ // Only inline if the code access of the inlined method allows it.
+ (allowAccessModification ||
+ ((!AccessMethodMarker.accessesPrivateCode(programMethod) ||
+ programClass.equals(targetClass)) &&
+
+ (!AccessMethodMarker.accessesPackageCode(programMethod) ||
+ ClassUtil.internalPackageName(programClass.getName()).equals(
+ ClassUtil.internalPackageName(targetClass.getName()))))) &&
+
+// (!AccessMethodMarker.accessesProtectedCode(programMethod) ||
+// targetClass.extends_(programClass) ||
+// targetClass.implements_(programClass)) ||
+ (!AccessMethodMarker.accessesProtectedCode(programMethod) ||
+ programClass.equals(targetClass)) &&
+
+ // Only inline the method if it doesn't catch exceptions, or if it
+ // is invoked with an empty stack.
+ (!CatchExceptionMarker.catchesExceptions(programMethod) ||
+ emptyInvokingStack) &&
+
+ // Only inline the method if it always returns with an empty
+ // stack.
+ !NonEmptyStackReturnMarker.returnsWithNonEmptyStack(programMethod) &&
+
+ // a subset of the initialized superclasses.
+ ((accessFlags & ClassConstants.ACC_STATIC) == 0 ||
+ programClass.equals(targetClass) ||
+ initializedSuperClasses(targetClass).containsAll(initializedSuperClasses(programClass))))
+ {
+ boolean oldInlining = inlining;
+ inlining = true;
+ inliningMethods.push(programMethod);
+
+ // Inline the method body.
+ programMethod.attributesAccept(programClass, this);
+
+ // Update the optimization information of the target method.
+ MethodOptimizationInfo info =
+ MethodOptimizationInfo.getMethodOptimizationInfo(targetMethod);
+ if (info != null)
+ {
+ info.merge(MethodOptimizationInfo.getMethodOptimizationInfo(programMethod));
+ }
+
+ inlining = oldInlining;
+ inliningMethods.pop();
+ }
+ else if (programMethod.getName(programClass).equals(ClassConstants.METHOD_NAME_INIT))
+ {
+ uninitializedObjectCount--;
+ }
+ }
+
+
+ // Implementations for LineNumberInfoVisitor.
+
+ public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
+ {
+ try
+ {
+ String newSource = lineNumberInfo.getSource() != null ?
+ lineNumberInfo.getSource() :
+ source;
+
+ LineNumberInfo newLineNumberInfo = newSource != null ?
+ new ExtendedLineNumberInfo(lineNumberInfo.u2startPC,
+ lineNumberInfo.u2lineNumber,
+ newSource) :
+ new LineNumberInfo(lineNumberInfo.u2startPC,
+ lineNumberInfo.u2lineNumber);
+
+ minimumLineNumberIndex =
+ codeAttributeComposer.insertLineNumber(minimumLineNumberIndex, newLineNumberInfo) + 1;
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (DEBUG)
+ {
+ System.err.println("Invalid line number while inlining method:");
+ System.err.println(" Target class = ["+targetClass.getName()+"]");
+ System.err.println(" Target method = ["+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]");
+ if (inlining)
+ {
+ System.err.println(" Inlined class = ["+clazz.getName()+"]");
+ System.err.println(" Inlined method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ }
+ System.err.println(" Exception = ["+e.getClass().getName()+"] ("+e.getMessage()+")");
+ }
+ }
+ }
+
+
+ /**
+ * Returns the set of superclasses and interfaces that are initialized.
+ */
+ private Set initializedSuperClasses(Clazz clazz)
+ {
+ Set set = new HashSet();
+
+ // Visit all superclasses and interfaces, collecting the ones that have
+ // static initializers.
+ clazz.hierarchyAccept(true, true, true, false,
+ new StaticInitializerContainingClassFilter(
+ new ClassCollector(set)));
+
+ return set;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/NopRemover.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/NopRemover.java
new file mode 100644
index 0000000000..fb40bea624
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/NopRemover.java
@@ -0,0 +1,89 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor removes all nop instructions that it encounters.
+ *
+ * @author Eric Lafortune
+ */
+public class NopRemover
+extends SimplifiedVisitor
+implements InstructionVisitor
+{
+ private final CodeAttributeEditor codeAttributeEditor;
+ private final InstructionVisitor extraInstructionVisitor;
+
+
+ /**
+ * Creates a new NopRemover.
+ * @param codeAttributeEditor a code editor that can be used for
+ * accumulating changes to the code.
+ */
+ public NopRemover(CodeAttributeEditor codeAttributeEditor)
+ {
+ this(codeAttributeEditor, null);
+ }
+
+
+ /**
+ * Creates a new NopRemover.
+ * @param codeAttributeEditor a code editor that can be used for
+ * accumulating changes to the code.
+ * @param extraInstructionVisitor an optional extra visitor for all removed
+ * nop instructions.
+ */
+ public NopRemover(CodeAttributeEditor codeAttributeEditor,
+ InstructionVisitor extraInstructionVisitor)
+ {
+ this.codeAttributeEditor = codeAttributeEditor;
+ this.extraInstructionVisitor = extraInstructionVisitor;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ // Check if the instruction is a nop instruction.
+ if (simpleInstruction.opcode == InstructionConstants.OP_NOP &&
+ !codeAttributeEditor.isModified(offset))
+ {
+ codeAttributeEditor.deleteInstruction(offset);
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ extraInstructionVisitor.visitSimpleInstruction(clazz, method, codeAttribute, offset, simpleInstruction);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/PeepholeOptimizer.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/PeepholeOptimizer.java
new file mode 100644
index 0000000000..10d2f80ea7
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/PeepholeOptimizer.java
@@ -0,0 +1,104 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.evaluation.BranchTargetFinder;
+
+/**
+ * This AttributeVisitor sets up and applies the peephole optimizations of its
+ * instruction visitor. The instruction visitor should be using the same
+ * (optional) branch target finder and code attribute editor.
+ *
+ * @author Eric Lafortune
+ */
+public class PeepholeOptimizer
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ private final BranchTargetFinder branchTargetFinder;
+ private final CodeAttributeEditor codeAttributeEditor;
+ private final InstructionVisitor instructionVisitor;
+
+
+ /**
+ * Creates a new PeepholeOptimizer.
+ * @param codeAttributeEditor the code attribute editor that will be reset
+ * and then executed.
+ * @param instructionVisitor the instruction visitor that performs
+ * peephole optimizations using the above code
+ * attribute editor.
+ */
+ public PeepholeOptimizer(CodeAttributeEditor codeAttributeEditor,
+ InstructionVisitor instructionVisitor)
+ {
+ this(null, codeAttributeEditor, instructionVisitor);
+ }
+
+
+ /**
+ * Creates a new PeepholeOptimizer.
+ * @param branchTargetFinder branch target finder that will be initialized
+ * to indicate branch targets in the visited code.
+ * @param codeAttributeEditor the code attribute editor that will be reset
+ * and then executed.
+ * @param instructionVisitor the instruction visitor that performs
+ * peephole optimizations using the above code
+ * attribute editor.
+ */
+ public PeepholeOptimizer(BranchTargetFinder branchTargetFinder,
+ CodeAttributeEditor codeAttributeEditor,
+ InstructionVisitor instructionVisitor)
+ {
+ this.branchTargetFinder = branchTargetFinder;
+ this.codeAttributeEditor = codeAttributeEditor;
+ this.instructionVisitor = instructionVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (branchTargetFinder != null)
+ {
+ // Set up the branch target finder.
+ branchTargetFinder.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+ // Set up the code attribute editor.
+ codeAttributeEditor.reset(codeAttribute.u4codeLength);
+
+ // Find the peephole optimizations.
+ codeAttribute.instructionsAccept(clazz, method, instructionVisitor);
+
+ // Apply the peephole optimizations.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ReachableCodeMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ReachableCodeMarker.java
new file mode 100644
index 0000000000..0e9a319590
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/ReachableCodeMarker.java
@@ -0,0 +1,262 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+import java.util.Arrays;
+
+/**
+ * This AttributeVisitor finds all instruction offsets, branch targets, and
+ * exception targets in the CodeAttribute objects that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class ReachableCodeMarker
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ExceptionInfoVisitor
+{
+ private boolean[] isReachable = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
+
+ private boolean next;
+ private boolean evaluateExceptions;
+
+
+ /**
+ * Returns whether the instruction at the given offset is reachable in
+ * the CodeAttribute that was visited most recently.
+ */
+ public boolean isReachable(int offset)
+ {
+ return isReachable[offset];
+ }
+
+
+ /**
+ * Returns whether any of the instructions at the given offsets are
+ * reachable in the CodeAttribute that was visited most recently.
+ */
+ public boolean isReachable(int startOffset, int endOffset)
+ {
+ // Check if any of the instructions is reachable.
+ for (int offset = startOffset; offset < endOffset; offset++)
+ {
+ if (isReachable[offset])
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Make sure there is a sufficiently large array.
+ int codeLength = codeAttribute.u4codeLength;
+ if (isReachable.length < codeLength)
+ {
+ // Create a new array.
+ isReachable = new boolean[codeLength];
+ }
+ else
+ {
+ // Reset the array.
+ Arrays.fill(isReachable, 0, codeLength, false);
+ }
+
+ // Mark the code, starting at the entry point.
+ markCode(clazz, method, codeAttribute, 0);
+
+ // Mark the exception handlers, iterating as long as necessary.
+ do
+ {
+ evaluateExceptions = false;
+
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ }
+ while (evaluateExceptions);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ byte opcode = simpleInstruction.opcode;
+ if (opcode == InstructionConstants.OP_IRETURN ||
+ opcode == InstructionConstants.OP_LRETURN ||
+ opcode == InstructionConstants.OP_FRETURN ||
+ opcode == InstructionConstants.OP_DRETURN ||
+ opcode == InstructionConstants.OP_ARETURN ||
+ opcode == InstructionConstants.OP_RETURN ||
+ opcode == InstructionConstants.OP_ATHROW)
+ {
+ next = false;
+ }
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ if (variableInstruction.opcode == InstructionConstants.OP_RET)
+ {
+ next = false;
+ }
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ // Mark the branch target.
+ markBranchTarget(clazz,
+ method,
+ codeAttribute,
+ offset + branchInstruction.branchOffset);
+
+ byte opcode = branchInstruction.opcode;
+ if (opcode == InstructionConstants.OP_GOTO ||
+ opcode == InstructionConstants.OP_GOTO_W)
+ {
+ next = false;
+ }
+ }
+
+
+ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ {
+ // Mark the branch targets of the default jump offset.
+ markBranchTarget(clazz,
+ method,
+ codeAttribute,
+ offset + switchInstruction.defaultOffset);
+
+ // Mark the branch targets of the jump offsets.
+ markBranchTargets(clazz,
+ method,
+ codeAttribute,
+ offset,
+ switchInstruction.jumpOffsets);
+
+ next = false;
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ // Mark the exception handler if it's relevant.
+ if (!isReachable(exceptionInfo.u2handlerPC) &&
+ isReachable(exceptionInfo.u2startPC, exceptionInfo.u2endPC))
+ {
+ markCode(clazz, method, codeAttribute, exceptionInfo.u2handlerPC);
+
+ evaluateExceptions = true;
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the branch targets of the given jump offsets for the instruction
+ * at the given offset.
+ */
+ private void markBranchTargets(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, int[] jumpOffsets)
+ {
+ for (int index = 0; index < jumpOffsets.length; index++)
+ {
+ markCode(clazz, method, codeAttribute, offset + jumpOffsets[index]);
+ }
+ }
+
+
+ /**
+ * Marks the branch target at the given offset.
+ */
+ private void markBranchTarget(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset)
+ {
+ boolean oldNext = next;
+
+ markCode(clazz, method, codeAttribute, offset);
+
+ next = oldNext;
+ }
+
+
+ /**
+ * Marks the code starting at the given offset.
+ */
+ private void markCode(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset)
+ {
+ boolean oldNext = next;
+
+ byte[] code = codeAttribute.code;
+
+ // Continue with the current instruction as long as we haven't marked it
+ // yet.
+ while (!isReachable[offset])
+ {
+ // Get the current instruction.
+ Instruction instruction = InstructionFactory.create(code, offset);
+
+ // Mark it as reachable.
+ isReachable[offset] = true;
+
+ // By default, we'll assume we can continue with the next
+ // instruction in a moment.
+ next = true;
+
+ // Mark the branch targets, if any.
+ instruction.accept(clazz, method, codeAttribute, offset, this);
+
+ // Can we really continue with the next instruction?
+ if (!next)
+ {
+ break;
+ }
+
+ // Go to the next instruction.
+ offset += instruction.length(offset);
+ }
+
+ next = oldNext;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/RetargetedClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/RetargetedClassFilter.java
new file mode 100644
index 0000000000..60e7eac508
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/RetargetedClassFilter.java
@@ -0,0 +1,96 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates its visits to one of two other given
+ * ClassVisitor instances, depending on whether the classes are marked to be
+ * retargeted or not.
+ *
+ * @see ClassMerger
+ *
+ * @author Eric Lafortune
+ */
+public class RetargetedClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor retargetedClassVisitor;
+ private final ClassVisitor otherClassVisitor;
+
+
+ /**
+ * Creates a new RetargetedClassFilter.
+ *
+ * @param retargetedClassVisitor the class visitor to which visits to
+ * classes that are marked to be retargeted
+ * will be delegated.
+ */
+ public RetargetedClassFilter(ClassVisitor retargetedClassVisitor)
+ {
+ this(retargetedClassVisitor, null);
+ }
+
+
+ /**
+ * Creates a new RetargetedClassFilter.
+ *
+ * @param retargetedClassVisitor the class visitor to which visits to
+ * classes that are marked to be retargeted
+ * will be delegated.
+ * @param otherClassVisitor the class visitor to which visits to
+ * classes that are not marked to be
+ * retargeted will be delegated.
+ */
+ public RetargetedClassFilter(ClassVisitor retargetedClassVisitor,
+ ClassVisitor otherClassVisitor)
+ {
+ this.retargetedClassVisitor = retargetedClassVisitor;
+ this.otherClassVisitor = otherClassVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Is the class marked to be retargeted?
+ ClassVisitor classVisitor = ClassMerger.getTargetClass(programClass) != null ?
+ retargetedClassVisitor : otherClassVisitor;
+
+ if (classVisitor != null)
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // A library class can't be retargeted.
+ if (otherClassVisitor != null)
+ {
+ otherClassVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java
new file mode 100644
index 0000000000..34364b4888
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java
@@ -0,0 +1,170 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+import java.util.Arrays;
+
+/**
+ * This ClassVisitor removes InnerClasses and EnclosingMethod attributes in
+ * classes that are retargeted or that refer to classes that are retargeted.
+ *
+ * @see ClassMerger
+ * @author Eric Lafortune
+ */
+public class RetargetedInnerClassAttributeRemover
+extends SimplifiedVisitor
+implements ClassVisitor,
+ AttributeVisitor,
+ InnerClassesInfoVisitor,
+ ConstantVisitor
+{
+ private boolean retargeted;
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ int attributesCount = programClass.u2attributesCount;
+ Attribute[] attributes = programClass.attributes;
+
+ int newAtributesCount = 0;
+
+ // Copy over all non-retargeted attributes.
+ for (int index = 0; index < attributesCount; index++)
+ {
+ Attribute attribute = attributes[index];
+
+ // Check if it's an InnerClasses or EnclosingMethod attribute in
+ // a retargeted class or referring to a retargeted class.
+ retargeted = false;
+ attribute.accept(programClass, this);
+ if (!retargeted)
+ {
+ attributes[newAtributesCount++] = attribute;
+ }
+ }
+
+ // Clean up any remaining array elements.
+ Arrays.fill(attributes, newAtributesCount, attributesCount, null);
+
+ // Update the number of attributes.
+ programClass.u2attributesCount = newAtributesCount;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ // Check whether the class itself is retargeted.
+ checkTarget(clazz);
+
+ if (!retargeted)
+ {
+ // Check whether the referenced classes are retargeted.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ int classesCount = innerClassesAttribute.u2classesCount;
+ InnerClassesInfo[] classes = innerClassesAttribute.classes;
+
+ int newClassesCount = 0;
+
+ // Copy over all non-retargeted attributes.
+ for (int index = 0; index < classesCount; index++)
+ {
+ InnerClassesInfo classInfo = classes[index];
+
+ // Check if the outer class or inner class is a retargeted class.
+ retargeted = false;
+ classInfo.outerClassConstantAccept(clazz, this);
+ classInfo.innerClassConstantAccept(clazz, this);
+ if (!retargeted)
+ {
+ classes[newClassesCount++] = classInfo;
+ }
+ }
+
+ // Clean up any remaining array elements.
+ Arrays.fill(classes, newClassesCount, classesCount, null);
+
+ // Update the number of classes.
+ innerClassesAttribute.u2classesCount = newClassesCount;
+
+ // Remove the attribute altogether if it's empty.
+ retargeted = newClassesCount == 0;
+ }
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ // Check whether the class itself is retargeted.
+ checkTarget(clazz);
+
+ // Check whether the referenced class is retargeted.
+ checkTarget(enclosingMethodAttribute.referencedClass);
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ // Check whether the inner class or the outer class are retargeted.
+ innerClassesInfo.innerClassConstantAccept(clazz, this);
+ innerClassesInfo.outerClassConstantAccept(clazz, this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Check whether the referenced class is retargeted.
+ checkTarget(classConstant.referencedClass);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Sets the global return value to true if the given class is retargeted.
+ */
+ private void checkTarget(Clazz clazz)
+ {
+ if (clazz != null &&
+ ClassMerger.getTargetClass(clazz) != null)
+ {
+ retargeted = true;
+ }
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/TargetClassChanger.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/TargetClassChanger.java
new file mode 100644
index 0000000000..6b53525816
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/TargetClassChanger.java
@@ -0,0 +1,508 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.editor.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor replaces references to classes and class members if the
+ * classes have targets that are intended to replace them.
+ *
+ * @see VerticalClassMerger
+ * @see ClassReferenceFixer
+ * @see MemberReferenceFixer
+ * @author Eric Lafortune
+ */
+public class TargetClassChanger
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor,
+ MemberVisitor,
+ AttributeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // We're only making changes locally in the class.
+ // Not all other classes may have been retargeted yet.
+
+ // Change the references of the constant pool.
+ programClass.constantPoolEntriesAccept(this);
+
+ // Change the references of the class members.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ // Change the references of the attributes.
+ programClass.attributesAccept(this);
+
+ // Remove duplicate interfaces and interface classes that have ended
+ // up pointing to the class itself.
+ boolean[] delete = null;
+ for (int index = 0; index < programClass.u2interfacesCount; index++)
+ {
+ Clazz interfaceClass = programClass.getInterface(index);
+ if (interfaceClass != null &&
+ (programClass.equals(interfaceClass) ||
+ containsInterfaceClass(programClass,
+ index,
+ interfaceClass)))
+ {
+ // Lazily create the array.
+ if (delete == null)
+ {
+ delete = new boolean[programClass.u2interfacesCount];
+ }
+
+ delete[index] = true;
+ }
+ }
+
+ if (delete != null)
+ {
+ new InterfaceDeleter(delete).visitProgramClass(programClass);
+ }
+
+ // Is the class being retargeted?
+ Clazz targetClass = ClassMerger.getTargetClass(programClass);
+ if (targetClass != null)
+ {
+ // We're not changing anything special in the superclass and
+ // interface hierarchy of the retargeted class. The shrinking
+ // step will remove the class for us.
+
+ // Restore the class name. We have to add a new class entry
+ // to avoid an existing entry with the same name being reused. The
+ // names have to be fixed later, based on their referenced classes.
+ programClass.u2thisClass =
+ addNewClassConstant(programClass,
+ programClass.getName(),
+ programClass);
+
+ // This class will no longer have any subclasses, because their
+ // subclasses and interfaces will be retargeted.
+ programClass.subClasses = null;
+ }
+ else
+ {
+ // This class has become the subclass of its possibly new
+ // superclass and of any new interfaces.
+ ConstantVisitor subclassAdder =
+ new ReferencedClassVisitor(
+ new SubclassFilter(programClass,
+ new SubclassAdder(programClass)));
+
+ programClass.superClassConstantAccept(subclassAdder);
+ programClass.interfaceConstantsAccept(subclassAdder);
+
+ // TODO: Maybe restore private method references.
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Change the references of the class members.
+ libraryClass.fieldsAccept(this);
+ libraryClass.methodsAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Change the referenced class.
+ programField.referencedClass =
+ updateReferencedClass(programField.referencedClass);
+
+ // Change the references of the attributes.
+ programField.attributesAccept(programClass, this);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Change the referenced classes.
+ updateReferencedClasses(programMethod.referencedClasses);
+
+ // Change the references of the attributes.
+ programMethod.attributesAccept(programClass, this);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ // Change the referenced class.
+ libraryField.referencedClass =
+ updateReferencedClass(libraryField.referencedClass);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ // Change the referenced classes.
+ updateReferencedClasses(libraryMethod.referencedClasses);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Does the string refer to a class, due to a Class.forName construct?
+ Clazz referencedClass = stringConstant.referencedClass;
+ Clazz newReferencedClass = updateReferencedClass(referencedClass);
+ if (referencedClass != newReferencedClass)
+ {
+ // Change the referenced class.
+ stringConstant.referencedClass = newReferencedClass;
+
+ // Change the referenced class member, if applicable.
+ stringConstant.referencedMember =
+ updateReferencedMember(stringConstant.referencedMember,
+ stringConstant.getString(clazz),
+ null,
+ newReferencedClass);
+ }
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Change the referenced classes.
+ updateReferencedClasses(invokeDynamicConstant.referencedClasses);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ Clazz referencedClass = refConstant.referencedClass;
+ Clazz newReferencedClass = updateReferencedClass(referencedClass);
+ if (referencedClass != newReferencedClass)
+ {
+ if (DEBUG)
+ {
+ System.out.println("TargetClassChanger:");
+ System.out.println(" ["+clazz.getName()+"] changing reference from ["+refConstant.referencedClass+"."+refConstant.referencedMember.getName(refConstant.referencedClass)+refConstant.referencedMember.getDescriptor(refConstant.referencedClass)+"]");
+ }
+
+ // Change the referenced class.
+ refConstant.referencedClass = newReferencedClass;
+
+ // Change the referenced class member.
+ refConstant.referencedMember =
+ updateReferencedMember(refConstant.referencedMember,
+ refConstant.getName(clazz),
+ refConstant.getType(clazz),
+ newReferencedClass);
+
+ if (DEBUG)
+ {
+ System.out.println(" ["+clazz.getName()+"] to ["+refConstant.referencedClass+"."+refConstant.referencedMember.getName(refConstant.referencedClass)+refConstant.referencedMember.getDescriptor(refConstant.referencedClass)+"]");
+ }
+ }
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Change the referenced class.
+ classConstant.referencedClass =
+ updateReferencedClass(classConstant.referencedClass);
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ updateReferencedClasses(methodTypeConstant.referencedClasses);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Change the references of the attributes.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Change the references of the local variables.
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Change the references of the local variables.
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ // Change the referenced classes.
+ updateReferencedClasses(signatureAttribute.referencedClasses);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ // Change the references of the annotations.
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Change the references of the annotations.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Change the references of the annotation.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Change the referenced class.
+ localVariableInfo.referencedClass =
+ updateReferencedClass(localVariableInfo.referencedClass);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Change the referenced classes.
+ updateReferencedClasses(localVariableTypeInfo.referencedClasses);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ // Change the referenced classes.
+ updateReferencedClasses(annotation.referencedClasses);
+
+ // Change the references of the element values.
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue)
+ {
+ Clazz referencedClass = elementValue.referencedClass;
+ Clazz newReferencedClass = updateReferencedClass(referencedClass);
+ if (referencedClass != newReferencedClass)
+ {
+ // Change the referenced annotation class.
+ elementValue.referencedClass = newReferencedClass;
+
+ // Change the referenced method.
+ elementValue.referencedMethod =
+ (Method)updateReferencedMember(elementValue.referencedMethod,
+ elementValue.getMethodName(clazz),
+ null,
+ newReferencedClass);
+ }
+ }
+
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ // Change the referenced annotation class and method.
+ visitAnyElementValue(clazz, annotation, constantElementValue);
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ // Change the referenced annotation class and method.
+ visitAnyElementValue(clazz, annotation, enumConstantElementValue);
+
+ // Change the referenced classes.
+ updateReferencedClasses(enumConstantElementValue.referencedClasses);
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ // Change the referenced annotation class and method.
+ visitAnyElementValue(clazz, annotation, classElementValue);
+
+ // Change the referenced classes.
+ updateReferencedClasses(classElementValue.referencedClasses);
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ // Change the referenced annotation class and method.
+ visitAnyElementValue(clazz, annotation, annotationElementValue);
+
+ // Change the references of the annotation.
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ // Change the referenced annotation class and method.
+ visitAnyElementValue(clazz, annotation, arrayElementValue);
+
+ // Change the references of the element values.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the given class contains the given interface
+ * class in its first given number of interfaces.
+ */
+ private boolean containsInterfaceClass(Clazz clazz,
+ int interfaceCount,
+ Clazz interfaceClass)
+ {
+ for (int index = 0; index < interfaceCount; index++)
+ {
+ if (interfaceClass.equals(clazz.getInterface(index)))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Updates the retargeted classes in the given array of classes.
+ */
+ private void updateReferencedClasses(Clazz[] referencedClasses)
+ {
+ if (referencedClasses == null)
+ {
+ return;
+ }
+
+ for (int index = 0; index < referencedClasses.length; index++)
+ {
+ referencedClasses[index] =
+ updateReferencedClass(referencedClasses[index]);
+ }
+ }
+
+
+ /**
+ * Returns the retargeted class of the given class.
+ */
+ private Clazz updateReferencedClass(Clazz referencedClass)
+ {
+ if (referencedClass == null)
+ {
+ return null;
+ }
+
+ Clazz targetClazz = ClassMerger.getTargetClass(referencedClass);
+ return targetClazz != null ?
+ targetClazz :
+ referencedClass;
+ }
+
+
+ /**
+ * Returns the retargeted class member of the given class member.
+ */
+ private Member updateReferencedMember(Member referencedMember,
+ String name,
+ String type,
+ Clazz newReferencedClass)
+ {
+ if (referencedMember == null)
+ {
+ return null;
+ }
+
+ return referencedMember instanceof Field ?
+ (Member)newReferencedClass.findField(name, type) :
+ (Member)newReferencedClass.findMethod(name, type);
+ }
+
+
+ /**
+ * Explicitly adds a new class constant for the given class in the given
+ * program class.
+ */
+ private int addNewClassConstant(ProgramClass programClass,
+ String className,
+ Clazz referencedClass)
+ {
+ ConstantPoolEditor constantPoolEditor =
+ new ConstantPoolEditor(programClass);
+
+ int nameIndex =
+ constantPoolEditor.addUtf8Constant(className);
+
+ int classConstantIndex =
+ constantPoolEditor.addConstant(new ClassConstant(nameIndex,
+ referencedClass));
+ return classConstantIndex;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/UnreachableCodeRemover.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/UnreachableCodeRemover.java
new file mode 100644
index 0000000000..aa07d11882
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/UnreachableCodeRemover.java
@@ -0,0 +1,143 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.CodeAttributeEditor;
+import proguard.classfile.instruction.Instruction;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor deletes blocks of code that can never be reached by
+ * regular calls or branches.
+ *
+ * @author Eric Lafortune
+ */
+public class UnreachableCodeRemover
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = true;
+ //*/
+
+ private final InstructionVisitor extraInstructionVisitor;
+
+ private final ReachableCodeMarker reachableCodeMarker = new ReachableCodeMarker();
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
+
+
+ /**
+ * Creates a new UnreachableCodeRemover.
+ */
+ public UnreachableCodeRemover()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new UnreachableCodeRemover.
+ * @param extraInstructionVisitor an optional extra visitor for all
+ * deleted instructions.
+ */
+ public UnreachableCodeRemover(InstructionVisitor extraInstructionVisitor)
+ {
+ this.extraInstructionVisitor = extraInstructionVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ // TODO: Remove this when the code has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while removing unreachable code:");
+ System.err.println(" Class = ["+clazz.getName()+"]");
+ System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+
+ throw ex;
+ }
+ }
+
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (DEBUG)
+ {
+ System.out.println("UnreachableCodeRemover: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ }
+
+ reachableCodeMarker.visitCodeAttribute(clazz, method, codeAttribute);
+
+ codeAttributeEditor.reset(codeAttribute.u4codeLength);
+
+ codeAttribute.instructionsAccept(clazz, method, this);
+
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ if (DEBUG)
+ {
+ System.out.println(" "+(reachableCodeMarker.isReachable(offset) ? "+" : "-")+" "+instruction.toString(offset));
+ }
+
+ // Is this instruction unreachable?
+ if (!reachableCodeMarker.isReachable(offset))
+ {
+ // Then delete it.
+ codeAttributeEditor.deleteInstruction(offset);
+
+ // Visit the instruction, if required.
+ if (extraInstructionVisitor != null)
+ {
+ instruction.accept(clazz, method, codeAttribute, offset, extraInstructionVisitor);
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/UnreachableExceptionRemover.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/UnreachableExceptionRemover.java
new file mode 100644
index 0000000000..8dad4468bb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/UnreachableExceptionRemover.java
@@ -0,0 +1,156 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.optimize.info.ExceptionInstructionChecker;
+
+/**
+ * This AttributeVisitor removes exception handlers that are unreachable in the
+ * code attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class UnreachableExceptionRemover
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ ExceptionInfoVisitor
+{
+ private final ExceptionInfoVisitor extraExceptionInfoVisitor;
+
+
+ /**
+ * Creates a new UnreachableExceptionRemover.
+ */
+ public UnreachableExceptionRemover()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new UnreachableExceptionRemover.
+ * @param extraExceptionInfoVisitor an optional extra visitor for all
+ * removed exceptions.
+ */
+ public UnreachableExceptionRemover(ExceptionInfoVisitor extraExceptionInfoVisitor)
+ {
+ this.extraExceptionInfoVisitor = extraExceptionInfoVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Go over the exception table.
+ codeAttribute.exceptionsAccept(clazz, method, this);
+
+ // Remove exceptions with empty code blocks.
+ codeAttribute.u2exceptionTableLength =
+ removeEmptyExceptions(codeAttribute.exceptionTable,
+ codeAttribute.u2exceptionTableLength);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ if (!mayThrowExceptions(clazz,
+ method,
+ codeAttribute,
+ exceptionInfo.u2startPC,
+ exceptionInfo.u2endPC))
+ {
+ // Make the code block empty.
+ exceptionInfo.u2endPC = exceptionInfo.u2startPC;
+
+ if (extraExceptionInfoVisitor != null)
+ {
+ extraExceptionInfoVisitor.visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the specified block of code may throw exceptions.
+ */
+ private boolean mayThrowExceptions(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int startOffset,
+ int endOffset)
+ {
+ byte[] code = codeAttribute.code;
+
+ // Go over all instructions.
+ int offset = startOffset;
+ while (offset < endOffset)
+ {
+ // Get the current instruction.
+ Instruction instruction = InstructionFactory.create(code, offset);
+
+ // Check if it may be throwing exceptions.
+ if (instruction.mayThrowExceptions())
+ {
+ return true;
+ }
+
+ // Go to the next instruction.
+ offset += instruction.length(offset);
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns the given list of exceptions, without the ones that have empty
+ * code blocks.
+ */
+ private int removeEmptyExceptions(ExceptionInfo[] exceptionInfos,
+ int exceptionInfoCount)
+ {
+ // Overwrite all empty exceptions.
+ int newIndex = 0;
+ for (int index = 0; index < exceptionInfoCount; index++)
+ {
+ ExceptionInfo exceptionInfo = exceptionInfos[index];
+ if (exceptionInfo.u2startPC < exceptionInfo.u2endPC)
+ {
+ exceptionInfos[newIndex++] = exceptionInfo;
+ }
+ }
+
+ return newIndex;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/VariableShrinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/VariableShrinker.java
new file mode 100644
index 0000000000..8f01954ddf
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/VariableShrinker.java
@@ -0,0 +1,133 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.VariableEditor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.MemberVisitor;
+import proguard.optimize.*;
+import proguard.optimize.info.*;
+
+/**
+ * This MemberVisitor removes unused local variables from the code of the methods
+ * that it visits.
+ *
+ * @see ParameterUsageMarker
+ * @see MethodStaticizer
+ * @see MethodDescriptorShrinker
+ * @author Eric Lafortune
+ */
+public class VariableShrinker
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("vs") != null;
+ //*/
+
+
+ private final MemberVisitor extraVariableMemberVisitor;
+
+ private final VariableUsageMarker variableUsageMarker = new VariableUsageMarker();
+ private final VariableEditor variableEditor = new VariableEditor();
+
+
+ /**
+ * Creates a new VariableShrinker.
+ */
+ public VariableShrinker()
+ {
+ this(null);
+ }
+
+
+ /**
+ * Creates a new VariableShrinker with an extra visitor.
+ * @param extraVariableMemberVisitor an optional extra visitor for all
+ * removed variables.
+ */
+ public VariableShrinker(MemberVisitor extraVariableMemberVisitor)
+ {
+ this.extraVariableMemberVisitor = extraVariableMemberVisitor;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if ((method.getAccessFlags() & ClassConstants.ACC_ABSTRACT) == 0)
+ {
+ // Compute the parameter size.
+ int parameterSize =
+ ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz),
+ method.getAccessFlags());
+
+ // Get the total size of the local variable frame.
+ int maxLocals = codeAttribute.u2maxLocals;
+
+ if (DEBUG)
+ {
+ System.out.println("VariableShrinker: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ System.out.println(" Parameter size = " + parameterSize);
+ System.out.println(" Max locals = " + maxLocals);
+ }
+
+ // Figure out the local variables that are used by the code.
+ variableUsageMarker.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Delete unused local variables from the local variable frame.
+ variableEditor.reset(maxLocals);
+
+ for (int variableIndex = parameterSize; variableIndex < maxLocals; variableIndex++)
+ {
+ // Is the variable not required?
+ if (!variableUsageMarker.isVariableUsed(variableIndex))
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Deleting local variable #"+variableIndex);
+ }
+
+ // Delete the unused variable.
+ variableEditor.deleteVariable(variableIndex);
+
+ // Visit the method, if required.
+ if (extraVariableMemberVisitor != null)
+ {
+ method.accept(clazz, extraVariableMemberVisitor);
+ }
+ }
+ }
+
+ // Shift all remaining parameters and variables in the byte code.
+ variableEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/VerticalClassMerger.java b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/VerticalClassMerger.java
new file mode 100644
index 0000000000..2f7fc00bbb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/VerticalClassMerger.java
@@ -0,0 +1,88 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.optimize.peephole;
+
+import proguard.classfile.ProgramClass;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor inlines the direct subclasses into the program classes
+ * that it visits, whenever possible.
+ *
+ * @see ClassMerger
+ * @author Eric Lafortune
+ */
+public class VerticalClassMerger
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ private final boolean allowAccessModification;
+ private final boolean mergeInterfacesAggressively;
+ private final ClassVisitor extraClassVisitor;
+
+
+ /**
+ * Creates a new VerticalClassMerger.
+ * @param allowAccessModification specifies whether the access modifiers
+ * of classes can be changed in order to
+ * merge them.
+ * @param mergeInterfacesAggressively specifies whether interfaces may
+ * be merged aggressively.
+ */
+ public VerticalClassMerger(boolean allowAccessModification,
+ boolean mergeInterfacesAggressively)
+ {
+ this(allowAccessModification, mergeInterfacesAggressively, null);
+ }
+
+
+ /**
+ * Creates a new VerticalClassMerger.
+ * @param allowAccessModification specifies whether the access modifiers
+ * of classes can be changed in order to
+ * merge them.
+ * @param mergeInterfacesAggressively specifies whether interfaces may
+ * be merged aggressively.
+ * @param extraClassVisitor an optional extra visitor for all
+ * merged classes.
+ */
+ public VerticalClassMerger(boolean allowAccessModification,
+ boolean mergeInterfacesAggressively,
+ ClassVisitor extraClassVisitor)
+ {
+ this.allowAccessModification = allowAccessModification;
+ this.mergeInterfacesAggressively = mergeInterfacesAggressively;
+ this.extraClassVisitor = extraClassVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Try inlining all immediate subclasses into this class.
+ programClass.subclassesAccept(new ClassMerger(programClass,
+ allowAccessModification,
+ mergeInterfacesAggressively,
+ extraClassVisitor));
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/package.html
new file mode 100644
index 0000000000..e0eeb51418
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/optimize/peephole/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains visitors that perform various peephole optimizations.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/package.html
new file mode 100644
index 0000000000..986cad89c0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/package.html
@@ -0,0 +1,5 @@
+<body>
+This package contains the main ProGuard application.
+ProGuard can read jar files, shrink and obfuscate them, and write out the
+resulting jar file.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/CodePreverifier.java b/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/CodePreverifier.java
new file mode 100644
index 0000000000..93c77ccb75
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/CodePreverifier.java
@@ -0,0 +1,623 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.preverify;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.*;
+import proguard.classfile.instruction.InstructionConstants;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassPrinter;
+import proguard.evaluation.*;
+import proguard.evaluation.value.*;
+import proguard.optimize.evaluation.*;
+
+import java.util.*;
+
+/**
+ * This class can preverify methods in program class pools, according to a given
+ * specification.
+ *
+ * @author Eric Lafortune
+ */
+public class CodePreverifier
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = true;
+ //*/
+
+
+ private final boolean microEdition;
+
+ private final PartialEvaluator partialEvaluator = new PartialEvaluator();
+ private final LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer(partialEvaluator);
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
+
+
+ /**
+ * Creates a new CodePreverifier.
+ */
+ public CodePreverifier(boolean microEdition)
+ {
+ this.microEdition = microEdition;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // TODO: Remove this when the preverifier has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while preverifying:");
+ System.err.println(" Class = ["+clazz.getName()+"]");
+ System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+
+ throw ex;
+ }
+ }
+
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+
+ ProgramClass programClass = (ProgramClass)clazz;
+ ProgramMethod programMethod = (ProgramMethod)method;
+
+ int codeLength = codeAttribute.u4codeLength;
+
+ // Evaluate the method.
+ //partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+ livenessAnalyzer.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // We may have to remove unreachable code.
+ codeAttributeEditor.reset(codeLength);
+
+ // Collect the stack map frames.
+ List stackMapFrameList = new ArrayList();
+
+ for (int offset = 0; offset < codeLength; offset++)
+ {
+ // Only store frames at the beginning of code blocks.
+ if (!partialEvaluator.isTraced(offset))
+ {
+ // Mark the unreachable instruction for deletion.
+ codeAttributeEditor.deleteInstruction(offset);
+ }
+ else if (partialEvaluator.isBranchOrExceptionTarget(offset))
+ {
+ // Convert the variable values to types.
+ VerificationType[] variableTypes =
+ correspondingVerificationTypes(programClass,
+ programMethod,
+ codeAttribute,
+ offset,
+ partialEvaluator.getVariablesBefore(offset));
+
+ // Convert the stack values to types.
+ VerificationType[] stackTypes =
+ correspondingVerificationTypes(programClass,
+ programMethod,
+ codeAttribute,
+ offset,
+ partialEvaluator.getStackBefore(offset));
+ // Create and store a new frame.
+ stackMapFrameList.add(new FullFrame(offset,
+ variableTypes,
+ stackTypes));
+ }
+ }
+
+ // Compress the stack map frames if the target is not Java Micro Edition.
+ if (!microEdition && !stackMapFrameList.isEmpty())
+ {
+ // Convert the initial variable values to types.
+ VerificationType[] initialVariables =
+ correspondingVerificationTypes(programClass,
+ programMethod,
+ codeAttribute,
+ PartialEvaluator.AT_METHOD_ENTRY,
+ partialEvaluator.getVariablesBefore(0));
+
+ // Special case: the <init> method.
+ if (method.getName(programClass).equals(ClassConstants.METHOD_NAME_INIT))
+ {
+ initialVariables[0] = VerificationTypeFactory.createUninitializedThisType();
+ }
+
+ compressStackMapFrames(initialVariables,
+ stackMapFrameList);
+ }
+
+ // Get the proper name for the attribute to be added/replaced/deleted.
+ String stackMapAttributeName = microEdition ?
+ ClassConstants.ATTR_StackMap :
+ ClassConstants.ATTR_StackMapTable;
+
+ int frameCount = stackMapFrameList.size();
+
+ if (DEBUG)
+ {
+ Attribute originalStackMapAttribute = codeAttribute.getAttribute(clazz,
+ stackMapAttributeName);
+
+ if (originalStackMapAttribute != null)
+ {
+ int originalFrameCount = microEdition ?
+ ((StackMapAttribute)originalStackMapAttribute).u2stackMapFramesCount :
+ ((StackMapTableAttribute)originalStackMapAttribute).u2stackMapFramesCount;
+
+ StackMapFrame[] originalFrames = microEdition ?
+ ((StackMapAttribute)originalStackMapAttribute).stackMapFrames :
+ ((StackMapTableAttribute)originalStackMapAttribute).stackMapFrames;
+
+ if (frameCount != originalFrameCount ||
+ !Arrays.equals(stackMapFrameList.toArray(), originalFrames))
+ {
+ System.out.println("Original preverification ["+clazz.getName()+"]:");
+ new ClassPrinter().visitProgramMethod(programClass, programMethod);
+ }
+ }
+ else if (frameCount != 0)
+ {
+ System.out.println("Original preverification empty ["+clazz.getName()+"."+method.getName(clazz)+"]");
+ }
+ }
+
+ if (frameCount == 0)
+ {
+ // Remove any stack map (table) attribute from the code attribute.
+ new AttributesEditor(programClass, programMethod, codeAttribute, true).deleteAttribute(stackMapAttributeName);
+ }
+ else
+ {
+ Attribute stackMapAttribute;
+
+ // Create the appropriate attribute.
+ if (microEdition)
+ {
+ // Copy the frames into an array.
+ FullFrame[] stackMapFrames = new FullFrame[frameCount];
+ stackMapFrameList.toArray(stackMapFrames);
+
+ // Put the frames into a stack map attribute.
+ stackMapAttribute = new StackMapAttribute(stackMapFrames);
+ }
+ else
+ {
+ // Copy the frames into an array.
+ StackMapFrame[] stackMapFrames = new StackMapFrame[frameCount];
+ stackMapFrameList.toArray(stackMapFrames);
+
+ // Put the frames into a stack map table attribute.
+ stackMapAttribute = new StackMapTableAttribute(stackMapFrames);
+ }
+
+ // Fill out the name of the stack map attribute.
+ stackMapAttribute.u2attributeNameIndex =
+ new ConstantPoolEditor(programClass).addUtf8Constant(stackMapAttributeName);
+
+ // Add the new stack map (table) attribute to the code attribute.
+ new AttributesEditor(programClass, programMethod, codeAttribute, true).addAttribute(stackMapAttribute);
+
+ if (DEBUG)
+ {
+ System.out.println("Preverifier ["+programClass.getName()+"."+programMethod.getName(programClass)+"]:");
+ stackMapAttribute.accept(programClass, programMethod, codeAttribute, new ClassPrinter());
+ }
+ }
+
+ // Apply code modifications, deleting unreachable code.
+ codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Creates and returns the verification types corresponding to the given
+ * variables. If necessary, class constants are added to the constant pool
+ * of the given class.
+ */
+ private VerificationType[] correspondingVerificationTypes(ProgramClass programClass,
+ ProgramMethod programMethod,
+ CodeAttribute codeAttribute,
+ int offset,
+ TracedVariables variables)
+ {
+ int maximumVariablesSize = variables.size();
+ int typeCount = 0;
+ int typeIndex = 0;
+
+ // Count the the number of verification types, ignoring any nulls at
+ // the end.
+ for (int index = 0; index < maximumVariablesSize; index++)
+ {
+ Value value = variables.getValue(index);
+
+ typeIndex++;
+
+ // Remember the maximum live type index.
+ if (value != null &&
+ (offset == PartialEvaluator.AT_METHOD_ENTRY ||
+ livenessAnalyzer.isAliveBefore(offset, index)))
+ {
+ typeCount = typeIndex;
+
+ // Category 2 types that are alive are stored as single entries.
+ if (value.isCategory2())
+ {
+ index++;
+ }
+ }
+ }
+
+ // Create and fill out the verification types.
+ VerificationType[] types = new VerificationType[typeCount];
+
+ typeIndex = 0;
+
+ // Note the slightly different terminating condition, because the
+ // types may have been truncated.
+ for (int index = 0; typeIndex < typeCount; index++)
+ {
+ Value value = variables.getValue(index);
+ Value producerValue = variables.getProducerValue(index);
+
+ // Fill out the type.
+ VerificationType type;
+
+ if (value != null &&
+ (offset == PartialEvaluator.AT_METHOD_ENTRY ||
+ livenessAnalyzer.isAliveBefore(offset, index)))
+ {
+ type = correspondingVerificationType(programClass,
+ programMethod,
+ codeAttribute,
+ offset,
+ index == 0,
+ value,
+ producerValue);
+
+ // Category 2 types that are alive are stored as single entries.
+ if (value.isCategory2())
+ {
+ index++;
+ }
+ }
+ else
+ {
+ type = VerificationTypeFactory.createTopType();
+ }
+
+ types[typeIndex++] = type;
+ }
+
+ return types;
+ }
+
+
+ /**
+ * Creates and returns the verification types corresponding to the given
+ * stack. If necessary, class constants are added to the constant pool
+ * of the given class.
+ */
+ private VerificationType[] correspondingVerificationTypes(ProgramClass programClass,
+ ProgramMethod programMethod,
+ CodeAttribute codeAttribute,
+ int offset,
+ TracedStack stack)
+ {
+ int maximumStackSize = stack.size();
+ int typeCount = 0;
+
+ // Count the the number of verification types.
+ for (int index = 0; index < maximumStackSize; index++)
+ {
+ // We have to work down from the top of the stack.
+ Value value = stack.getTop(index);
+
+ typeCount++;
+
+ // Category 2 types are stored as single entries.
+ if (value.isCategory2())
+ {
+ index++;
+ }
+ }
+
+ // Create and fill out the verification types.
+ VerificationType[] types = new VerificationType[typeCount];
+
+ int typeIndex = typeCount;
+
+ for (int index = 0; index < maximumStackSize; index++)
+ {
+ // We have to work down from the top of the stack.
+ Value value = stack.getTop(index);
+ Value producerValue = stack.getTopProducerValue(index);
+
+ // Fill out the type.
+ types[--typeIndex] =
+ correspondingVerificationType(programClass,
+ programMethod,
+ codeAttribute,
+ offset,
+ false,
+ value,
+ producerValue);
+
+ // Category 2 types are stored as single entries.
+ if (value.isCategory2())
+ {
+ index++;
+ }
+ }
+
+ return types;
+ }
+
+
+ /**
+ * Creates and returns the verification type corresponding to the given
+ * value. If necessary, a class constant is added to the constant pool of
+ * the given class.
+ */
+ private VerificationType correspondingVerificationType(ProgramClass programClass,
+ ProgramMethod programMethod,
+ CodeAttribute codeAttribute,
+ int offset,
+ boolean isVariable0,
+ Value value,
+ Value producerValue)
+ {
+ if (value == null)
+ {
+ return VerificationTypeFactory.createTopType();
+ }
+
+ int type = value.computationalType();
+
+ switch (type)
+ {
+ case Value.TYPE_INSTRUCTION_OFFSET:
+ case Value.TYPE_INTEGER: return VerificationTypeFactory.createIntegerType();
+ case Value.TYPE_LONG: return VerificationTypeFactory.createLongType();
+ case Value.TYPE_FLOAT: return VerificationTypeFactory.createFloatType();
+ case Value.TYPE_DOUBLE: return VerificationTypeFactory.createDoubleType();
+ case Value.TYPE_TOP: return VerificationTypeFactory.createTopType();
+ case Value.TYPE_REFERENCE:
+ // Is it a Null type?
+ ReferenceValue referenceValue = value.referenceValue();
+ if (referenceValue.isNull() == Value.ALWAYS)
+ {
+ return VerificationTypeFactory.createNullType();
+ }
+
+ // Does the reference type have a single producer?
+ if (offset != PartialEvaluator.AT_METHOD_ENTRY)
+ {
+ InstructionOffsetValue producers = producerValue.instructionOffsetValue();
+ if (producers.instructionOffsetCount() == 1)
+ {
+ int producerOffset = producers.instructionOffset(0);
+
+ // Follow any dup or swap instructions.
+ while (producerOffset != PartialEvaluator.AT_METHOD_ENTRY &&
+ isDupOrSwap(codeAttribute.code[producerOffset]))
+ {
+ producers = partialEvaluator.getStackBefore(producerOffset).getTopProducerValue(0).instructionOffsetValue();
+ producerOffset = producers.minimumValue();
+ }
+
+ // Are we in an instance initialization method,
+ // before the super initialization, loading "this"?
+ if (partialEvaluator.isInitializer() &&
+ offset <= partialEvaluator.superInitializationOffset() &&
+ (isVariable0 ||
+ producerOffset > PartialEvaluator.AT_METHOD_ENTRY &&
+ codeAttribute.code[producerOffset] == InstructionConstants.OP_ALOAD_0))
+ {
+ // It's an UninitializedThis type.
+ return VerificationTypeFactory.createUninitializedThisType();
+ }
+
+ // Is the reference type newly created and still
+ // uninitialized?
+ if (producerOffset > PartialEvaluator.AT_METHOD_ENTRY &&
+ offset <= partialEvaluator.initializationOffset(producerOffset))
+ {
+ // It's an Uninitialized type.
+ return VerificationTypeFactory.createUninitializedType(producerOffset);
+ }
+ }
+ }
+
+ // It's an ordinary Object type.
+ return VerificationTypeFactory.createObjectType(createClassConstant(programClass, referenceValue));
+ }
+
+ throw new IllegalArgumentException("Unknown computational type ["+type+"]");
+ }
+
+
+ /**
+ * Finds or creates a class constant for the given reference value, and
+ * returns its index in the constant pool.
+ */
+ private int createClassConstant(ProgramClass programClass,
+ ReferenceValue referenceValue)
+ {
+ return new ConstantPoolEditor(programClass).addClassConstant(referenceValue.getType(),
+ referenceValue.getReferencedClass());
+ }
+
+
+ /**
+ * Compresses the given list of full frames, for use in a stack map table.
+ */
+ private void compressStackMapFrames(VerificationType[] initialVariableTypes,
+ List stackMapFrameList)
+ {
+ int previousVariablesCount = initialVariableTypes.length;
+ VerificationType[] previousVariableTypes = initialVariableTypes;
+
+ int previousOffset = -1;
+
+ for (int index = 0; index < stackMapFrameList.size(); index++)
+ {
+ FullFrame fullFrame = (FullFrame)stackMapFrameList.get(index);
+
+ int variablesCount = fullFrame.variablesCount;
+ VerificationType[] variables = fullFrame.variables;
+ int stackCount = fullFrame.stackCount;
+ VerificationType[] stack = fullFrame.stack;
+
+ // Start computing the compressed frame.
+ // The default is the full frame.
+ StackMapFrame compressedFrame = fullFrame;
+
+ // Are all variables equal?
+ if (variablesCount == previousVariablesCount &&
+ equalVerificationTypes(variables, previousVariableTypes, variablesCount))
+ {
+ // Are the stacks equal?
+ //if (stackCount == previousStackCount &&
+ // equalVerificationTypes(stack, previousStack, stackCount))
+ //{
+ // // Remove the identical frame.
+ // stackMapFrameList.remove(index--);
+ //
+ // // Move on to the next frame (at the same index).
+ // continue;
+ //}
+ // Is the new stack empty?
+ //else
+ if (stackCount == 0)
+ {
+ compressedFrame = new SameZeroFrame();
+ }
+ // Does the new stack contain a single element?
+ else if (stackCount == 1)
+ {
+ compressedFrame = new SameOneFrame(stack[0]);
+ }
+ }
+ // Is the stack empty?
+ else if (stackCount == 0)
+ {
+ int additionalVariablesCount = variablesCount - previousVariablesCount;
+
+ // Are the variables chopped?
+ if (additionalVariablesCount < 0 &&
+ additionalVariablesCount > -4 &&
+ equalVerificationTypes(variables, previousVariableTypes, variablesCount))
+ {
+ compressedFrame = new LessZeroFrame((byte)-additionalVariablesCount);
+ }
+ // Are the variables extended?
+ else if (//previousVariablesCount > 0 &&
+ additionalVariablesCount > 0 &&
+ additionalVariablesCount < 4 &&
+ equalVerificationTypes(variables, previousVariableTypes, previousVariablesCount))
+ {
+ // Copy the additional variables into an array.
+ VerificationType[] additionalVariables = new VerificationType[additionalVariablesCount];
+ System.arraycopy(variables, variablesCount - additionalVariablesCount,
+ additionalVariables, 0,
+ additionalVariablesCount);
+
+ compressedFrame = new MoreZeroFrame(additionalVariables);
+ }
+ }
+
+ // Compress the instruction offset.
+ int offset = fullFrame.u2offsetDelta;
+ compressedFrame.u2offsetDelta = offset - previousOffset - 1;
+ previousOffset = offset;
+
+ // Remember this frame.
+ previousVariablesCount = fullFrame.variablesCount;
+ previousVariableTypes = fullFrame.variables;
+
+ // Replace the full frame.
+ stackMapFrameList.set(index, compressedFrame);
+ }
+ }
+
+
+ /**
+ * Returns whether the given arrays of verification types are equal, up to
+ * the given length.
+ */
+ private boolean equalVerificationTypes(VerificationType[] types1,
+ VerificationType[] types2,
+ int length)
+ {
+ if (length > 0 &&
+ (types1.length < length ||
+ types2.length < length))
+ {
+ return false;
+ }
+
+ for (int index = 0; index < length; index++)
+ {
+ if (!types1[index].equals(types2[index]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the given instruction opcode represents a dup or swap
+ * instruction (dup, dup_x1, dup_x2, dup2, dup2_x1, dup2_x2, swap).
+ */
+ private boolean isDupOrSwap(int opcode)
+ {
+ return opcode >= InstructionConstants.OP_DUP &&
+ opcode <= InstructionConstants.OP_SWAP;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/CodeSubroutineInliner.java b/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/CodeSubroutineInliner.java
new file mode 100644
index 0000000000..df6627d701
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/CodeSubroutineInliner.java
@@ -0,0 +1,402 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.preverify;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.editor.CodeAttributeComposer;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+import proguard.evaluation.BranchTargetFinder;
+
+/**
+ * This AttributeVisitor inlines local subroutines (jsr/ret) in the code
+ * attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class CodeSubroutineInliner
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor,
+ ExceptionInfoVisitor
+{
+ //*
+ private static final boolean DEBUG = false;
+ /*/
+ private static boolean DEBUG = System.getProperty("csi") != null;
+ //*/
+
+ private final BranchTargetFinder branchTargetFinder = new BranchTargetFinder();
+ private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer(true, true, true);
+
+ private ExceptionInfoVisitor subroutineExceptionInliner = this;
+ private int clipStart = 0;
+ private int clipEnd = Integer.MAX_VALUE;
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+// DEBUG =
+// clazz.getName().equals("abc/Def") &&
+// method.getName(clazz).equals("abc");
+// CodeAttributeComposer.DEBUG = DEBUG;
+
+ // TODO: Remove this when the subroutine inliner has stabilized.
+ // Catch any unexpected exceptions from the actual visiting method.
+ try
+ {
+ // Process the code.
+ visitCodeAttribute0(clazz, method, codeAttribute);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.println("Unexpected error while inlining subroutines:");
+ System.err.println(" Class = ["+clazz.getName()+"]");
+ System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
+
+ if (DEBUG)
+ {
+ method.accept(clazz, new ClassPrinter());
+ }
+
+ throw ex;
+ }
+ }
+
+
+ public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ branchTargetFinder.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Don't bother if there aren't any subroutines anyway.
+ if (!branchTargetFinder.containsSubroutines())
+ {
+ return;
+ }
+
+ if (DEBUG)
+ {
+ System.out.println("SubroutineInliner: processing ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]");
+ }
+
+ // Append the body of the code.
+ codeAttributeComposer.reset();
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
+
+ // Copy the non-subroutine instructions.
+ int offset = 0;
+ while (offset < codeAttribute.u4codeLength)
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code, offset);
+ int instructionLength = instruction.length(offset);
+
+ // Is this a returning subroutine?
+ if (branchTargetFinder.isSubroutine(offset) &&
+ branchTargetFinder.isSubroutineReturning(offset))
+ {
+ // Skip the subroutine.
+ if (DEBUG)
+ {
+ System.out.println(" Skipping original subroutine instruction "+instruction.toString(offset));
+ }
+
+ // Append a label at this offset instead.
+ codeAttributeComposer.appendLabel(offset);
+ }
+ else
+ {
+ // Copy the instruction, inlining any subroutine call recursively.
+ instruction.accept(clazz, method, codeAttribute, offset, this);
+ }
+
+ offset += instructionLength;
+ }
+
+ // Copy the exceptions. Note that exceptions with empty try blocks
+ // are automatically removed.
+ codeAttribute.exceptionsAccept(clazz,
+ method,
+ subroutineExceptionInliner);
+
+ if (DEBUG)
+ {
+ System.out.println(" Appending label after code at ["+offset+"]");
+ }
+
+ // Append a label just after the code.
+ codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
+
+ // End and update the code attribute.
+ codeAttributeComposer.endCodeFragment();
+ codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+
+
+ /**
+ * Appends the specified subroutine.
+ */
+ private void inlineSubroutine(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int subroutineInvocationOffset,
+ int subroutineStart)
+ {
+ int subroutineEnd = branchTargetFinder.subroutineEnd(subroutineStart);
+
+ if (DEBUG)
+ {
+ System.out.println(" Inlining subroutine ["+subroutineStart+" -> "+subroutineEnd+"] at ["+subroutineInvocationOffset+"]");
+ }
+
+ // Don't go inlining exceptions that are already applicable to this
+ // subroutine invocation.
+ ExceptionInfoVisitor oldSubroutineExceptionInliner = subroutineExceptionInliner;
+ int oldClipStart = clipStart;
+ int oldClipEnd = clipEnd;
+
+ subroutineExceptionInliner =
+ new ExceptionExcludedOffsetFilter(subroutineInvocationOffset,
+ subroutineExceptionInliner);
+ clipStart = subroutineStart;
+ clipEnd = subroutineEnd;
+
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
+
+ // Copy the subroutine instructions, inlining any subroutine calls
+ // recursively.
+ codeAttribute.instructionsAccept(clazz,
+ method,
+ subroutineStart,
+ subroutineEnd,
+ this);
+
+ if (DEBUG)
+ {
+ System.out.println(" Appending label after inlined subroutine at ["+subroutineEnd+"]");
+ }
+
+ // Append a label just after the code.
+ codeAttributeComposer.appendLabel(subroutineEnd);
+
+ // Inline the subroutine exceptions.
+ codeAttribute.exceptionsAccept(clazz,
+ method,
+ subroutineStart,
+ subroutineEnd,
+ subroutineExceptionInliner);
+
+ // We can again inline exceptions that are applicable to this
+ // subroutine invocation.
+ subroutineExceptionInliner = oldSubroutineExceptionInliner;
+ clipStart = oldClipStart;
+ clipEnd = oldClipEnd;
+
+ codeAttributeComposer.endCodeFragment();
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ if (branchTargetFinder.isSubroutineStart(offset))
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Replacing first subroutine instruction "+instruction.toString(offset)+" by a label");
+ }
+
+ // Append a label at this offset instead of saving the subroutine
+ // return address.
+ codeAttributeComposer.appendLabel(offset);
+ }
+ else
+ {
+ // Append the instruction.
+ codeAttributeComposer.appendInstruction(offset, instruction);
+ }
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ byte opcode = variableInstruction.opcode;
+ if (opcode == InstructionConstants.OP_RET)
+ {
+ // Is the return instruction the last instruction of the subroutine?
+ if (branchTargetFinder.subroutineEnd(offset) == offset + variableInstruction.length(offset))
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Replacing subroutine return at ["+offset+"] by a label");
+ }
+
+ // Append a label at this offset instead of the subroutine return.
+ codeAttributeComposer.appendLabel(offset);
+ }
+ else
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Replacing subroutine return at ["+offset+"] by a simple branch");
+ }
+
+ // Replace the instruction by a branch.
+ Instruction replacementInstruction =
+ new BranchInstruction(InstructionConstants.OP_GOTO,
+ branchTargetFinder.subroutineEnd(offset) - offset);
+
+ codeAttributeComposer.appendInstruction(offset, replacementInstruction);
+ }
+ }
+ else if (branchTargetFinder.isSubroutineStart(offset))
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Replacing first subroutine instruction "+variableInstruction.toString(offset)+" by a label");
+ }
+
+ // Append a label at this offset instead of saving the subroutine
+ // return address.
+ codeAttributeComposer.appendLabel(offset);
+ }
+ else
+ {
+ // Append the instruction.
+ codeAttributeComposer.appendInstruction(offset, variableInstruction);
+ }
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ byte opcode = branchInstruction.opcode;
+ if (opcode == InstructionConstants.OP_JSR ||
+ opcode == InstructionConstants.OP_JSR_W)
+ {
+ int branchOffset = branchInstruction.branchOffset;
+ int branchTarget = offset + branchOffset;
+
+ // Is the subroutine ever returning?
+ if (branchTargetFinder.isSubroutineReturning(branchTarget))
+ {
+ // Append a label at this offset instead of the subroutine invocation.
+ codeAttributeComposer.appendLabel(offset);
+
+ // Inline the invoked subroutine.
+ inlineSubroutine(clazz,
+ method,
+ codeAttribute,
+ offset,
+ branchTarget);
+ }
+ else
+ {
+ if (DEBUG)
+ {
+ System.out.println("Replacing subroutine invocation at ["+offset+"] by a simple branch");
+ }
+
+ // Replace the subroutine invocation by a simple branch.
+ Instruction replacementInstruction =
+ new BranchInstruction(InstructionConstants.OP_GOTO,
+ branchOffset);
+
+ codeAttributeComposer.appendInstruction(offset, replacementInstruction);
+ }
+ }
+ else
+ {
+ // Append the instruction.
+ codeAttributeComposer.appendInstruction(offset, branchInstruction);
+ }
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ int startPC = Math.max(exceptionInfo.u2startPC, clipStart);
+ int endPC = Math.min(exceptionInfo.u2endPC, clipEnd);
+ int handlerPC = exceptionInfo.u2handlerPC;
+ int catchType = exceptionInfo.u2catchType;
+
+ // Exclude any subroutine invocations that jump out of the try block,
+ // by adding a try block before (and later on, after) each invocation.
+ for (int offset = startPC; offset < endPC; offset++)
+ {
+ if (branchTargetFinder.isSubroutineInvocation(offset))
+ {
+ Instruction instruction = InstructionFactory.create(codeAttribute.code, offset);
+ int instructionLength = instruction.length(offset);
+
+ // Is it a subroutine invocation?
+ if (!exceptionInfo.isApplicable(offset + ((BranchInstruction)instruction).branchOffset))
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Appending extra exception ["+startPC+" -> "+offset+"] -> "+handlerPC);
+ }
+
+ // Append a try block that ends before the subroutine invocation.
+ codeAttributeComposer.appendException(new ExceptionInfo(startPC,
+ offset,
+ handlerPC,
+ catchType));
+
+ // The next try block will start after the subroutine invocation.
+ startPC = offset + instructionLength;
+ }
+ }
+ }
+
+ if (DEBUG)
+ {
+ if (startPC == exceptionInfo.u2startPC &&
+ endPC == exceptionInfo.u2endPC)
+ {
+ System.out.println(" Appending exception ["+startPC+" -> "+endPC+"] -> "+handlerPC);
+ }
+ else
+ {
+ System.out.println(" Appending clipped exception ["+exceptionInfo.u2startPC+" -> "+exceptionInfo.u2endPC+"] ~> ["+startPC+" -> "+endPC+"] -> "+handlerPC);
+ }
+ }
+
+ // Append the exception. Note that exceptions with empty try blocks
+ // are automatically ignored.
+ codeAttributeComposer.appendException(new ExceptionInfo(startPC,
+ endPC,
+ handlerPC,
+ catchType));
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/Preverifier.java b/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/Preverifier.java
new file mode 100644
index 0000000000..2f5f51d567
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/Preverifier.java
@@ -0,0 +1,68 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.preverify;
+
+import proguard.Configuration;
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AllAttributeVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This class can preverify methods in program class pools, according to a given
+ * configuration.
+ *
+ * @author Eric Lafortune
+ */
+public class Preverifier
+{
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new Preverifier.
+ */
+ public Preverifier(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Performs preverification of the given program class pool.
+ */
+ public void execute(ClassPool programClassPool)
+ {
+ // Clean up any old visitor info.
+ programClassPool.classesAccept(new ClassCleaner());
+
+ // Preverify all methods.
+ // Classes for JME must be preverified.
+ // Classes for JSE 6 may optionally be preverified.
+ // Classes for JSE 7 or higher must be preverified.
+ programClassPool.classesAccept(
+ new ClassVersionFilter(configuration.microEdition ?
+ ClassConstants.CLASS_VERSION_1_0 :
+ ClassConstants.CLASS_VERSION_1_6,
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new CodePreverifier(configuration.microEdition)))));
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/SubroutineInliner.java b/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/SubroutineInliner.java
new file mode 100644
index 0000000000..90701ee3dd
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/preverify/SubroutineInliner.java
@@ -0,0 +1,73 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.preverify;
+
+import proguard.Configuration;
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.AllAttributeVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This class can inline subroutines in methods. This is generally useful (i.e.
+ * required) for preverifying code.
+ *
+ * @author Eric Lafortune
+ */
+public class SubroutineInliner
+{
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new SubroutineInliner.
+ */
+ public SubroutineInliner(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Performs subroutine inlining of the given program class pool.
+ */
+ public void execute(ClassPool programClassPool)
+ {
+ // Clean up any old visitor info.
+ programClassPool.classesAccept(new ClassCleaner());
+
+ // Inline all subroutines.
+ ClassVisitor inliner =
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new CodeSubroutineInliner()));
+
+ // In Java Standard Edition, only class files from Java 6 or higher
+ // should be preverified.
+ if (!configuration.microEdition)
+ {
+ inliner =
+ new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_6,
+ inliner);
+ }
+
+ programClassPool.classesAccept(inliner);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FrameInfo.java b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FrameInfo.java
new file mode 100644
index 0000000000..a87db0c192
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FrameInfo.java
@@ -0,0 +1,108 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.retrace;
+
+/**
+ * This class represents the class name, field name, method name, etc.
+ * possibly found in a stack frame. Values that are not defined are null.
+ */
+public class FrameInfo
+{
+ private final String className;
+ private final String sourceFile;
+ private final int lineNumber;
+ private final String type;
+ private final String fieldName;
+ private final String methodName;
+ private final String arguments;
+
+
+ /**
+ * Creates a new FrameInfo with the given information.
+ * Any undefined values can be null.
+ */
+ public FrameInfo(String className,
+ String sourceFile,
+ int lineNumber,
+ String type,
+ String fieldName,
+ String methodName,
+ String arguments)
+ {
+ this.className = className;
+ this.sourceFile = sourceFile;
+ this.lineNumber = lineNumber;
+ this.type = type;
+ this.fieldName = fieldName;
+ this.methodName = methodName;
+ this.arguments = arguments;
+ }
+
+
+ public String getClassName()
+ {
+ return className;
+ }
+
+
+ public String getSourceFile()
+ {
+ return sourceFile;
+ }
+
+
+ public int getLineNumber()
+ {
+ return lineNumber;
+ }
+
+
+ public String getType()
+ {
+ return type;
+ }
+
+
+ public String getFieldName()
+ {
+ return fieldName;
+ }
+
+
+ public String getMethodName()
+ {
+ return methodName;
+ }
+
+
+ public String getArguments()
+ {
+ return arguments;
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return FrameInfo.class.getName() + "(class=["+className+"], line=["+lineNumber+"], type=["+type+"], field=["+fieldName+"], method=["+methodName+"], arguments=["+arguments+"]";
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FramePattern.java b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FramePattern.java
new file mode 100644
index 0000000000..e3eab12569
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FramePattern.java
@@ -0,0 +1,303 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.retrace;
+
+import proguard.classfile.util.ClassUtil;
+
+import java.util.regex.*;
+
+/**
+ * This class can parse and format lines that represent stack frames
+ * matching a given regular expression.
+ *
+ * @author Eric Lafortune
+ */
+public class FramePattern
+{
+ // The pattern matcher has problems with \\b against some unicode
+ // characters, so we're no longer using \\b for classes and class members.
+ private static final String REGEX_CLASS = "(?:[^\\s\":./()]+\\.)*[^\\s\":./()]+";
+ private static final String REGEX_CLASS_SLASH = "(?:[^\\s\":./()]+/)*[^\\s\":./()]+";
+ private static final String REGEX_SOURCE_FILE = "[^:()]*";
+ private static final String REGEX_LINE_NUMBER = "-?\\b\\d+\\b";
+ private static final String REGEX_TYPE = REGEX_CLASS + "(?:\\[\\])*";
+ private static final String REGEX_MEMBER = "<?[^\\s\":./()]+>?";
+ private static final String REGEX_ARGUMENTS = "(?:" + REGEX_TYPE + "(?:\\s*,\\s*" + REGEX_TYPE + ")*)?";
+
+ private final char[] expressionTypes = new char[32];
+ private final int expressionTypeCount;
+ private final Pattern pattern;
+ private final boolean verbose;
+
+
+ /**
+ * Creates a new FramePattern.
+ */
+ public FramePattern(String regularExpression, boolean verbose)
+ {
+ // Construct the regular expression.
+ StringBuffer expressionBuffer = new StringBuffer(regularExpression.length() + 32);
+
+ int expressionTypeCount = 0;
+ int index = 0;
+ while (true)
+ {
+ int nextIndex = regularExpression.indexOf('%', index);
+ if (nextIndex < 0 ||
+ nextIndex == regularExpression.length()-1 ||
+ expressionTypeCount == expressionTypes.length)
+ {
+ break;
+ }
+
+ // Copy a literal piece of the input line.
+ expressionBuffer.append(regularExpression.substring(index, nextIndex));
+ expressionBuffer.append('(');
+
+ char expressionType = regularExpression.charAt(nextIndex + 1);
+ switch(expressionType)
+ {
+ case 'c':
+ expressionBuffer.append(REGEX_CLASS);
+ break;
+
+ case 'C':
+ expressionBuffer.append(REGEX_CLASS_SLASH);
+ break;
+
+ case 's':
+ expressionBuffer.append(REGEX_SOURCE_FILE);
+ break;
+
+ case 'l':
+ expressionBuffer.append(REGEX_LINE_NUMBER);
+ break;
+
+ case 't':
+ expressionBuffer.append(REGEX_TYPE);
+ break;
+
+ case 'f':
+ expressionBuffer.append(REGEX_MEMBER);
+ break;
+
+ case 'm':
+ expressionBuffer.append(REGEX_MEMBER);
+ break;
+
+ case 'a':
+ expressionBuffer.append(REGEX_ARGUMENTS);
+ break;
+ }
+
+ expressionBuffer.append(')');
+
+ expressionTypes[expressionTypeCount++] = expressionType;
+
+ index = nextIndex + 2;
+ }
+
+ // Copy the last literal piece of the input line.
+ expressionBuffer.append(regularExpression.substring(index));
+
+ this.expressionTypeCount = expressionTypeCount;
+ this.pattern = Pattern.compile(expressionBuffer.toString());
+ this.verbose = verbose;
+ }
+
+
+ /**
+ * Parses all frame information from a given line.
+ * @param line a line that represents a stack frame.
+ * @return the parsed information, or null if the line doesn't match a
+ * stack frame.
+ */
+ public FrameInfo parse(String line)
+ {
+ // Try to match it against the regular expression.
+ Matcher matcher = pattern.matcher(line);
+
+ if (!matcher.matches())
+ {
+ return null;
+ }
+
+ // The line matched the regular expression.
+ String className = null;
+ String sourceFile = null;
+ int lineNumber = 0;
+ String type = null;
+ String fieldName = null;
+ String methodName = null;
+ String arguments = null;
+
+ // Extract a class name, a line number, a type, and
+ // arguments.
+ for (int expressionTypeIndex = 0; expressionTypeIndex < expressionTypeCount; expressionTypeIndex++)
+ {
+ int startIndex = matcher.start(expressionTypeIndex + 1);
+ if (startIndex >= 0)
+ {
+ String match = matcher.group(expressionTypeIndex + 1);
+
+ char expressionType = expressionTypes[expressionTypeIndex];
+ switch (expressionType)
+ {
+ case 'c':
+ className = match;
+ break;
+
+ case 'C':
+ className = ClassUtil.externalClassName(match);
+ break;
+
+ case 's':
+ sourceFile = match;
+ break;
+
+ case 'l':
+ lineNumber = Integer.parseInt(match);
+ break;
+
+ case 't':
+ type = match;
+ break;
+
+ case 'f':
+ fieldName = match;
+ break;
+
+ case 'm':
+ methodName = match;
+ break;
+
+ case 'a':
+ arguments = match;
+ break;
+ }
+ }
+ }
+
+ return new FrameInfo(className,
+ sourceFile,
+ lineNumber,
+ type,
+ fieldName,
+ methodName,
+ arguments);
+ }
+
+
+ /**
+ * Formats the given frame information based on the given template line.
+ * It is the reverse of {@link #parse(String)}, but optionally with
+ * different frame information.
+ * @param line a template line that represents a stack frame.
+ * @param frameInfo information about a stack frame.
+ * @return the formatted line, or null if the line doesn't match a
+ * stack frame.
+ */
+ public String format(String line, FrameInfo frameInfo)
+ {
+ // Try to match it against the regular expression.
+ Matcher matcher = pattern.matcher(line);
+
+ if (!matcher.matches())
+ {
+ return null;
+ }
+
+ StringBuffer formattedBuffer = new StringBuffer();
+
+ int lineIndex = 0;
+ for (int expressionTypeIndex = 0; expressionTypeIndex < expressionTypeCount; expressionTypeIndex++)
+ {
+ int startIndex = matcher.start(expressionTypeIndex + 1);
+ if (startIndex >= 0)
+ {
+ int endIndex = matcher.end(expressionTypeIndex + 1);
+ String match = matcher.group(expressionTypeIndex + 1);
+
+ // Copy a literal piece of the input line.
+ formattedBuffer.append(line.substring(lineIndex, startIndex));
+
+ // Copy a matched and translated piece of the input line.
+ char expressionType = expressionTypes[expressionTypeIndex];
+ switch (expressionType)
+ {
+ case 'c':
+ formattedBuffer.append(frameInfo.getClassName());
+ break;
+
+ case 'C':
+ formattedBuffer.append(ClassUtil.internalClassName(frameInfo.getClassName()));
+ break;
+
+ case 's':
+ formattedBuffer.append(frameInfo.getSourceFile());
+ break;
+
+ case 'l':
+ formattedBuffer.append(frameInfo.getLineNumber());
+ break;
+
+ case 't':
+ formattedBuffer.append(frameInfo.getType());
+ break;
+
+ case 'f':
+ if (verbose)
+ {
+ formattedBuffer.append(frameInfo.getType()).append(' ');
+ }
+ formattedBuffer.append(frameInfo.getFieldName());
+ break;
+
+ case 'm':
+ if (verbose)
+ {
+ formattedBuffer.append(frameInfo.getType()).append(' ');
+ }
+ formattedBuffer.append(frameInfo.getMethodName());
+ if (verbose)
+ {
+ formattedBuffer.append('(').append(frameInfo.getArguments()).append(')');
+ }
+ break;
+
+ case 'a':
+ formattedBuffer.append(frameInfo.getArguments());
+ break;
+ }
+
+ // Skip the original element whose replacement value
+ // has just been appended.
+ lineIndex = endIndex;
+ }
+ }
+
+ // Copy the last literal piece of the input line.
+ formattedBuffer.append(line.substring(lineIndex));
+
+ // Return the formatted line.
+ return formattedBuffer.toString();
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FrameRemapper.java b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FrameRemapper.java
new file mode 100644
index 0000000000..083a29e9d1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/FrameRemapper.java
@@ -0,0 +1,435 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.retrace;
+
+import proguard.obfuscate.MappingProcessor;
+
+import java.util.*;
+
+/**
+ * This class accumulates mapping information and then transforms stack frames
+ * accordingly.
+ *
+ * @author Eric Lafortune
+ */
+public class FrameRemapper implements MappingProcessor
+{
+ // Obfuscated class name -> original class name.
+ private final Map<String,String> classMap = new HashMap<String,String>();
+
+ // Original class name -> obfuscated member name -> member info set.
+ private final Map<String,Map<String,Set<FieldInfo>>> classFieldMap = new HashMap<String,Map<String,Set<FieldInfo>>>();
+ private final Map<String,Map<String,Set<MethodInfo>>> classMethodMap = new HashMap<String,Map<String,Set<MethodInfo>>>();
+
+
+ /**
+ * Transforms the given obfuscated frame back to one or more original frames.
+ */
+ public List<FrameInfo> transform(FrameInfo obfuscatedFrame)
+ {
+ // First remap the class name.
+ String originalClassName = originalClassName(obfuscatedFrame.getClassName());
+ if (originalClassName == null)
+ {
+ return null;
+ }
+
+ List<FrameInfo> originalFrames = new ArrayList<FrameInfo>();
+
+ // Create any transformed frames with remapped field names.
+ transformFieldInfo(obfuscatedFrame,
+ originalClassName,
+ originalFrames);
+
+ // Create any transformed frames with remapped method names.
+ transformMethodInfo(obfuscatedFrame,
+ originalClassName,
+ originalFrames);
+
+ if (originalFrames.isEmpty())
+ {
+ // Create a transformed frame with the remapped class name.
+ originalFrames.add(new FrameInfo(originalClassName,
+ sourceFileName(originalClassName),
+ obfuscatedFrame.getLineNumber(),
+ obfuscatedFrame.getType(),
+ obfuscatedFrame.getFieldName(),
+ obfuscatedFrame.getMethodName(),
+ obfuscatedFrame.getArguments()));
+ }
+
+ return originalFrames;
+ }
+
+
+ /**
+ * Transforms the obfuscated frame into one or more original frames,
+ * if the frame contains information about a field that can be remapped.
+ * @param obfuscatedFrame the obfuscated frame.
+ * @param originalFieldFrames the list in which remapped frames can be
+ * collected.
+ */
+ private void transformFieldInfo(FrameInfo obfuscatedFrame,
+ String originalClassName,
+ List<FrameInfo> originalFieldFrames)
+ {
+ // Class name -> obfuscated field names.
+ Map<String,Set<FieldInfo>> fieldMap = classFieldMap.get(originalClassName);
+ if (fieldMap != null)
+ {
+ // Obfuscated field names -> fields.
+ String obfuscatedFieldName = obfuscatedFrame.getFieldName();
+ Set<FieldInfo> fieldSet = fieldMap.get(obfuscatedFieldName);
+ if (fieldSet != null)
+ {
+ String obfuscatedType = obfuscatedFrame.getType();
+ String originalType = obfuscatedType == null ? null :
+ originalType(obfuscatedType);
+
+ // Find all matching fields.
+ Iterator<FieldInfo> fieldInfoIterator = fieldSet.iterator();
+ while (fieldInfoIterator.hasNext())
+ {
+ FieldInfo fieldInfo = fieldInfoIterator.next();
+ if (fieldInfo.matches(originalType))
+ {
+ originalFieldFrames.add(new FrameInfo(fieldInfo.originalClassName,
+ sourceFileName(fieldInfo.originalClassName),
+ obfuscatedFrame.getLineNumber(),
+ fieldInfo.originalType,
+ fieldInfo.originalName,
+ obfuscatedFrame.getMethodName(),
+ obfuscatedFrame.getArguments()));
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Transforms the obfuscated frame into one or more original frames,
+ * if the frame contains information about a method that can be remapped.
+ * @param obfuscatedFrame the obfuscated frame.
+ * @param originalMethodFrames the list in which remapped frames can be
+ * collected.
+ */
+ private void transformMethodInfo(FrameInfo obfuscatedFrame,
+ String originalClassName,
+ List<FrameInfo> originalMethodFrames)
+ {
+ // Class name -> obfuscated method names.
+ Map<String,Set<MethodInfo>> methodMap = classMethodMap.get(originalClassName);
+ if (methodMap != null)
+ {
+ // Obfuscated method names -> methods.
+ String obfuscatedMethodName = obfuscatedFrame.getMethodName();
+ Set<MethodInfo> methodSet = methodMap.get(obfuscatedMethodName);
+ if (methodSet != null)
+ {
+ int obfuscatedLineNumber = obfuscatedFrame.getLineNumber();
+
+ String obfuscatedType = obfuscatedFrame.getType();
+ String originalType = obfuscatedType == null ? null :
+ originalType(obfuscatedType);
+
+ String obfuscatedArguments = obfuscatedFrame.getArguments();
+ String originalArguments = obfuscatedArguments == null ? null :
+ originalArguments(obfuscatedArguments);
+
+ // Find all matching methods.
+ Iterator<MethodInfo> methodInfoIterator = methodSet.iterator();
+ while (methodInfoIterator.hasNext())
+ {
+ MethodInfo methodInfo = methodInfoIterator.next();
+ if (methodInfo.matches(obfuscatedLineNumber,
+ originalType,
+ originalArguments))
+ {
+ // Do we have a different original first line number?
+ // We're allowing unknown values, represented as 0.
+ int lineNumber = obfuscatedFrame.getLineNumber();
+ if (methodInfo.originalFirstLineNumber != methodInfo.obfuscatedFirstLineNumber)
+ {
+ // Do we have an original line number range and
+ // sufficient information to shift the line number?
+ lineNumber = methodInfo.originalLastLineNumber != 0 &&
+ methodInfo.originalLastLineNumber != methodInfo.originalFirstLineNumber &&
+ methodInfo.obfuscatedFirstLineNumber != 0 &&
+ lineNumber != 0 ?
+ methodInfo.originalFirstLineNumber - methodInfo.obfuscatedFirstLineNumber + lineNumber :
+ methodInfo.originalFirstLineNumber;
+ }
+
+ originalMethodFrames.add(new FrameInfo(methodInfo.originalClassName,
+ sourceFileName(methodInfo.originalClassName),
+ lineNumber,
+ methodInfo.originalType,
+ obfuscatedFrame.getFieldName(),
+ methodInfo.originalName,
+ methodInfo.originalArguments));
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Returns the original argument types.
+ */
+ private String originalArguments(String obfuscatedArguments)
+ {
+ StringBuilder originalArguments = new StringBuilder();
+
+ int startIndex = 0;
+ while (true)
+ {
+ int endIndex = obfuscatedArguments.indexOf(',', startIndex);
+ if (endIndex < 0)
+ {
+ break;
+ }
+
+ originalArguments.append(originalType(obfuscatedArguments.substring(startIndex, endIndex).trim())).append(',');
+
+ startIndex = endIndex + 1;
+ }
+
+ originalArguments.append(originalType(obfuscatedArguments.substring(startIndex).trim()));
+
+ return originalArguments.toString();
+ }
+
+
+ /**
+ * Returns the original type.
+ */
+ private String originalType(String obfuscatedType)
+ {
+ int index = obfuscatedType.indexOf('[');
+
+ return index >= 0 ?
+ originalClassName(obfuscatedType.substring(0, index)) + obfuscatedType.substring(index) :
+ originalClassName(obfuscatedType);
+ }
+
+
+ /**
+ * Returns the original class name.
+ */
+ private String originalClassName(String obfuscatedClassName)
+ {
+ String originalClassName = classMap.get(obfuscatedClassName);
+
+ return originalClassName != null ?
+ originalClassName :
+ obfuscatedClassName;
+ }
+
+
+ /**
+ * Returns the Java source file name that typically corresponds to the
+ * given class name.
+ */
+ private String sourceFileName(String className)
+ {
+ int index1 = className.lastIndexOf('.') + 1;
+ int index2 = className.indexOf('$', index1);
+
+ return (index2 > 0 ?
+ className.substring(index1, index2) :
+ className.substring(index1)) +
+ ".java";
+ }
+
+
+ // Implementations for MappingProcessor.
+
+ public boolean processClassMapping(String className,
+ String newClassName)
+ {
+ // Obfuscated class name -> original class name.
+ classMap.put(newClassName, className);
+
+ return true;
+ }
+
+
+ public void processFieldMapping(String className,
+ String fieldType,
+ String fieldName,
+ String newClassName,
+ String newFieldName)
+ {
+ // Obfuscated class name -> obfuscated field names.
+ Map<String,Set<FieldInfo>> fieldMap = classFieldMap.get(newClassName);
+ if (fieldMap == null)
+ {
+ fieldMap = new HashMap<String,Set<FieldInfo>>();
+ classFieldMap.put(newClassName, fieldMap);
+ }
+
+ // Obfuscated field name -> fields.
+ Set<FieldInfo> fieldSet = fieldMap.get(newFieldName);
+ if (fieldSet == null)
+ {
+ fieldSet = new LinkedHashSet<FieldInfo>();
+ fieldMap.put(newFieldName, fieldSet);
+ }
+
+ // Add the field information.
+ fieldSet.add(new FieldInfo(className,
+ fieldType,
+ fieldName));
+ }
+
+
+ public void processMethodMapping(String className,
+ int firstLineNumber,
+ int lastLineNumber,
+ String methodReturnType,
+ String methodName,
+ String methodArguments,
+ String newClassName,
+ int newFirstLineNumber,
+ int newLastLineNumber,
+ String newMethodName)
+ {
+ // Original class name -> obfuscated method names.
+ Map<String,Set<MethodInfo>> methodMap = classMethodMap.get(newClassName);
+ if (methodMap == null)
+ {
+ methodMap = new HashMap<String,Set<MethodInfo>>();
+ classMethodMap.put(newClassName, methodMap);
+ }
+
+ // Obfuscated method name -> methods.
+ Set<MethodInfo> methodSet = methodMap.get(newMethodName);
+ if (methodSet == null)
+ {
+ methodSet = new LinkedHashSet<MethodInfo>();
+ methodMap.put(newMethodName, methodSet);
+ }
+
+ // Add the method information.
+ methodSet.add(new MethodInfo(newFirstLineNumber,
+ newLastLineNumber,
+ className,
+ firstLineNumber,
+ lastLineNumber,
+ methodReturnType,
+ methodName,
+ methodArguments));
+ }
+
+
+ /**
+ * Information about the original version and the obfuscated version of
+ * a field (without the obfuscated class name or field name).
+ */
+ private static class FieldInfo
+ {
+ private final String originalClassName;
+ private final String originalType;
+ private final String originalName;
+
+
+ /**
+ * Creates a new FieldInfo with the given properties.
+ */
+ private FieldInfo(String originalClassName,
+ String originalType,
+ String originalName)
+ {
+ this.originalClassName = originalClassName;
+ this.originalType = originalType;
+ this.originalName = originalName;
+ }
+
+
+ /**
+ * Returns whether the given type matches the original type of this field.
+ * The given type may be a null wildcard.
+ */
+ private boolean matches(String originalType)
+ {
+ return
+ originalType == null || originalType.equals(this.originalType);
+ }
+ }
+
+
+ /**
+ * Information about the original version and the obfuscated version of
+ * a method (without the obfuscated class name or method name).
+ */
+ private static class MethodInfo
+ {
+ private final int obfuscatedFirstLineNumber;
+ private final int obfuscatedLastLineNumber;
+ private final String originalClassName;
+ private final int originalFirstLineNumber;
+ private final int originalLastLineNumber;
+ private final String originalType;
+ private final String originalName;
+ private final String originalArguments;
+
+
+ /**
+ * Creates a new MethodInfo with the given properties.
+ */
+ private MethodInfo(int obfuscatedFirstLineNumber,
+ int obfuscatedLastLineNumber,
+ String originalClassName,
+ int originalFirstLineNumber,
+ int originalLastLineNumber,
+ String originalType,
+ String originalName,
+ String originalArguments)
+ {
+ this.obfuscatedFirstLineNumber = obfuscatedFirstLineNumber;
+ this.obfuscatedLastLineNumber = obfuscatedLastLineNumber;
+ this.originalType = originalType;
+ this.originalArguments = originalArguments;
+ this.originalClassName = originalClassName;
+ this.originalName = originalName;
+ this.originalFirstLineNumber = originalFirstLineNumber;
+ this.originalLastLineNumber = originalLastLineNumber;
+ }
+
+
+ /**
+ * Returns whether the given properties match the properties of this
+ * method. The given properties may be null wildcards.
+ */
+ private boolean matches(int obfuscatedLineNumber,
+ String originalType,
+ String originalArguments)
+ {
+ return
+ (obfuscatedLineNumber == 0 ? obfuscatedLastLineNumber == 0 :
+ obfuscatedFirstLineNumber <= obfuscatedLineNumber && obfuscatedLineNumber <= obfuscatedLastLineNumber) &&
+ (originalType == null || originalType.equals(this.originalType)) &&
+ (originalArguments == null || originalArguments.equals(this.originalArguments));
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/MANIFEST.MF b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/MANIFEST.MF
new file mode 100644
index 0000000000..42c9800c82
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: proguard.retrace.ReTrace
+Class-Path: proguard.jar
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/ReTrace.java b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/ReTrace.java
new file mode 100644
index 0000000000..182941bd7d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/ReTrace.java
@@ -0,0 +1,305 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.retrace;
+
+import proguard.obfuscate.MappingReader;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Tool for de-obfuscating stack traces of applications that were obfuscated
+ * with ProGuard.
+ *
+ * @author Eric Lafortune
+ */
+public class ReTrace
+{
+ private static final String USAGE = "Usage: java proguard.retrace.ReTrace [-regex <regex>] [-verbose] <mapping_file> [<stacktrace_file>]";
+ private static final String REGEX_OPTION = "-regex";
+ private static final String VERBOSE_OPTION = "-verbose";
+
+ public static final String STACK_TRACE_EXPRESSION = "(?:.*?\\bat\\s+%c\\.%m\\s*\\(%s(?::%l)?\\)\\s*(?:~\\[.*\\])?)|(?:(?:.*?[:\"]\\s+)?%c(?::.*)?)";
+
+
+ // The settings.
+ private final String regularExpression;
+ private final boolean verbose;
+ private final File mappingFile;
+
+
+ /**
+ * Creates a new ReTrace instance.
+ * @param regularExpression the regular expression for parsing the lines in
+ * the stack trace.
+ * @param verbose specifies whether the de-obfuscated stack trace
+ * should be verbose.
+ * @param mappingFile the mapping file that was written out by
+ * ProGuard.
+ */
+ public ReTrace(String regularExpression,
+ boolean verbose,
+ File mappingFile)
+ {
+ this.regularExpression = regularExpression;
+ this.verbose = verbose;
+ this.mappingFile = mappingFile;
+ }
+
+
+ /**
+ * De-obfuscates a given stack trace.
+ * @param stackTraceReader a reader for the obfuscated stack trace.
+ * @param stackTraceWriter a writer for the de-obfuscated stack trace.
+ */
+ public void retrace(LineNumberReader stackTraceReader,
+ PrintWriter stackTraceWriter) throws IOException
+ {
+ // Create a pattern for stack frames.
+ FramePattern pattern = new FramePattern(regularExpression, verbose);
+
+ // Create a remapper.
+ FrameRemapper mapper = new FrameRemapper();
+
+ // Read the mapping file.
+ MappingReader mappingReader = new MappingReader(mappingFile);
+ mappingReader.pump(mapper);
+
+ // Read and process the lines of the stack trace.
+ while (true)
+ {
+ // Read a line.
+ String obfuscatedLine = stackTraceReader.readLine();
+ if (obfuscatedLine == null)
+ {
+ break;
+ }
+
+ // Try to match it against the regular expression.
+ FrameInfo obfuscatedFrame = pattern.parse(obfuscatedLine);
+ if (obfuscatedFrame != null)
+ {
+ // Transform the obfuscated frame back to one or more
+ // original frames.
+ Iterator<FrameInfo> retracedFrames =
+ mapper.transform(obfuscatedFrame).iterator();
+
+ String previousLine = null;
+
+ while (retracedFrames.hasNext())
+ {
+ // Retrieve the next retraced frame.
+ FrameInfo retracedFrame = retracedFrames.next();
+
+ // Format the retraced line.
+ String retracedLine =
+ pattern.format(obfuscatedLine, retracedFrame);
+
+ // Clear the common first part of ambiguous alternative
+ // retraced lines, to present a cleaner list of
+ // alternatives.
+ String trimmedLine =
+ previousLine != null &&
+ obfuscatedFrame.getLineNumber() == 0 ?
+ trim(retracedLine, previousLine) :
+ retracedLine;
+
+ // Print out the retraced line.
+ if (trimmedLine != null)
+ {
+ stackTraceWriter.println(trimmedLine);
+ }
+
+ previousLine = retracedLine;
+ }
+ }
+ else
+ {
+ // Print out the original line.
+ stackTraceWriter.println(obfuscatedLine);
+ }
+ }
+
+ stackTraceWriter.flush();
+ }
+
+
+ /**
+ * Returns the first given string, with any leading characters that it has
+ * in common with the second string replaced by spaces.
+ */
+ private String trim(String string1, String string2)
+ {
+ StringBuilder line = new StringBuilder(string1);
+
+ // Find the common part.
+ int trimEnd = firstNonCommonIndex(string1, string2);
+ if (trimEnd == string1.length())
+ {
+ return null;
+ }
+
+ // Don't clear the last identifier characters.
+ trimEnd = lastNonIdentifierIndex(string1, trimEnd) + 1;
+
+ // Clear the common characters.
+ for (int index = 0; index < trimEnd; index++)
+ {
+ if (!Character.isWhitespace(string1.charAt(index)))
+ {
+ line.setCharAt(index, ' ');
+ }
+ }
+
+ return line.toString();
+ }
+
+
+ /**
+ * Returns the index of the first character that is not the same in both
+ * given strings.
+ */
+ private int firstNonCommonIndex(String string1, String string2)
+ {
+ int index = 0;
+ while (index < string1.length() &&
+ index < string2.length() &&
+ string1.charAt(index) == string2.charAt(index))
+ {
+ index++;
+ }
+
+ return index;
+ }
+
+
+ /**
+ * Returns the index of the last character that is not an identifier
+ * character in the given string, at or before the given index.
+ */
+ private int lastNonIdentifierIndex(String line, int index)
+ {
+ while (index >= 0 &&
+ Character.isJavaIdentifierPart(line.charAt(index)))
+ {
+ index--;
+ }
+
+ return index;
+ }
+
+
+ /**
+ * The main program for ReTrace.
+ */
+ public static void main(String[] args)
+ {
+ // Parse the arguments.
+ if (args.length < 1)
+ {
+ System.err.println(USAGE);
+ System.exit(-1);
+ }
+
+ String regularExpresssion = STACK_TRACE_EXPRESSION;
+ boolean verbose = false;
+
+ int argumentIndex = 0;
+ while (argumentIndex < args.length)
+ {
+ String arg = args[argumentIndex];
+ if (arg.equals(REGEX_OPTION))
+ {
+ regularExpresssion = args[++argumentIndex];
+ }
+ else if (arg.equals(VERBOSE_OPTION))
+ {
+ verbose = true;
+ }
+ else
+ {
+ break;
+ }
+
+ argumentIndex++;
+ }
+
+ if (argumentIndex >= args.length)
+ {
+ System.err.println(USAGE);
+ System.exit(-1);
+ }
+
+ // Convert the arguments into File instances.
+ File mappingFile = new File(args[argumentIndex++]);
+ File stackTraceFile = argumentIndex < args.length ?
+ new File(args[argumentIndex]) :
+ null;
+
+ try
+ {
+ // Open the input stack trace. We're always using the UTF-8
+ // character encoding, even for reading from the standard
+ // input.
+ LineNumberReader reader =
+ new LineNumberReader(
+ new BufferedReader(
+ new InputStreamReader(stackTraceFile == null ? System.in :
+ new FileInputStream(stackTraceFile), "UTF-8")));
+
+ // Open the output stack trace, again using UTF-8 encoding.
+ PrintWriter writer =
+ new PrintWriter(new OutputStreamWriter(System.out, "UTF-8"));
+
+ try
+ {
+ // Execute ReTrace with the collected settings.
+ new ReTrace(regularExpresssion, verbose, mappingFile)
+ .retrace(reader, writer);
+ }
+ finally
+ {
+ // Close the input stack trace if it was a file.
+ if (stackTraceFile != null)
+ {
+ reader.close();
+ }
+ }
+ }
+ catch (IOException ex)
+ {
+ if (verbose)
+ {
+ // Print a verbose stack trace.
+ ex.printStackTrace();
+ }
+ else
+ {
+ // Print just the stack trace message.
+ System.err.println("Error: "+ex.getMessage());
+ }
+
+ System.exit(1);
+ }
+
+ System.exit(0);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/package.html
new file mode 100644
index 0000000000..a35ce214a0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/retrace/package.html
@@ -0,0 +1,4 @@
+<body>
+This package contains the main ReTrace application.
+ReTrace can de-obfuscate stack traces of obfuscated programs.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/AnnotationUsageMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/AnnotationUsageMarker.java
new file mode 100644
index 0000000000..cd0f5fae1e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/AnnotationUsageMarker.java
@@ -0,0 +1,327 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.Attribute;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This AttributeVisitor recursively marks all necessary annotation information
+ * in the attributes that it visits.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class AnnotationUsageMarker
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor,
+ ConstantVisitor,
+ ClassVisitor,
+ MemberVisitor
+{
+ private final UsageMarker usageMarker;
+
+ // Fields acting as a return parameters for several methods.
+ private boolean attributeUsed;
+ private boolean annotationUsed;
+ private boolean allClassesUsed;
+ private boolean methodUsed;
+
+
+ /**
+ * Creates a new AnnotationUsageMarker.
+ * @param usageMarker the usage marker that is used to mark the classes
+ * and class members.
+ */
+ public AnnotationUsageMarker(UsageMarker usageMarker)
+ {
+ this.usageMarker = usageMarker;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ // Mark the necessary annotation information.
+ attributeUsed = false;
+ annotationsAttribute.annotationsAccept(clazz, this);
+
+ if (attributeUsed)
+ {
+ // We got a positive used flag, so some annotation is being used.
+ // Mark this attribute as being used as well.
+ usageMarker.markAsUsed(annotationsAttribute);
+
+ markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
+ }
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Mark the necessary annotation information.
+ attributeUsed = false;
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+
+ if (attributeUsed)
+ {
+ // We got a positive used flag, so some annotation is being used.
+ // Mark this attribute as being used as well.
+ usageMarker.markAsUsed(parameterAnnotationsAttribute);
+
+ markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
+ }
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Mark the necessary annotation information in any annotation elements.
+ annotationDefaultAttribute.defaultValueAccept(clazz, this);
+
+ // Always mark annotation defaults.
+ usageMarker.markAsUsed(annotationDefaultAttribute);
+
+ markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ if (isReferencedClassUsed(annotation))
+ {
+ // Mark the annotation as being used.
+ usageMarker.markAsUsed(annotation);
+
+ markConstant(clazz, annotation.u2typeIndex);
+
+ // Mark the necessary element values.
+ annotation.elementValuesAccept(clazz, this);
+
+ // The return values.
+ annotationUsed = true;
+ attributeUsed = true;
+ }
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+ {
+ if (isReferencedMethodUsed(constantElementValue))
+ {
+ // Mark the element value as being used.
+ usageMarker.markAsUsed(constantElementValue);
+
+ markConstant(clazz, constantElementValue.u2elementNameIndex);
+ markConstant(clazz, constantElementValue.u2constantValueIndex);
+ }
+ }
+
+
+ public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+ {
+ if (isReferencedMethodUsed(enumConstantElementValue))
+ {
+ // Check the referenced classes.
+ allClassesUsed = true;
+ enumConstantElementValue.referencedClassesAccept(this);
+
+ if (allClassesUsed)
+ {
+ // Mark the element value as being used.
+ usageMarker.markAsUsed(enumConstantElementValue);
+
+ markConstant(clazz, enumConstantElementValue.u2elementNameIndex);
+ markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
+ markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
+ }
+ }
+ }
+
+
+ public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+ {
+ if (isReferencedMethodUsed(classElementValue))
+ {
+ // Mark the element value as being used.
+ usageMarker.markAsUsed(classElementValue);
+
+ markConstant(clazz, classElementValue.u2elementNameIndex);
+ markConstant(clazz, classElementValue.u2classInfoIndex);
+
+ // Mark the referenced classes, since they can be retrieved from
+ // the annotation and then used.
+ // TODO: This could mark more annotation methods, affecting other annotations.
+ classElementValue.referencedClassesAccept(usageMarker);
+ }
+ }
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ if (isReferencedMethodUsed(annotationElementValue))
+ {
+ boolean oldAnnotationUsed = annotationUsed;
+
+ // Check and mark the contained annotation.
+ annotationUsed = false;
+ annotationElementValue.annotationAccept(clazz, this);
+
+ if (annotationUsed)
+ {
+ // Mark the element value as being used.
+ usageMarker.markAsUsed(annotationElementValue);
+
+ markConstant(clazz, annotationElementValue.u2elementNameIndex);
+ }
+
+ annotationUsed = oldAnnotationUsed;
+ }
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ if (isReferencedMethodUsed(arrayElementValue))
+ {
+ // Check and mark the contained element values.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+
+ // Mark the element value as being used.
+ usageMarker.markAsUsed(arrayElementValue);
+
+ markConstant(clazz, arrayElementValue.u2elementNameIndex);
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ usageMarker.markAsUsed(constant);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Is the class constant marked as being used?
+ if (!usageMarker.isUsed(classConstant))
+ {
+ // Check the referenced class.
+ allClassesUsed = true;
+ classConstant.referencedClassAccept(this);
+
+ // Is the referenced class marked as being used?
+ if (allClassesUsed)
+ {
+ // Mark the class constant and its Utf8 constant.
+ usageMarker.markAsUsed(classConstant);
+
+ markConstant(clazz, classConstant.u2nameIndex);
+ }
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ allClassesUsed &= usageMarker.isUsed(programClass);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ methodUsed = usageMarker.isUsed(programMethod);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass LibraryClass, LibraryMethod libraryMethod)
+ {
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the annotation class has been marked as being used.
+ */
+ private boolean isReferencedClassUsed(Annotation annotation)
+ {
+ // Check if the referenced class is being used.
+ allClassesUsed = true;
+ annotation.referencedClassAccept(this);
+
+ return allClassesUsed;
+ }
+
+
+ /**
+ * Returns whether the annotation method has been marked as being used.
+ */
+ private boolean isReferencedMethodUsed(ElementValue elementValue)
+ {
+ // Check if the referenced method is being used.
+ methodUsed = true;
+ elementValue.referencedMethodAccept(this);
+
+ return methodUsed;
+ }
+
+
+ /**
+ * Marks the specified constant pool entry.
+ */
+ private void markConstant(Clazz clazz, int index)
+ {
+ if (index > 0)
+ {
+ clazz.constantPoolEntryAccept(index, this);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ClassShrinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ClassShrinker.java
new file mode 100644
index 0000000000..7e7dfe10ac
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ClassShrinker.java
@@ -0,0 +1,567 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.annotation.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.editor.*;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+import java.util.Arrays;
+
+/**
+ * This ClassVisitor removes constant pool entries, class members, and other
+ * class elements that are not marked as being used.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class ClassShrinker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor,
+ AnnotationVisitor,
+ ElementValueVisitor
+{
+ private final UsageMarker usageMarker;
+
+ private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
+ private int[] bootstrapMethodIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE];
+ private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();
+ private final BootstrapMethodRemapper bootstrapMethodRemapper = new BootstrapMethodRemapper();
+
+
+ /**
+ * Creates a new ClassShrinker.
+ * @param usageMarker the usage marker that is used to mark the classes
+ * and class members.
+ */
+ public ClassShrinker(UsageMarker usageMarker)
+ {
+ this.usageMarker = usageMarker;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Shrink the arrays for constant pool, interfaces, fields, methods,
+ // and class attributes.
+ if (programClass.u2interfacesCount > 0)
+ {
+ new InterfaceDeleter(shrinkFlags(programClass.constantPool,
+ programClass.u2interfaces,
+ programClass.u2interfacesCount))
+ .visitProgramClass(programClass);
+ }
+
+ // Shrinking the constant pool also sets up an index map.
+ int newConstantPoolCount =
+ shrinkConstantPool(programClass.constantPool,
+ programClass.u2constantPoolCount);
+
+ programClass.u2fieldsCount =
+ shrinkArray(programClass.fields,
+ programClass.u2fieldsCount);
+
+ programClass.u2methodsCount =
+ shrinkArray(programClass.methods,
+ programClass.u2methodsCount);
+
+ programClass.u2attributesCount =
+ shrinkArray(programClass.attributes,
+ programClass.u2attributesCount);
+
+ // Compact the remaining fields, methods, and attributes,
+ // and remap their references to the constant pool.
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+ programClass.attributesAccept(this);
+
+ // Remap the references to the constant pool if it has shrunk.
+ if (newConstantPoolCount < programClass.u2constantPoolCount)
+ {
+ programClass.u2constantPoolCount = newConstantPoolCount;
+
+ // Remap all constant pool references.
+ constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+ constantPoolRemapper.visitProgramClass(programClass);
+ }
+
+ // Replace any unused classes in the signatures.
+ MySignatureCleaner signatureCleaner = new MySignatureCleaner();
+ programClass.fieldsAccept(new AllAttributeVisitor(signatureCleaner));
+ programClass.methodsAccept(new AllAttributeVisitor(signatureCleaner));
+ programClass.attributesAccept(signatureCleaner);
+
+ // Compact the extra field pointing to the subclasses of this class.
+ programClass.subClasses =
+ shrinkToNewArray(programClass.subClasses);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Library classes are left unchanged.
+
+ // Compact the extra field pointing to the subclasses of this class.
+ libraryClass.subClasses =
+ shrinkToNewArray(libraryClass.subClasses);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
+ {
+ // Shrink the attributes array.
+ programMember.u2attributesCount =
+ shrinkArray(programMember.attributes,
+ programMember.u2attributesCount);
+
+ // Shrink any attributes.
+ programMember.attributesAccept(programClass, this);
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Shrink the array of BootstrapMethodInfo objects.
+ int newBootstrapMethodsCount =
+ shrinkBootstrapMethodArray(bootstrapMethodsAttribute.bootstrapMethods,
+ bootstrapMethodsAttribute.u2bootstrapMethodsCount);
+
+ if (newBootstrapMethodsCount < bootstrapMethodsAttribute.u2bootstrapMethodsCount)
+ {
+ bootstrapMethodsAttribute.u2bootstrapMethodsCount = newBootstrapMethodsCount;
+
+ // Remap all constant pool references.
+ bootstrapMethodRemapper.setConstantIndexMap(bootstrapMethodIndexMap);
+ clazz.constantPoolEntriesAccept(bootstrapMethodRemapper);
+ }
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ // Shrink the array of InnerClassesInfo objects.
+ innerClassesAttribute.u2classesCount =
+ shrinkArray(innerClassesAttribute.classes,
+ innerClassesAttribute.u2classesCount);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ // Sometimes, a class is still referenced (apparently as a dummy class),
+ // but its enclosing method is not. Then remove the reference to
+ // the enclosing method.
+ // E.g. the anonymous inner class javax.swing.JList$1 is defined inside
+ // a constructor of javax.swing.JList, but it is also referenced as a
+ // dummy argument in a constructor of javax.swing.JList$ListSelectionHandler.
+ if (enclosingMethodAttribute.referencedMethod != null &&
+ !usageMarker.isUsed(enclosingMethodAttribute.referencedMethod))
+ {
+ enclosingMethodAttribute.u2nameAndTypeIndex = 0;
+
+ enclosingMethodAttribute.referencedMethod = null;
+ }
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Shrink the attributes array.
+ codeAttribute.u2attributesCount =
+ shrinkArray(codeAttribute.attributes,
+ codeAttribute.u2attributesCount);
+
+ // Shrink the attributes themselves.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Shrink the local variable info array.
+ localVariableTableAttribute.u2localVariableTableLength =
+ shrinkArray(localVariableTableAttribute.localVariableTable,
+ localVariableTableAttribute.u2localVariableTableLength);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Shrink the local variable type info array.
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength =
+ shrinkArray(localVariableTypeTableAttribute.localVariableTypeTable,
+ localVariableTypeTableAttribute.u2localVariableTypeTableLength);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ // Shrink the annotations array.
+ annotationsAttribute.u2annotationsCount =
+ shrinkArray(annotationsAttribute.annotations,
+ annotationsAttribute.u2annotationsCount);
+
+ // Shrink the annotations themselves.
+ annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Loop over all parameters.
+ for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u1parametersCount; parameterIndex++)
+ {
+ // Shrink the parameter annotations array.
+ parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex] =
+ shrinkArray(parameterAnnotationsAttribute.parameterAnnotations[parameterIndex],
+ parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]);
+ }
+
+ // Shrink the annotations themselves.
+ parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ // Implementations for AnnotationVisitor.
+
+ public void visitAnnotation(Clazz clazz, Annotation annotation)
+ {
+ // Shrink the element values array.
+ annotation.u2elementValuesCount =
+ shrinkArray(annotation.elementValues,
+ annotation.u2elementValuesCount);
+
+ // Shrink the element values themselves.
+ annotation.elementValuesAccept(clazz, this);
+ }
+
+
+ /**
+ * This AttributeVisitor updates the Utf8 constants of signatures
+ * of classes, fields, and methods.
+ */
+ private class MySignatureCleaner
+ extends SimplifiedVisitor
+ implements AttributeVisitor
+ {
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ Clazz[] referencedClasses = signatureAttribute.referencedClasses;
+ if (referencedClasses != null)
+ {
+ // Go over the classes in the signature.
+ String signature = signatureAttribute.getSignature(clazz);
+
+ DescriptorClassEnumeration classEnumeration =
+ new DescriptorClassEnumeration(signature);
+
+ int referencedClassIndex = 0;
+
+ // Start construction a new signature.
+ StringBuffer newSignatureBuffer = new StringBuffer();
+
+ newSignatureBuffer.append(classEnumeration.nextFluff());
+
+ while (classEnumeration.hasMoreClassNames())
+ {
+ String className = classEnumeration.nextClassName();
+
+ // Replace the class name if it is unused.
+ Clazz referencedClass = referencedClasses[referencedClassIndex];
+ if (referencedClass != null &&
+ !usageMarker.isUsed(referencedClass))
+ {
+ className = ClassConstants.NAME_JAVA_LANG_OBJECT;
+
+ referencedClasses[referencedClassIndex] = null;
+ }
+
+ // Use a short name if it's an inner class after a '.'
+ // separator.
+ else if (classEnumeration.isInnerClassName())
+ {
+ className = className.substring(className.lastIndexOf(ClassConstants.INNER_CLASS_SEPARATOR)+1);
+ }
+
+ referencedClassIndex++;
+
+ newSignatureBuffer.append(className);
+ newSignatureBuffer.append(classEnumeration.nextFluff());
+ }
+
+ // Update the signature.
+ ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString());
+ }
+ }
+ }
+
+
+ // Implementations for ElementValueVisitor.
+
+ public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) {}
+
+
+ public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+ {
+ // Shrink the contained annotation.
+ annotationElementValue.annotationAccept(clazz, this);
+ }
+
+
+ public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+ {
+ // Shrink the element values array.
+ arrayElementValue.u2elementValuesCount =
+ shrinkArray(arrayElementValue.elementValues,
+ arrayElementValue.u2elementValuesCount);
+
+ // Shrink the element values themselves.
+ arrayElementValue.elementValuesAccept(clazz, annotation, this);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Removes all entries that are not marked as being used from the given
+ * constant pool. Creates a map from the old indices to the new indices
+ * as a side effect.
+ * @return the new number of entries.
+ */
+ private int shrinkConstantPool(Constant[] constantPool, int length)
+ {
+ if (constantIndexMap.length < length)
+ {
+ constantIndexMap = new int[length];
+ }
+
+ int counter = 1;
+ boolean isUsed = false;
+
+ // Shift the used constant pool entries together.
+ for (int index = 1; index < length; index++)
+ {
+ constantIndexMap[index] = counter;
+
+ Constant constant = constantPool[index];
+
+ // Is the constant being used? Don't update the flag if this is the
+ // second half of a long entry.
+ if (constant != null)
+ {
+ isUsed = usageMarker.isUsed(constant);
+ }
+
+ if (isUsed)
+ {
+ // Remember the new index.
+ constantIndexMap[index] = counter;
+
+ // Shift the constant pool entry.
+ constantPool[counter++] = constant;
+ }
+ else
+ {
+ // Remember an invalid index.
+ constantIndexMap[index] = -1;
+ }
+ }
+
+ // Clear the remaining constant pool elements.
+ Arrays.fill(constantPool, counter, length, null);
+
+ return counter;
+ }
+
+
+ /**
+ * Creates an array marking unused constant pool entries for all the
+ * elements in the given array of constant pool indices.
+ * @return an array of flags indicating unused elements.
+ */
+ private boolean[] shrinkFlags(Constant[] constantPool, int[] array, int length)
+ {
+ boolean[] unused = new boolean[length];
+
+ // Shift the used objects together.
+ for (int index = 0; index < length; index++)
+ {
+ if (!usageMarker.isUsed(constantPool[array[index]]))
+ {
+ unused[index] = true;
+ }
+ }
+
+ return unused;
+ }
+
+
+ /**
+ * Removes all indices that point to unused constant pool entries
+ * from the given array.
+ * @return the new number of indices.
+ */
+ private int shrinkConstantIndexArray(Constant[] constantPool, int[] array, int length)
+ {
+ int counter = 0;
+
+ // Shift the used objects together.
+ for (int index = 0; index < length; index++)
+ {
+ if (usageMarker.isUsed(constantPool[array[index]]))
+ {
+ array[counter++] = array[index];
+ }
+ }
+
+ // Clear the remaining array elements.
+ Arrays.fill(array, counter, length, 0);
+
+ return counter;
+ }
+
+
+ /**
+ * Removes all Clazz objects that are not marked as being used
+ * from the given array and returns the remaining objects in a an array
+ * of the right size.
+ * @return the new array.
+ */
+ private Clazz[] shrinkToNewArray(Clazz[] array)
+ {
+ if (array == null)
+ {
+ return null;
+ }
+
+ // Shrink the given array in-place.
+ int length = shrinkArray(array, array.length);
+ if (length == 0)
+ {
+ return null;
+ }
+
+ // Return immediately if the array is of right size already.
+ if (length == array.length)
+ {
+ return array;
+ }
+
+ // Copy the remaining elements into a new array of the right size.
+ Clazz[] newArray = new Clazz[length];
+ System.arraycopy(array, 0, newArray, 0, length);
+ return newArray;
+ }
+
+
+ /**
+ * Removes all entries that are not marked as being used from the given
+ * array of bootstrap methods. Creates a map from the old indices to the
+ * new indices as a side effect.
+ * @return the new number of entries.
+ */
+ private int shrinkBootstrapMethodArray(BootstrapMethodInfo[] bootstrapMethods, int length)
+ {
+ if (bootstrapMethodIndexMap.length < length)
+ {
+ bootstrapMethodIndexMap = new int[length];
+ }
+
+ int counter = 0;
+
+ // Shift the used bootstrap methods together.
+ for (int index = 0; index < length; index++)
+ {
+ BootstrapMethodInfo bootstrapMethod = bootstrapMethods[index];
+
+ // Is the entry being used?
+ if (usageMarker.isUsed(bootstrapMethod))
+ {
+ // Remember the new index.
+ bootstrapMethodIndexMap[index] = counter;
+
+ // Shift the entry.
+ bootstrapMethods[counter++] = bootstrapMethod;
+ }
+ else
+ {
+ // Remember an invalid index.
+ bootstrapMethodIndexMap[index] = -1;
+ }
+ }
+
+ // Clear the remaining bootstrap methods.
+ Arrays.fill(bootstrapMethods, counter, length, null);
+
+ return counter;
+ }
+
+
+ /**
+ * Removes all VisitorAccepter objects that are not marked as being used
+ * from the given array.
+ * @return the new number of VisitorAccepter objects.
+ */
+ private int shrinkArray(VisitorAccepter[] array, int length)
+ {
+ int counter = 0;
+
+ // Shift the used objects together.
+ for (int index = 0; index < length; index++)
+ {
+ VisitorAccepter visitorAccepter = array[index];
+
+ if (usageMarker.isUsed(visitorAccepter))
+ {
+ array[counter++] = visitorAccepter;
+ }
+ }
+
+ // Clear any remaining array elements.
+ if (counter < length)
+ {
+ Arrays.fill(array, counter, length, null);
+ }
+
+ return counter;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/InnerUsageMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/InnerUsageMarker.java
new file mode 100644
index 0000000000..d0dd186352
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/InnerUsageMarker.java
@@ -0,0 +1,174 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This AttributeVisitor recursively marks all necessary inner class information
+ * in the attributes that it visits.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class InnerUsageMarker
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InnerClassesInfoVisitor,
+ ConstantVisitor,
+ ClassVisitor
+{
+ private final UsageMarker usageMarker;
+
+ // Fields acting as a return parameters for several methods.
+ private boolean attributeUsed;
+ private boolean classUsed;
+
+
+ /**
+ * Creates a new InnerUsageMarker.
+ * @param usageMarker the usage marker that is used to mark the classes
+ * and class members.
+ */
+ public InnerUsageMarker(UsageMarker usageMarker)
+ {
+ this.usageMarker = usageMarker;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ // Mark the necessary inner classes information.
+ attributeUsed = false;
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+
+ if (attributeUsed)
+ {
+ // We got a positive used flag, so some inner class is being used.
+ // Mark this attribute as being used as well.
+ usageMarker.markAsUsed(innerClassesAttribute);
+
+ markConstant(clazz, innerClassesAttribute.u2attributeNameIndex);
+ }
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ boolean innerClassesInfoUsed = usageMarker.isUsed(innerClassesInfo);
+
+ if (!innerClassesInfoUsed)
+ {
+ // Check if the inner class (if any) is marked as being used.
+ classUsed = true;
+ innerClassesInfo.innerClassConstantAccept(clazz, this);
+ innerClassesInfoUsed = classUsed;
+
+ // Check if the outer class (if any) is marked as being used.
+ classUsed = true;
+ innerClassesInfo.outerClassConstantAccept(clazz, this);
+ innerClassesInfoUsed &= classUsed;
+
+ // If both the inner class and the outer class are marked as being
+ // used, then mark this InnerClassesInfo as well.
+ if (innerClassesInfoUsed)
+ {
+ usageMarker.markAsUsed(innerClassesInfo);
+
+ innerClassesInfo.innerNameConstantAccept(clazz, this);
+ }
+ }
+
+ // The return value.
+ attributeUsed |= innerClassesInfoUsed;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classUsed = usageMarker.isUsed(classConstant);
+
+ // Is the class constant marked as being used?
+ if (!classUsed)
+ {
+ // Check the referenced class.
+ classUsed = true;
+ classConstant.referencedClassAccept(this);
+
+ // Is the referenced class marked as being used?
+ if (classUsed)
+ {
+ // Mark the class constant and its Utf8 constant.
+ usageMarker.markAsUsed(classConstant);
+
+ markConstant(clazz, classConstant.u2nameIndex);
+ }
+ }
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ usageMarker.markAsUsed(utf8Constant);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ classUsed = usageMarker.isUsed(programClass);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ classUsed = true;
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given constant pool entry of the given class. This includes
+ * visiting any other referenced constant pool entries.
+ */
+ private void markConstant(Clazz clazz, int index)
+ {
+ clazz.constantPoolEntryAccept(index, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/InterfaceUsageMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/InterfaceUsageMarker.java
new file mode 100644
index 0000000000..327d719dd4
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/InterfaceUsageMarker.java
@@ -0,0 +1,152 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+
+/**
+ * This ClassVisitor recursively marks all interface
+ * classes that are being used in the visited class.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class InterfaceUsageMarker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor
+{
+ private final UsageMarker usageMarker;
+
+ // Fields acting as return parameters for the visitor methods.
+ private boolean used;
+ private boolean anyUsed;
+
+
+ /**
+ * Creates a new InterfaceUsageMarker.
+ * @param usageMarker the usage marker that is used to mark the classes
+ * and class members.
+ */
+ public InterfaceUsageMarker(UsageMarker usageMarker)
+ {
+ this.usageMarker = usageMarker;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ boolean classUsed = usageMarker.isUsed(programClass);
+ boolean classPossiblyUsed = usageMarker.isPossiblyUsed(programClass);
+
+ if (classUsed || classPossiblyUsed)
+ {
+ // Check if any interfaces are being used.
+ boolean oldAnyUsed = anyUsed;
+ anyUsed = false;
+
+ programClass.interfaceConstantsAccept(this);
+
+ classUsed |= anyUsed;
+ anyUsed = oldAnyUsed;
+
+ // Is this an interface with a preliminary mark?
+ if (classPossiblyUsed)
+ {
+ // Should it be included now?
+ if (classUsed)
+ {
+ // At least one if this interface's interfaces is being used.
+ // Mark this interface as well.
+ usageMarker.markAsUsed(programClass);
+
+ // Mark this interface's name.
+ programClass.thisClassConstantAccept(this);
+
+ // Mark the superclass (java/lang/Object).
+ programClass.superClassConstantAccept(this);
+ }
+ else
+ {
+ // Unmark this interface, so we don't bother looking at it again.
+ usageMarker.markAsUnused(programClass);
+ }
+ }
+ }
+
+ // The return value.
+ used = classUsed;
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // The return values.
+ used = true;
+ anyUsed = true;
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ boolean classUsed = usageMarker.isUsed(classConstant);
+
+ if (!classUsed)
+ {
+ // The ClassConstant isn't marked as being used yet. But maybe it
+ // should be included as an interface, so check the actual class.
+ classConstant.referencedClassAccept(this);
+ classUsed = used;
+
+ if (classUsed)
+ {
+ // The class is being used. Mark the ClassConstant as being used
+ // as well.
+ usageMarker.markAsUsed(classConstant);
+
+ clazz.constantPoolEntryAccept(classConstant.u2nameIndex, this);
+ }
+ }
+
+ // The return values.
+ used = classUsed;
+ anyUsed |= classUsed;
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ if (!usageMarker.isUsed(utf8Constant))
+ {
+ usageMarker.markAsUsed(utf8Constant);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/LocalVariableTypeUsageMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/LocalVariableTypeUsageMarker.java
new file mode 100644
index 0000000000..9c63455b15
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/LocalVariableTypeUsageMarker.java
@@ -0,0 +1,177 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.Constant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This AttributeVisitor recursively marks all information that points to used
+ * classes, in the LocalVariableTable and LocalVariableTypeTable attributes that
+ * it visits.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class LocalVariableTypeUsageMarker
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+ ClassVisitor,
+ ConstantVisitor
+{
+ private final UsageMarker usageMarker;
+
+ // Fields acting as return values for several visitor methods.
+ private boolean tableUsed;
+ private boolean variableInfoUsed;
+
+
+ /**
+ * Creates a new LocalVariableTypeUsageMarker.
+ * @param usageMarker the usage marker that is used to mark the classes
+ * and class members.
+ */
+ public LocalVariableTypeUsageMarker(UsageMarker usageMarker)
+ {
+ this.usageMarker = usageMarker;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Check and mark the individual entries.
+ tableUsed = false;
+ localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+
+ // Mark the table if any of the entries is marked.
+ if (tableUsed)
+ {
+ usageMarker.markAsUsed(localVariableTableAttribute);
+
+ markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
+ }
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Check and mark the individual entries.
+ tableUsed = false;
+ localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+
+ // Mark the table if any of the entries is marked.
+ if (tableUsed)
+ {
+ usageMarker.markAsUsed(localVariableTypeTableAttribute);
+
+ markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
+ }
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ // Only keep the local variable info if all of its classes are used.
+ variableInfoUsed = true;
+ localVariableInfo.referencedClassAccept(this);
+
+ if (variableInfoUsed)
+ {
+ // We got a positive used flag, so the local variable info is useful.
+ usageMarker.markAsUsed(localVariableInfo);
+
+ markConstant(clazz, localVariableInfo.u2nameIndex);
+ markConstant(clazz, localVariableInfo.u2descriptorIndex);
+
+ tableUsed = true;
+ }
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ // Only keep the local variable info if all of its classes are used.
+ variableInfoUsed = true;
+ localVariableTypeInfo.referencedClassesAccept(this);
+
+ if (variableInfoUsed)
+ {
+ // We got a positive used flag, so the local variable info is useful.
+ usageMarker.markAsUsed(localVariableTypeInfo);
+
+ markConstant(clazz, localVariableTypeInfo.u2nameIndex);
+ markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
+
+ tableUsed = true;
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Don't keep the local variable info if one of its classes is not used.
+ if (!usageMarker.isUsed(programClass))
+ {
+ variableInfoUsed = false;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant)
+ {
+ usageMarker.markAsUsed(constant);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given constant pool entry of the given class.
+ */
+ private void markConstant(Clazz clazz, int index)
+ {
+ clazz.constantPoolEntryAccept(index, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsageMark.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsageMark.java
new file mode 100644
index 0000000000..bdfe991560
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsageMark.java
@@ -0,0 +1,183 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.*;
+
+
+/**
+ * This class can be used as a mark when keeping classes, class members, and
+ * other elements. It can be certain or preliminary. It also contains additional
+ * information about the reasons why an element is being kept.
+ *
+ * @see ClassShrinker
+ *
+ * @author Eric Lafortune
+ */
+final class ShortestUsageMark
+{
+ private final boolean certain;
+ private final String reason;
+ private final int depth;
+ private Clazz clazz;
+ private Member member;
+
+
+ /**
+ * Creates a new certain ShortestUsageMark.
+ * @param reason the reason for this mark.
+ */
+ public ShortestUsageMark(String reason)
+ {
+ this.certain = true;
+ this.reason = reason;
+ this.depth = 0;
+ }
+
+
+ /**
+ * Creates a new certain ShortestUsageMark.
+ * @param previousUsageMark the previous mark to which this one is linked.
+ * @param reason the reason for this mark.
+ * @param clazz the class causing this mark.
+ */
+ public ShortestUsageMark(ShortestUsageMark previousUsageMark,
+ String reason,
+ int cost,
+ Clazz clazz)
+ {
+ this(previousUsageMark, reason, cost, clazz, null);
+ }
+
+
+ /**
+ * Creates a new certain ShortestUsageMark.
+ * @param previousUsageMark the previous mark to which this one is linked.
+ * @param reason the reason for this mark.
+ * @param clazz the class causing this mark.
+ * @param member the member in the above class causing this mark.
+ * @param cost the added cost of following this path.
+ */
+ public ShortestUsageMark(ShortestUsageMark previousUsageMark,
+ String reason,
+ int cost,
+ Clazz clazz,
+ Member member)
+ {
+ this.certain = true;
+ this.reason = reason;
+ this.depth = previousUsageMark.depth + cost;
+ this.clazz = clazz;
+ this.member = member;
+ }
+
+
+ /**
+ * Creates a new ShortestUsageMark, based on another mark.
+ * @param otherUsageMark the other mark, whose properties will be copied.
+ * @param certain specifies whether this is a certain mark.
+ */
+ public ShortestUsageMark(ShortestUsageMark otherUsageMark,
+ boolean certain)
+ {
+ this.certain = certain;
+ this.reason = otherUsageMark.reason;
+ this.depth = otherUsageMark.depth;
+ this.clazz = otherUsageMark.clazz;
+ this.member = otherUsageMark.member;
+ }
+
+
+ /**
+ * Returns whether this is a certain mark.
+ */
+ public boolean isCertain()
+ {
+ return certain;
+ }
+
+
+ /**
+ * Returns the reason for this mark.
+ */
+ public String getReason()
+ {
+ return reason;
+ }
+
+
+ /**
+ * Returns whether this mark has a shorter chain of reasons than the
+ * given mark.
+ */
+ public boolean isShorter(ShortestUsageMark otherUsageMark)
+ {
+ return this.depth < otherUsageMark.depth;
+ }
+
+
+ /**
+ * Returns whether this is mark is caused by the given class.
+ */
+ public boolean isCausedBy(Clazz clazz)
+ {
+ return clazz.equals(this.clazz);
+ }
+
+
+ /**
+ * Applies the given class visitor to this mark's class, if any,
+ * and if this mark doesn't have a member.
+ */
+ public void acceptClassVisitor(ClassVisitor classVisitor)
+ {
+ if (clazz != null &&
+ member == null)
+ {
+ clazz.accept(classVisitor);
+ }
+ }
+
+
+ /**
+ * Applies the given class visitor to this mark's member, if any.
+ */
+ public void acceptMemberVisitor(MemberVisitor memberVisitor)
+ {
+ if (clazz != null &&
+ member != null)
+ {
+ member.accept(clazz, memberVisitor);
+ }
+ }
+
+
+ // Implementations for Object.
+
+ public String toString()
+ {
+ return "certain=" + certain + ", depth="+depth+": " +
+ reason +
+ (clazz != null ? clazz.getName() : "(none)") + ": " +
+ (member != null ? member.getName(clazz) : "(none)");
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsageMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsageMarker.java
new file mode 100644
index 0000000000..d3da17cdeb
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsageMarker.java
@@ -0,0 +1,277 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.*;
+
+
+/**
+ * This ClassVisitor and MemberVisitor recursively marks all classes
+ * and class elements that are being used. For each element, it finds the
+ * shortest chain of dependencies.
+ *
+ * @see ClassShrinker
+ *
+ * @author Eric Lafortune
+ */
+public class ShortestUsageMarker extends UsageMarker
+{
+ private static final ShortestUsageMark INITIAL_MARK =
+ new ShortestUsageMark("is kept by a directive in the configuration.\n\n");
+
+
+ // A field acting as a parameter to the visitor methods.
+ private ShortestUsageMark currentUsageMark = INITIAL_MARK;
+
+ // A utility object to check for recursive causes.
+ private final MyRecursiveCauseChecker recursiveCauseChecker = new MyRecursiveCauseChecker();
+
+
+ // Overriding implementations for UsageMarker.
+
+ protected void markProgramClassBody(ProgramClass programClass)
+ {
+ ShortestUsageMark previousUsageMark = currentUsageMark;
+
+ currentUsageMark = new ShortestUsageMark(getShortestUsageMark(programClass),
+ "is extended by ",
+ 10000,
+ programClass);
+
+ super.markProgramClassBody(programClass);
+
+ currentUsageMark = previousUsageMark;
+ }
+
+
+ protected void markProgramFieldBody(ProgramClass programClass, ProgramField programField)
+ {
+ ShortestUsageMark previousUsageMark = currentUsageMark;
+
+ currentUsageMark = new ShortestUsageMark(getShortestUsageMark(programField),
+ "is referenced by ",
+ 1,
+ programClass,
+ programField);
+
+ super.markProgramFieldBody(programClass, programField);
+
+ currentUsageMark = previousUsageMark;
+ }
+
+
+ protected void markProgramMethodBody(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ ShortestUsageMark previousUsageMark = currentUsageMark;
+
+ currentUsageMark = new ShortestUsageMark(getShortestUsageMark(programMethod),
+ "is invoked by ",
+ 1,
+ programClass,
+ programMethod);
+
+ super.markProgramMethodBody(programClass, programMethod);
+
+ currentUsageMark = previousUsageMark;
+ }
+
+
+ protected void markMethodHierarchy(Clazz clazz, Method method)
+ {
+ ShortestUsageMark previousUsageMark = currentUsageMark;
+
+ currentUsageMark = new ShortestUsageMark(getShortestUsageMark(method),
+ "implements ",
+ 100,
+ clazz,
+ method);
+
+ super.markMethodHierarchy(clazz, method);
+
+ currentUsageMark = previousUsageMark;
+ }
+
+
+ // Small utility methods.
+
+ protected void markAsUsed(VisitorAccepter visitorAccepter)
+ {
+ Object visitorInfo = visitorAccepter.getVisitorInfo();
+
+ ShortestUsageMark shortestUsageMark =
+ visitorInfo != null &&
+ visitorInfo instanceof ShortestUsageMark &&
+ !((ShortestUsageMark)visitorInfo).isCertain() &&
+ !currentUsageMark.isShorter((ShortestUsageMark)visitorInfo) ?
+ new ShortestUsageMark((ShortestUsageMark)visitorInfo, true):
+ currentUsageMark;
+
+ visitorAccepter.setVisitorInfo(shortestUsageMark);
+ }
+
+
+ protected boolean shouldBeMarkedAsUsed(VisitorAccepter visitorAccepter)
+ {
+ Object visitorInfo = visitorAccepter.getVisitorInfo();
+
+ return //!(visitorAccepter instanceof Clazz &&
+ // isCausedBy(currentUsageMark, (Clazz)visitorAccepter)) &&
+ (visitorInfo == null ||
+ !(visitorInfo instanceof ShortestUsageMark) ||
+ !((ShortestUsageMark)visitorInfo).isCertain() ||
+ currentUsageMark.isShorter((ShortestUsageMark)visitorInfo));
+ }
+
+
+ protected boolean isUsed(VisitorAccepter visitorAccepter)
+ {
+ Object visitorInfo = visitorAccepter.getVisitorInfo();
+
+ return visitorInfo != null &&
+ visitorInfo instanceof ShortestUsageMark &&
+ ((ShortestUsageMark)visitorInfo).isCertain();
+ }
+
+
+ protected void markAsPossiblyUsed(VisitorAccepter visitorAccepter)
+ {
+ visitorAccepter.setVisitorInfo(new ShortestUsageMark(currentUsageMark, false));
+ }
+
+
+ protected boolean shouldBeMarkedAsPossiblyUsed(VisitorAccepter visitorAccepter)
+ {
+ Object visitorInfo = visitorAccepter.getVisitorInfo();
+
+ return visitorInfo == null ||
+ !(visitorInfo instanceof ShortestUsageMark) ||
+ (!((ShortestUsageMark)visitorInfo).isCertain() &&
+ currentUsageMark.isShorter((ShortestUsageMark)visitorInfo));
+ }
+
+
+ protected boolean isPossiblyUsed(VisitorAccepter visitorAccepter)
+ {
+ Object visitorInfo = visitorAccepter.getVisitorInfo();
+
+ return visitorInfo != null &&
+ visitorInfo instanceof ShortestUsageMark &&
+ !((ShortestUsageMark)visitorInfo).isCertain();
+ }
+
+
+ protected ShortestUsageMark getShortestUsageMark(VisitorAccepter visitorAccepter)
+ {
+ Object visitorInfo = visitorAccepter.getVisitorInfo();
+
+ return (ShortestUsageMark)visitorInfo;
+ }
+
+
+ // Small utility methods.
+
+ private boolean isCausedBy(ShortestUsageMark shortestUsageMark,
+ Clazz clazz)
+ {
+ return recursiveCauseChecker.check(shortestUsageMark, clazz);
+ }
+
+
+ private class MyRecursiveCauseChecker implements ClassVisitor, MemberVisitor
+ {
+ private Clazz checkClass;
+ private boolean isRecursing;
+
+
+ public boolean check(ShortestUsageMark shortestUsageMark,
+ Clazz clazz)
+ {
+ checkClass = clazz;
+ isRecursing = false;
+
+ shortestUsageMark.acceptClassVisitor(this);
+ shortestUsageMark.acceptMemberVisitor(this);
+
+ return isRecursing;
+ }
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ checkCause(programClass);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ checkCause(libraryClass);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ checkCause(programField);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ checkCause(programMethod);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ checkCause(libraryField);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ checkCause(libraryMethod);
+ }
+
+
+ // Small utility methods.
+
+ private void checkCause(VisitorAccepter visitorAccepter)
+ {
+ if (ShortestUsageMarker.this.isUsed(visitorAccepter))
+ {
+ ShortestUsageMark shortestUsageMark = ShortestUsageMarker.this.getShortestUsageMark(visitorAccepter);
+
+ // Check the class of this mark, if any
+ isRecursing = shortestUsageMark.isCausedBy(checkClass);
+
+ // Check the causing class or method, if still necessary.
+ if (!isRecursing)
+ {
+ shortestUsageMark.acceptClassVisitor(this);
+ shortestUsageMark.acceptMemberVisitor(this);
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsagePrinter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsagePrinter.java
new file mode 100644
index 0000000000..cd7da48c84
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/ShortestUsagePrinter.java
@@ -0,0 +1,220 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+import java.io.PrintStream;
+
+
+/**
+ * This ClassVisitor and MemberVisitor prints out the reasons why
+ * classes and class members have been marked as being used.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class ShortestUsagePrinter
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor
+{
+ private final ShortestUsageMarker shortestUsageMarker;
+ private final boolean verbose;
+ private final PrintStream ps;
+
+
+ /**
+ * Creates a new UsagePrinter that prints verbosely to <code>System.out</code>.
+ * @param shortestUsageMarker the usage marker that was used to mark the
+ * classes and class members.
+ */
+ public ShortestUsagePrinter(ShortestUsageMarker shortestUsageMarker)
+ {
+ this(shortestUsageMarker, true);
+ }
+
+
+ /**
+ * Creates a new UsagePrinter that prints to the given stream.
+ * @param shortestUsageMarker the usage marker that was used to mark the
+ * classes and class members.
+ * @param verbose specifies whether the output should be verbose.
+ */
+ public ShortestUsagePrinter(ShortestUsageMarker shortestUsageMarker,
+ boolean verbose)
+ {
+ this(shortestUsageMarker, verbose, System.out);
+ }
+
+ /**
+ * Creates a new UsagePrinter that prints to the given stream.
+ * @param shortestUsageMarker the usage marker that was used to mark the
+ * classes and class members.
+ * @param verbose specifies whether the output should be verbose.
+ * @param printStream the stream to which to print.
+ */
+ public ShortestUsagePrinter(ShortestUsageMarker shortestUsageMarker,
+ boolean verbose,
+ PrintStream printStream)
+ {
+ this.shortestUsageMarker = shortestUsageMarker;
+ this.verbose = verbose;
+ this.ps = printStream;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Print the name of this class.
+ ps.println(ClassUtil.externalClassName(programClass.getName()));
+
+ // Print the reason for keeping this class.
+ printReason(programClass);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Print the name of this class.
+ ps.println(ClassUtil.externalClassName(libraryClass.getName()));
+
+ // Print the reason for keeping this class.
+ ps.println(" is a library class.\n");
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Print the name of this field.
+ String name = programField.getName(programClass);
+ String type = programField.getDescriptor(programClass);
+
+ ps.println(ClassUtil.externalClassName(programClass.getName()) +
+ (verbose ?
+ ": " + ClassUtil.externalFullFieldDescription(0, name, type):
+ "." + name));
+
+ // Print the reason for keeping this method.
+ printReason(programField);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Print the name of this method.
+ String name = programMethod.getName(programClass);
+ String type = programMethod.getDescriptor(programClass);
+
+ ps.print(ClassUtil.externalClassName(programClass.getName()) +
+ (verbose ?
+ ": " + ClassUtil.externalFullMethodDescription(programClass.getName(), 0, name, type):
+ "." + name));
+ programMethod.attributesAccept(programClass, this);
+ ps.println();
+
+ // Print the reason for keeping this method.
+ printReason(programMethod);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ // Print the name of this field.
+ String name = libraryField.getName(libraryClass);
+ String type = libraryField.getDescriptor(libraryClass);
+
+ ps.println(ClassUtil.externalClassName(libraryClass.getName()) +
+ (verbose ?
+ ": " + ClassUtil.externalFullFieldDescription(0, name, type):
+ "." + name));
+
+ // Print the reason for keeping this field.
+ ps.println(" is a library field.\n");
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ // Print the name of this method.
+ String name = libraryMethod.getName(libraryClass);
+ String type = libraryMethod.getDescriptor(libraryClass);
+
+ ps.println(ClassUtil.externalClassName(libraryClass.getName()) +
+ (verbose ?
+ ": " + ClassUtil.externalFullMethodDescription(libraryClass.getName(), 0, name, type):
+ "." + name));
+
+ // Print the reason for keeping this method.
+ ps.println(" is a library method.\n");
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ ps.print(" (" +
+ lineNumberTableAttribute.getLowestLineNumber() + ":" +
+ lineNumberTableAttribute.getHighestLineNumber() + ")");
+ }
+
+
+ // Small utility methods.
+
+ private void printReason(VisitorAccepter visitorAccepter)
+ {
+ if (shortestUsageMarker.isUsed(visitorAccepter))
+ {
+ ShortestUsageMark shortestUsageMark = shortestUsageMarker.getShortestUsageMark(visitorAccepter);
+
+ // Print the reason for keeping this class.
+ ps.print(" " + shortestUsageMark.getReason());
+
+ // Print the class or method that is responsible, with its reasons.
+ shortestUsageMark.acceptClassVisitor(this);
+ shortestUsageMark.acceptMemberVisitor(this);
+ }
+ else
+ {
+ ps.println(" is not being kept.\n");
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/Shrinker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/Shrinker.java
new file mode 100644
index 0000000000..60524ba0df
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/Shrinker.java
@@ -0,0 +1,192 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.*;
+import proguard.classfile.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.visitor.*;
+
+import java.io.*;
+
+/**
+ * This class shrinks class pools according to a given configuration.
+ *
+ * @author Eric Lafortune
+ */
+public class Shrinker
+{
+ private final Configuration configuration;
+
+
+ /**
+ * Creates a new Shrinker.
+ */
+ public Shrinker(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Performs shrinking of the given program class pool.
+ */
+ public ClassPool execute(ClassPool programClassPool,
+ ClassPool libraryClassPool) throws IOException
+ {
+ // Check if we have at least some keep commands.
+ if (configuration.keep == null)
+ {
+ throw new IOException("You have to specify '-keep' options for the shrinking step.");
+ }
+
+ // Clean up any old visitor info.
+ programClassPool.classesAccept(new ClassCleaner());
+ libraryClassPool.classesAccept(new ClassCleaner());
+
+ // Create a visitor for marking the seeds.
+ UsageMarker usageMarker = configuration.whyAreYouKeeping == null ?
+ new UsageMarker() :
+ new ShortestUsageMarker();
+
+ // Automatically mark the parameterless constructors of seed classes,
+ // mainly for convenience and for backward compatibility.
+ ClassVisitor classUsageMarker =
+ new MultiClassVisitor(new ClassVisitor[]
+ {
+ usageMarker,
+ new NamedMethodVisitor(ClassConstants.METHOD_NAME_INIT,
+ ClassConstants.METHOD_TYPE_INIT,
+ usageMarker)
+ });
+
+ ClassPoolVisitor classPoolvisitor =
+ ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep,
+ classUsageMarker,
+ usageMarker,
+ true,
+ false,
+ false);
+ // Mark the seeds.
+ programClassPool.accept(classPoolvisitor);
+ libraryClassPool.accept(classPoolvisitor);
+ libraryClassPool.classesAccept(usageMarker);
+
+ // Mark interfaces that have to be kept.
+ programClassPool.classesAccept(new InterfaceUsageMarker(usageMarker));
+
+ // Mark the inner class and annotation information that has to be kept.
+ programClassPool.classesAccept(
+ new UsedClassFilter(usageMarker,
+ new AllAttributeVisitor(true,
+ new MultiAttributeVisitor(new AttributeVisitor[]
+ {
+ new InnerUsageMarker(usageMarker),
+ new AnnotationUsageMarker(usageMarker),
+ new LocalVariableTypeUsageMarker(usageMarker)
+ }))));
+
+ // Should we explain ourselves?
+ if (configuration.whyAreYouKeeping != null)
+ {
+ System.out.println();
+
+ // Create a visitor for explaining classes and class members.
+ ShortestUsagePrinter shortestUsagePrinter =
+ new ShortestUsagePrinter((ShortestUsageMarker)usageMarker,
+ configuration.verbose);
+
+ ClassPoolVisitor whyClassPoolvisitor =
+ ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.whyAreYouKeeping,
+ shortestUsagePrinter,
+ shortestUsagePrinter);
+
+ // Mark the seeds.
+ programClassPool.accept(whyClassPoolvisitor);
+ libraryClassPool.accept(whyClassPoolvisitor);
+ }
+
+ if (configuration.printUsage != null)
+ {
+ PrintStream ps =
+ configuration.printUsage == Configuration.STD_OUT ? System.out :
+ new PrintStream(
+ new BufferedOutputStream(
+ new FileOutputStream(configuration.printUsage)));
+
+ // Print out items that will be removed.
+ programClassPool.classesAcceptAlphabetically(
+ new UsagePrinter(usageMarker, true, ps));
+
+ if (ps == System.out)
+ {
+ ps.flush();
+ }
+ else
+ {
+ ps.close();
+ }
+ }
+
+ // Clean up used program classes and discard unused program classes.
+ int originalProgramClassPoolSize = programClassPool.size();
+
+ ClassPool newProgramClassPool = new ClassPool();
+ programClassPool.classesAccept(
+ new UsedClassFilter(usageMarker,
+ new MultiClassVisitor(
+ new ClassVisitor[] {
+ new ClassShrinker(usageMarker),
+ new ClassPoolFiller(newProgramClassPool)
+ })));
+
+ programClassPool.clear();
+
+ // Clean up library classes.
+ libraryClassPool.classesAccept(
+ new ClassShrinker(usageMarker));
+
+ // Check if we have at least some output classes.
+ int newProgramClassPoolSize = newProgramClassPool.size();
+
+ if (configuration.verbose)
+ {
+ System.out.println("Removing unused program classes and class elements...");
+ System.out.println(" Original number of program classes: " + originalProgramClassPoolSize);
+ System.out.println(" Final number of program classes: " + newProgramClassPoolSize);
+ }
+
+ if (newProgramClassPoolSize == 0 &&
+ (configuration.warn == null || !configuration.warn.isEmpty()))
+ {
+ if (configuration.ignoreWarnings)
+ {
+ System.err.println("Warning: the output jar is empty. Did you specify the proper '-keep' options?");
+ }
+ else
+ {
+ throw new IOException("The output jar is empty. Did you specify the proper '-keep' options?");
+ }
+ }
+
+ return newProgramClassPool;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsageMarker.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsageMarker.java
new file mode 100644
index 0000000000..8ebfaec415
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsageMarker.java
@@ -0,0 +1,1125 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
+import proguard.classfile.attribute.preverification.visitor.*;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.*;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor and MemberVisitor recursively marks all classes and class
+ * elements that are being used.
+ *
+ * @see ClassShrinker
+ *
+ * @author Eric Lafortune
+ */
+class UsageMarker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ ConstantVisitor,
+ AttributeVisitor,
+ InnerClassesInfoVisitor,
+ ExceptionInfoVisitor,
+ StackMapFrameVisitor,
+ VerificationTypeVisitor,
+ ParameterInfoVisitor,
+ LocalVariableInfoVisitor,
+ LocalVariableTypeInfoVisitor,
+// AnnotationVisitor,
+// ElementValueVisitor,
+ InstructionVisitor
+{
+ // A visitor info flag to indicate the ProgramMember object is being used,
+ // if its Clazz can be determined as being used as well.
+ private static final Object POSSIBLY_USED = new Object();
+ // A visitor info flag to indicate the visitor accepter is being used.
+ private static final Object USED = new Object();
+
+
+ private final MyInterfaceUsageMarker interfaceUsageMarker = new MyInterfaceUsageMarker();
+ private final MyDefaultMethodUsageMarker defaultMethodUsageMarker = new MyDefaultMethodUsageMarker();
+ private final MyPossiblyUsedMemberUsageMarker possiblyUsedMemberUsageMarker = new MyPossiblyUsedMemberUsageMarker();
+ private final MemberVisitor nonEmptyMethodUsageMarker = new AllAttributeVisitor(
+ new MyNonEmptyMethodUsageMarker());
+ private final ConstantVisitor parameterlessConstructorMarker = new ConstantTagFilter(new int[] { ClassConstants.CONSTANT_String, ClassConstants.CONSTANT_Class },
+ new ReferencedClassVisitor(
+ new NamedMethodVisitor(ClassConstants.METHOD_NAME_INIT,
+ ClassConstants.METHOD_TYPE_INIT,
+ this)));
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (shouldBeMarkedAsUsed(programClass))
+ {
+ // Mark this class.
+ markAsUsed(programClass);
+
+ markProgramClassBody(programClass);
+ }
+ }
+
+
+ protected void markProgramClassBody(ProgramClass programClass)
+ {
+ // Mark this class's name.
+ markConstant(programClass, programClass.u2thisClass);
+
+ // Mark the superclass.
+ if (programClass.u2superClass != 0)
+ {
+ markConstant(programClass, programClass.u2superClass);
+ }
+
+ // Give the interfaces preliminary marks.
+ programClass.hierarchyAccept(false, false, true, false,
+ interfaceUsageMarker);
+
+ // Explicitly mark the <clinit> method, if it's not empty.
+ programClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT,
+ ClassConstants.METHOD_TYPE_CLINIT,
+ nonEmptyMethodUsageMarker);
+
+ // Process all class members that have already been marked as possibly used.
+ programClass.fieldsAccept(possiblyUsedMemberUsageMarker);
+ programClass.methodsAccept(possiblyUsedMemberUsageMarker);
+
+ // Mark the attributes.
+ programClass.attributesAccept(this);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (shouldBeMarkedAsUsed(libraryClass))
+ {
+ markAsUsed(libraryClass);
+
+ // We're not going to analyze all library code. We're assuming that
+ // if this class is being used, all of its methods will be used as
+ // well. We'll mark them as such (here and in all subclasses).
+
+ // Mark the superclass.
+ Clazz superClass = libraryClass.superClass;
+ if (superClass != null)
+ {
+ superClass.accept(this);
+ }
+
+ // Mark the interfaces.
+ Clazz[] interfaceClasses = libraryClass.interfaceClasses;
+ if (interfaceClasses != null)
+ {
+ for (int index = 0; index < interfaceClasses.length; index++)
+ {
+ if (interfaceClasses[index] != null)
+ {
+ interfaceClasses[index].accept(this);
+ }
+ }
+ }
+
+ // Mark all methods.
+ libraryClass.methodsAccept(this);
+ }
+ }
+
+
+ /**
+ * This ClassVisitor marks ProgramClass objects as possibly used,
+ * and it visits LibraryClass objects with its outer UsageMarker.
+ */
+ private class MyInterfaceUsageMarker
+ implements ClassVisitor
+ {
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (shouldBeMarkedAsPossiblyUsed(programClass))
+ {
+ // We can't process the interface yet, because it might not
+ // be required. Give it a preliminary mark.
+ markAsPossiblyUsed(programClass);
+ }
+ }
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Make sure all library interface methods are marked.
+ UsageMarker.this.visitLibraryClass(libraryClass);
+ }
+ }
+
+
+ /**
+ * This MemberVisitor marks ProgramMethod objects of default
+ * implementations that may be present in interface classes.
+ */
+ private class MyDefaultMethodUsageMarker
+ extends SimplifiedVisitor
+ implements MemberVisitor
+ {
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (shouldBeMarkedAsUsed(programMethod))
+ {
+ markAsUsed(programMethod);
+
+ // Mark the method body.
+ markProgramMethodBody(programClass, programMethod);
+
+ // Note that, if the method has been marked as possibly used,
+ // the method hierarchy has already been marked (cfr. below).
+ }
+ }
+ }
+
+
+ /**
+ * This MemberVisitor marks ProgramField and ProgramMethod objects that
+ * have already been marked as possibly used.
+ */
+ private class MyPossiblyUsedMemberUsageMarker
+ extends SimplifiedVisitor
+ implements MemberVisitor
+ {
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Has the method already been referenced?
+ if (isPossiblyUsed(programField))
+ {
+ markAsUsed(programField);
+
+ // Mark the name and descriptor.
+ markConstant(programClass, programField.u2nameIndex);
+ markConstant(programClass, programField.u2descriptorIndex);
+
+ // Mark the attributes.
+ programField.attributesAccept(programClass, UsageMarker.this);
+
+ // Mark the classes referenced in the descriptor string.
+ programField.referencedClassesAccept(UsageMarker.this);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Has the method already been referenced?
+ if (isPossiblyUsed(programMethod))
+ {
+ markAsUsed(programMethod);
+
+ // Mark the method body.
+ markProgramMethodBody(programClass, programMethod);
+
+ // Note that, if the method has been marked as possibly used,
+ // the method hierarchy has already been marked (cfr. below).
+ }
+ }
+ }
+
+
+ /**
+ * This AttributeVisitor marks ProgramMethod objects of non-empty methods.
+ */
+ private class MyNonEmptyMethodUsageMarker
+ extends SimplifiedVisitor
+ implements AttributeVisitor
+ {
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (codeAttribute.u4codeLength > 1)
+ {
+ method.accept(clazz, UsageMarker.this);
+ }
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (shouldBeMarkedAsUsed(programField))
+ {
+ // Is the field's class used?
+ if (isUsed(programClass))
+ {
+ markAsUsed(programField);
+
+ // Mark the field body.
+ markProgramFieldBody(programClass, programField);
+ }
+
+ // Hasn't the field been marked as possibly being used yet?
+ else if (shouldBeMarkedAsPossiblyUsed(programField))
+ {
+ // We can't process the field yet, because the class isn't
+ // marked as being used (yet). Give it a preliminary mark.
+ markAsPossiblyUsed(programField);
+ }
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (shouldBeMarkedAsUsed(programMethod))
+ {
+ // Is the method's class used?
+ if (isUsed(programClass))
+ {
+ markAsUsed(programMethod);
+
+ // Mark the method body.
+ markProgramMethodBody(programClass, programMethod);
+
+ // Mark the method hierarchy.
+ markMethodHierarchy(programClass, programMethod);
+ }
+
+ // Hasn't the method been marked as possibly being used yet?
+ else if (shouldBeMarkedAsPossiblyUsed(programMethod))
+ {
+ // We can't process the method yet, because the class isn't
+ // marked as being used (yet). Give it a preliminary mark.
+ markAsPossiblyUsed(programMethod);
+
+ // Mark the method hierarchy.
+ markMethodHierarchy(programClass, programMethod);
+ }
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass programClass, LibraryField programField) {}
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (shouldBeMarkedAsUsed(libraryMethod))
+ {
+ markAsUsed(libraryMethod);
+
+ // Mark the method hierarchy.
+ markMethodHierarchy(libraryClass, libraryMethod);
+ }
+ }
+
+
+ protected void markProgramFieldBody(ProgramClass programClass, ProgramField programField)
+ {
+ // Mark the name and descriptor.
+ markConstant(programClass, programField.u2nameIndex);
+ markConstant(programClass, programField.u2descriptorIndex);
+
+ // Mark the attributes.
+ programField.attributesAccept(programClass, this);
+
+ // Mark the classes referenced in the descriptor string.
+ programField.referencedClassesAccept(this);
+ }
+
+
+ protected void markProgramMethodBody(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ // Mark the name and descriptor.
+ markConstant(programClass, programMethod.u2nameIndex);
+ markConstant(programClass, programMethod.u2descriptorIndex);
+
+ // Mark the attributes.
+ programMethod.attributesAccept(programClass, this);
+
+ // Mark the classes referenced in the descriptor string.
+ programMethod.referencedClassesAccept(this);
+ }
+
+
+ /**
+ * Marks the hierarchy of implementing or overriding methods corresponding
+ * to the given method, if any.
+ */
+ protected void markMethodHierarchy(Clazz clazz, Method method)
+ {
+ // Only visit the hierarchy if the method is not private, static, or
+ // an initializer.
+ int accessFlags = method.getAccessFlags();
+ if ((accessFlags &
+ (ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC)) == 0 &&
+ !ClassUtil.isInitializer(method.getName(clazz)))
+ {
+ // We can skip private and static methods in the hierarchy, and
+ // also abstract methods, unless they might widen a current
+ // non-public access.
+ int requiredUnsetAccessFlags =
+ ClassConstants.ACC_PRIVATE |
+ ClassConstants.ACC_STATIC |
+ ((accessFlags & ClassConstants.ACC_PUBLIC) == 0 ? 0 :
+ ClassConstants.ACC_ABSTRACT);
+
+ // Mark default implementations in interfaces down the hierarchy,
+ // if this is an interface itself.
+ // TODO: This may be premature if there aren't any concrete implementing classes.
+ clazz.accept(new ClassAccessFilter(ClassConstants.ACC_INTERFACE, 0,
+ new ClassHierarchyTraveler(false, false, false, true,
+ new ProgramClassFilter(
+ new ClassAccessFilter(ClassConstants.ACC_INTERFACE, 0,
+ new NamedMethodVisitor(method.getName(clazz),
+ method.getDescriptor(clazz),
+ new MemberAccessFilter(0, requiredUnsetAccessFlags,
+ defaultMethodUsageMarker)))))));
+
+ // Mark other implementations.
+ clazz.accept(new ConcreteClassDownTraveler(
+ new ClassHierarchyTraveler(true, true, false, true,
+ new NamedMethodVisitor(method.getName(clazz),
+ method.getDescriptor(clazz),
+ new MemberAccessFilter(0, requiredUnsetAccessFlags,
+ this)))));
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
+ {
+ if (shouldBeMarkedAsUsed(integerConstant))
+ {
+ markAsUsed(integerConstant);
+ }
+ }
+
+
+ public void visitLongConstant(Clazz clazz, LongConstant longConstant)
+ {
+ if (shouldBeMarkedAsUsed(longConstant))
+ {
+ markAsUsed(longConstant);
+ }
+ }
+
+
+ public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
+ {
+ if (shouldBeMarkedAsUsed(floatConstant))
+ {
+ markAsUsed(floatConstant);
+ }
+ }
+
+
+ public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
+ {
+ if (shouldBeMarkedAsUsed(doubleConstant))
+ {
+ markAsUsed(doubleConstant);
+ }
+ }
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ if (shouldBeMarkedAsUsed(stringConstant))
+ {
+ markAsUsed(stringConstant);
+
+ markConstant(clazz, stringConstant.u2stringIndex);
+
+ // Mark the referenced class and class member, if any.
+ stringConstant.referencedClassAccept(this);
+ stringConstant.referencedMemberAccept(this);
+ }
+ }
+
+
+ public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
+ {
+ if (shouldBeMarkedAsUsed(utf8Constant))
+ {
+ markAsUsed(utf8Constant);
+ }
+ }
+
+
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ if (shouldBeMarkedAsUsed(invokeDynamicConstant))
+ {
+ markAsUsed(invokeDynamicConstant);
+
+ markConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);
+
+ // Mark the referenced descriptor classes.
+ invokeDynamicConstant.referencedClassesAccept(this);
+
+ // Mark the bootstrap methods attribute.
+ clazz.attributesAccept(new MyBootStrapMethodUsageMarker(invokeDynamicConstant.u2bootstrapMethodAttributeIndex));
+ }
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ if (shouldBeMarkedAsUsed(methodHandleConstant))
+ {
+ markAsUsed(methodHandleConstant);
+
+ markConstant(clazz, methodHandleConstant.u2referenceIndex);
+ }
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ if (shouldBeMarkedAsUsed(refConstant))
+ {
+ markAsUsed(refConstant);
+
+ markConstant(clazz, refConstant.u2classIndex);
+ markConstant(clazz, refConstant.u2nameAndTypeIndex);
+
+ // When compiled with "-target 1.2" or higher, the class or
+ // interface actually containing the referenced class member may
+ // be higher up the hierarchy. Make sure it's marked, in case it
+ // isn't used elsewhere.
+ refConstant.referencedClassAccept(this);
+
+ // Mark the referenced class member itself.
+ refConstant.referencedMemberAccept(this);
+ }
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ if (shouldBeMarkedAsUsed(classConstant))
+ {
+ markAsUsed(classConstant);
+
+ markConstant(clazz, classConstant.u2nameIndex);
+
+ // Mark the referenced class itself.
+ classConstant.referencedClassAccept(this);
+ }
+ }
+
+
+ public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
+ {
+ if (shouldBeMarkedAsUsed(methodTypeConstant))
+ {
+ markAsUsed(methodTypeConstant);
+
+ markConstant(clazz, methodTypeConstant.u2descriptorIndex);
+
+ // Mark the referenced descriptor classes.
+ methodTypeConstant.referencedClassesAccept(this);
+ }
+ }
+
+
+ public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
+ {
+ if (shouldBeMarkedAsUsed(nameAndTypeConstant))
+ {
+ markAsUsed(nameAndTypeConstant);
+
+ markConstant(clazz, nameAndTypeConstant.u2nameIndex);
+ markConstant(clazz, nameAndTypeConstant.u2descriptorIndex);
+ }
+ }
+
+
+ /**
+ * This AttributeVisitor marks the bootstrap methods attributes, their
+ * method entries, their method handles, and their arguments.
+ */
+ private class MyBootStrapMethodUsageMarker
+ extends SimplifiedVisitor
+ implements AttributeVisitor,
+ BootstrapMethodInfoVisitor
+ {
+ private int bootstrapMethodIndex;
+
+
+ private MyBootStrapMethodUsageMarker(int bootstrapMethodIndex)
+ {
+ this.bootstrapMethodIndex = bootstrapMethodIndex;
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ if (shouldBeMarkedAsUsed(bootstrapMethodsAttribute))
+ {
+ markAsUsed(bootstrapMethodsAttribute);
+
+ markConstant(clazz, bootstrapMethodsAttribute.u2attributeNameIndex);
+ }
+
+ bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz,
+ bootstrapMethodIndex,
+ this);
+ }
+
+
+ // Implementations for BootstrapMethodInfoVisitor.
+
+ public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
+ {
+ markAsUsed(bootstrapMethodInfo);
+
+ markConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex);
+
+ // Mark the constant pool entries referenced by the arguments.
+ bootstrapMethodInfo.methodArgumentsAccept(clazz, UsageMarker.this);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+ // Note that attributes are typically only referenced once, so we don't
+ // test if they have been marked already.
+
+ public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
+ {
+ // This is the best we can do for unknown attributes.
+ markAsUsed(unknownAttribute);
+
+ markConstant(clazz, unknownAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
+ {
+ // Don't mark the attribute and its name here. We may mark it in
+ // MyBootStrapMethodsAttributeUsageMarker.
+ }
+
+
+ public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
+ {
+ markAsUsed(sourceFileAttribute);
+
+ markConstant(clazz, sourceFileAttribute.u2attributeNameIndex);
+ markConstant(clazz, sourceFileAttribute.u2sourceFileIndex);
+ }
+
+
+ public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
+ {
+ markAsUsed(sourceDirAttribute);
+
+ markConstant(clazz, sourceDirAttribute.u2attributeNameIndex);
+ markConstant(clazz, sourceDirAttribute.u2sourceDirIndex);
+ }
+
+
+ public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
+ {
+ // Don't mark the attribute and its name yet. We may mark it later, in
+ // InnerUsageMarker.
+ //markAsUsed(innerClassesAttribute);
+
+ //markConstant(clazz, innerClassesAttribute.u2attrNameIndex);
+
+ // Do mark the outer class entries.
+ innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+ }
+
+
+ public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
+ {
+ markAsUsed(enclosingMethodAttribute);
+
+ markConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex);
+ markConstant(clazz, enclosingMethodAttribute.u2classIndex);
+
+ if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
+ {
+ markConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex);
+ }
+ }
+
+
+ public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
+ {
+ markAsUsed(deprecatedAttribute);
+
+ markConstant(clazz, deprecatedAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
+ {
+ markAsUsed(syntheticAttribute);
+
+ markConstant(clazz, syntheticAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ markAsUsed(signatureAttribute);
+
+ markConstant(clazz, signatureAttribute.u2attributeNameIndex);
+ markConstant(clazz, signatureAttribute.u2signatureIndex);
+
+ // Don't mark the referenced classes. We'll clean them up in
+ // ClassShrinker, if they appear unused.
+ //// Mark the classes referenced in the descriptor string.
+ //signatureAttribute.referencedClassesAccept(this);
+ }
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ markAsUsed(constantValueAttribute);
+
+ markConstant(clazz, constantValueAttribute.u2attributeNameIndex);
+ markConstant(clazz, constantValueAttribute.u2constantValueIndex);
+ }
+
+
+ public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
+ {
+ markAsUsed(methodParametersAttribute);
+
+ markConstant(clazz, methodParametersAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the parameter information.
+ methodParametersAttribute.parametersAccept(clazz, method, this);
+ }
+
+
+ public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
+ {
+ markAsUsed(exceptionsAttribute);
+
+ markConstant(clazz, exceptionsAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the exceptions.
+ exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this);
+ }
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ markAsUsed(codeAttribute);
+
+ markConstant(clazz, codeAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the instructions,
+ // by the exceptions, and by the attributes.
+ codeAttribute.instructionsAccept(clazz, method, this);
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
+ {
+ markAsUsed(stackMapAttribute);
+
+ markConstant(clazz, stackMapAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the stack map frames.
+ stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
+ {
+ markAsUsed(stackMapTableAttribute);
+
+ markConstant(clazz, stackMapTableAttribute.u2attributeNameIndex);
+
+ // Mark the constant pool entries referenced by the stack map frames.
+ stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ markAsUsed(lineNumberTableAttribute);
+
+ markConstant(clazz, lineNumberTableAttribute.u2attributeNameIndex);
+ }
+
+
+ public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
+ {
+ // Don't mark the attribute and its contents yet. We may mark them later,
+ // in LocalVariableTypeUsageMarker.
+ //markAsUsed(localVariableTableAttribute);
+ //
+ //markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the local variables.
+ //localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
+ {
+ // Don't mark the attribute and its contents yet. We may mark them later,
+ // in LocalVariableTypeUsageMarker.
+ //markAsUsed(localVariableTypeTableAttribute);
+ //
+ //markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the local variable types.
+ //localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
+ }
+
+
+ public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
+ {
+ // Don't mark the attribute and its contents yet. We may mark them later,
+ // in AnnotationUsageMarker.
+ //markAsUsed(annotationsAttribute);
+ //
+ //markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the annotations.
+ //annotationsAttribute.annotationsAccept(clazz, this);
+ }
+
+
+ public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+ {
+ // Don't mark the attribute and its contents yet. We may mark them later,
+ // in AnnotationUsageMarker.
+ //markAsUsed(parameterAnnotationsAttribute);
+ //
+ //markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the annotations.
+ //parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
+ }
+
+
+ public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
+ {
+ // Don't mark the attribute and its contents yet. We may mark them later,
+ // in AnnotationUsageMarker.
+ //markAsUsed(annotationDefaultAttribute);
+ //
+ //markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex);
+ //
+ //// Mark the constant pool entries referenced by the element value.
+ //annotationDefaultAttribute.defaultValueAccept(clazz, this);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ markAsUsed(exceptionInfo);
+
+ if (exceptionInfo.u2catchType != 0)
+ {
+ markConstant(clazz, exceptionInfo.u2catchType);
+ }
+ }
+
+
+ // Implementations for InnerClassesInfoVisitor.
+
+ public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
+ {
+ // At this point, we only mark outer classes of this class.
+ // Inner class can be marked later, by InnerUsageMarker.
+ if (innerClassesInfo.u2innerClassIndex != 0 &&
+ clazz.getName().equals(clazz.getClassName(innerClassesInfo.u2innerClassIndex)))
+ {
+ markAsUsed(innerClassesInfo);
+
+ innerClassesInfo.innerClassConstantAccept(clazz, this);
+ innerClassesInfo.outerClassConstantAccept(clazz, this);
+ innerClassesInfo.innerNameConstantAccept(clazz, this);
+ }
+ }
+
+
+ // Implementations for StackMapFrameVisitor.
+
+ public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) {}
+
+
+ public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
+ {
+ // Mark the constant pool entries referenced by the verification types.
+ fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
+ fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
+ }
+
+
+ // Implementations for VerificationTypeVisitor.
+
+ public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
+
+
+ public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
+ {
+ markConstant(clazz, objectType.u2classIndex);
+ }
+
+
+ // Implementations for ParameterInfoVisitor.
+
+ public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
+ {
+ if (parameterInfo.u2nameIndex != 0)
+ {
+ markConstant(clazz, parameterInfo.u2nameIndex);
+ }
+ }
+
+
+ // Implementations for LocalVariableInfoVisitor.
+
+ public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
+ {
+ markConstant(clazz, localVariableInfo.u2nameIndex);
+ markConstant(clazz, localVariableInfo.u2descriptorIndex);
+ }
+
+
+ // Implementations for LocalVariableTypeInfoVisitor.
+
+ public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
+ {
+ markConstant(clazz, localVariableTypeInfo.u2nameIndex);
+ markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
+ }
+
+
+// // Implementations for AnnotationVisitor.
+//
+// public void visitAnnotation(Clazz clazz, Annotation annotation)
+// {
+// markConstant(clazz, annotation.u2typeIndex);
+//
+// // Mark the constant pool entries referenced by the element values.
+// annotation.elementValuesAccept(clazz, this);
+// }
+//
+//
+// // Implementations for ElementValueVisitor.
+//
+// public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
+// {
+// if (constantElementValue.u2elementNameIndex != 0)
+// {
+// markConstant(clazz, constantElementValue.u2elementNameIndex);
+// }
+//
+// markConstant(clazz, constantElementValue.u2constantValueIndex);
+// }
+//
+//
+// public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
+// {
+// if (enumConstantElementValue.u2elementNameIndex != 0)
+// {
+// markConstant(clazz, enumConstantElementValue.u2elementNameIndex);
+// }
+//
+// markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
+// markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
+// }
+//
+//
+// public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
+// {
+// if (classElementValue.u2elementNameIndex != 0)
+// {
+// markConstant(clazz, classElementValue.u2elementNameIndex);
+// }
+//
+// // Mark the referenced class constant pool entry.
+// markConstant(clazz, classElementValue.u2classInfoIndex);
+// }
+//
+//
+// public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
+// {
+// if (annotationElementValue.u2elementNameIndex != 0)
+// {
+// markConstant(clazz, annotationElementValue.u2elementNameIndex);
+// }
+//
+// // Mark the constant pool entries referenced by the annotation.
+// annotationElementValue.annotationAccept(clazz, this);
+// }
+//
+//
+// public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
+// {
+// if (arrayElementValue.u2elementNameIndex != 0)
+// {
+// markConstant(clazz, arrayElementValue.u2elementNameIndex);
+// }
+//
+// // Mark the constant pool entries referenced by the element values.
+// arrayElementValue.elementValuesAccept(clazz, annotation, this);
+// }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ markConstant(clazz, constantInstruction.constantIndex);
+
+ // Also mark the parameterless constructor of the class, in case the
+ // string constant or class constant is being used in a Class.forName
+ // or a .class construct.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+ parameterlessConstructorMarker);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given visitor accepter as being used.
+ */
+ protected void markAsUsed(VisitorAccepter visitorAccepter)
+ {
+ visitorAccepter.setVisitorInfo(USED);
+ }
+
+
+ /**
+ * Returns whether the given visitor accepter should still be marked as
+ * being used.
+ */
+ protected boolean shouldBeMarkedAsUsed(VisitorAccepter visitorAccepter)
+ {
+ return visitorAccepter.getVisitorInfo() != USED;
+ }
+
+
+ /**
+ * Returns whether the given visitor accepter has been marked as being used.
+ */
+ protected boolean isUsed(VisitorAccepter visitorAccepter)
+ {
+ return visitorAccepter.getVisitorInfo() == USED;
+ }
+
+
+ /**
+ * Marks the given visitor accepter as possibly being used.
+ */
+ protected void markAsPossiblyUsed(VisitorAccepter visitorAccepter)
+ {
+ visitorAccepter.setVisitorInfo(POSSIBLY_USED);
+ }
+
+
+ /**
+ * Returns whether the given visitor accepter should still be marked as
+ * possibly being used.
+ */
+ protected boolean shouldBeMarkedAsPossiblyUsed(VisitorAccepter visitorAccepter)
+ {
+ return visitorAccepter.getVisitorInfo() != USED &&
+ visitorAccepter.getVisitorInfo() != POSSIBLY_USED;
+ }
+
+
+ /**
+ * Returns whether the given visitor accepter has been marked as possibly
+ * being used.
+ */
+ protected boolean isPossiblyUsed(VisitorAccepter visitorAccepter)
+ {
+ return visitorAccepter.getVisitorInfo() == POSSIBLY_USED;
+ }
+
+
+ /**
+ * Clears any usage marks from the given visitor accepter.
+ */
+ protected void markAsUnused(VisitorAccepter visitorAccepter)
+ {
+ visitorAccepter.setVisitorInfo(null);
+ }
+
+
+ /**
+ * Marks the given constant pool entry of the given class. This includes
+ * visiting any referenced objects.
+ */
+ private void markConstant(Clazz clazz, int index)
+ {
+ clazz.constantPoolEntryAccept(index, this);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsagePrinter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsagePrinter.java
new file mode 100644
index 0000000000..c333de1377
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsagePrinter.java
@@ -0,0 +1,184 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.*;
+import proguard.classfile.visitor.*;
+
+import java.io.PrintStream;
+
+
+/**
+ * This ClassVisitor prints out the classes and class members that have been
+ * marked as being used (or not used).
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class UsagePrinter
+extends SimplifiedVisitor
+implements ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor
+{
+ private final UsageMarker usageMarker;
+ private final boolean printUnusedItems;
+ private final PrintStream ps;
+
+ // A field to remember the class name, if a header is needed for class members.
+ private String className;
+
+
+ /**
+ * Creates a new UsagePrinter that prints to <code>System.out</code>.
+ * @param usageMarker the usage marker that was used to mark the
+ * classes and class members.
+ * @param printUnusedItems a flag that indicates whether only unused items
+ * should be printed, or alternatively, only used
+ * items.
+ */
+ public UsagePrinter(UsageMarker usageMarker,
+ boolean printUnusedItems)
+ {
+ this(usageMarker, printUnusedItems, System.out);
+ }
+
+
+ /**
+ * Creates a new UsagePrinter that prints to the given stream.
+ * @param usageMarker the usage marker that was used to mark the
+ * classes and class members.
+ * @param printUnusedItems a flag that indicates whether only unused items
+ * should be printed, or alternatively, only used
+ * items.
+ * @param printStream the stream to which to print.
+ */
+ public UsagePrinter(UsageMarker usageMarker,
+ boolean printUnusedItems,
+ PrintStream printStream)
+ {
+ this.usageMarker = usageMarker;
+ this.printUnusedItems = printUnusedItems;
+ this.ps = printStream;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (usageMarker.isUsed(programClass))
+ {
+ if (printUnusedItems)
+ {
+ className = programClass.getName();
+
+ programClass.fieldsAccept(this);
+ programClass.methodsAccept(this);
+
+ className = null;
+ }
+ else
+ {
+ ps.println(ClassUtil.externalClassName(programClass.getName()));
+ }
+ }
+ else
+ {
+ if (printUnusedItems)
+ {
+ ps.println(ClassUtil.externalClassName(programClass.getName()));
+ }
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (usageMarker.isUsed(programField) ^ printUnusedItems)
+ {
+ printClassNameHeader();
+
+ ps.println(" " +
+ ClassUtil.externalFullFieldDescription(
+ programField.getAccessFlags(),
+ programField.getName(programClass),
+ programField.getDescriptor(programClass)));
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (usageMarker.isUsed(programMethod) ^ printUnusedItems)
+ {
+ printClassNameHeader();
+
+ ps.print(" ");
+ programMethod.attributesAccept(programClass, this);
+ ps.println(ClassUtil.externalFullMethodDescription(
+ programClass.getName(),
+ programMethod.getAccessFlags(),
+ programMethod.getName(programClass),
+ programMethod.getDescriptor(programClass)));
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
+
+
+ public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
+ {
+ ps.print(lineNumberTableAttribute.getLowestLineNumber() + ":" +
+ lineNumberTableAttribute.getHighestLineNumber() + ":");
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Prints the class name field. The field is then cleared, so it is not
+ * printed again.
+ */
+ private void printClassNameHeader()
+ {
+ if (className != null)
+ {
+ ps.println(ClassUtil.externalClassName(className) + ":");
+ className = null;
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsedClassFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsedClassFilter.java
new file mode 100644
index 0000000000..421cfc962b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsedClassFilter.java
@@ -0,0 +1,74 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are marked as used.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class UsedClassFilter
+implements ClassVisitor
+{
+ private final UsageMarker usageMarker;
+ private final ClassVisitor classVisitor;
+
+
+ /**
+ * Creates a new UsedClassFilter.
+ * @param usageMarker the usage marker that is used to mark the classes
+ * and class members.
+ * @param classVisitor the class visitor to which the visiting will be
+ * delegated.
+ */
+ public UsedClassFilter(UsageMarker usageMarker,
+ ClassVisitor classVisitor)
+ {
+ this.usageMarker = usageMarker;
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (usageMarker.isUsed(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (usageMarker.isUsed(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsedMemberFilter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsedMemberFilter.java
new file mode 100644
index 0000000000..fa01a06746
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/UsedMemberFilter.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.shrink;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor delegates all its method calls to another MemberVisitor,
+ * but only for Member objects that are marked as used.
+ *
+ * @see UsageMarker
+ *
+ * @author Eric Lafortune
+ */
+public class UsedMemberFilter
+implements MemberVisitor
+{
+ private final UsageMarker usageMarker;
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new UsedMemberFilter.
+ * @param usageMarker the usage marker that is used to mark the classes
+ * and class members.
+ * @param memberVisitor the member visitor to which the visiting will be
+ * delegated.
+ */
+ public UsedMemberFilter(UsageMarker usageMarker,
+ MemberVisitor memberVisitor)
+ {
+ this.usageMarker = usageMarker;
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (usageMarker.isUsed(programField))
+ {
+ memberVisitor.visitProgramField(programClass, programField);
+ }
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (usageMarker.isUsed(programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ if (usageMarker.isUsed(libraryField))
+ {
+ memberVisitor.visitLibraryField(libraryClass, libraryField);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (usageMarker.isUsed(libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/package.html
new file mode 100644
index 0000000000..897319880d
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/shrink/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains classes to perform shrinking of class files.
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/AndMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/AndMatcher.java
new file mode 100644
index 0000000000..55a8dafd67
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/AndMatcher.java
@@ -0,0 +1,49 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This StringMatcher tests whether strings matches both given StringMatcher
+ * instances.
+ *
+ * @author Eric Lafortune
+ */
+public class AndMatcher extends StringMatcher
+{
+ private final StringMatcher matcher1;
+ private final StringMatcher matcher2;
+
+
+ public AndMatcher(StringMatcher matcher1, StringMatcher matcher2)
+ {
+ this.matcher1 = matcher1;
+ this.matcher2 = matcher2;
+ }
+
+
+ // Implementations for StringMatcher.
+
+ protected boolean matches(String string, int offset, int length)
+ {
+ return matcher1.matches(string, offset, length) &&
+ matcher2.matches(string, offset, length);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/ArrayUtil.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ArrayUtil.java
new file mode 100644
index 0000000000..1c064f1213
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ArrayUtil.java
@@ -0,0 +1,1015 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+
+/**
+ * This class contains utility methods operating on arrays.
+ */
+public class ArrayUtil
+{
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(byte[] array1, byte[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (array1[index] != array2[index])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(short[] array1, short[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (array1[index] != array2[index])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(int[] array1, int[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (array1[index] != array2[index])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the elements of the two given arrays are the same.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equal(Object[] array1, Object[] array2, int size)
+ {
+ for (int index = 0; index < size; index++)
+ {
+ if (!array1[index].equals(array2[index]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Returns whether the elements of the two given arrays are the same, or
+ * both arrays are null.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @return whether the elements are the same.
+ */
+ public static boolean equalOrNull(Object[] array1, Object[] array2)
+ {
+ return array1 == null ? array2 == null :
+ equalOrNull(array1, array2, array1.length);
+ }
+
+
+ /**
+ * Returns whether the elements of the two given arrays are the same, or
+ * both arrays are null.
+ * @param array1 the first array.
+ * @param array2 the second array.
+ * @param size the size of the arrays to be checked.
+ * @return whether the elements are the same.
+ */
+ public static boolean equalOrNull(Object[] array1, Object[] array2, int size)
+ {
+ return array1 == null ? array2 == null :
+ array2 != null &&
+ equal(array1, array2, size);
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(byte[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index];
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(short[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index];
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(int[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index];
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCode(Object[] array, int size)
+ {
+ int hashCode = 0;
+
+ for (int index = 0; index < size; index++)
+ {
+ hashCode ^= array[index].hashCode();
+ }
+
+ return hashCode;
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array, or 0 if it is
+ * null.
+ * @param array the array.
+ * @return a hash code.
+ */
+ public static int hashCodeOrNull(Object[] array)
+ {
+ return array == null ? 0 : hashCode(array, array.length);
+ }
+
+
+ /**
+ * Returns a hash code for the elements of the given array, or 0 if it is
+ * null.
+ * @param array the array.
+ * @param size the size of the array to be taken into account.
+ * @return a hash code.
+ */
+ public static int hashCodeOrNull(Object[] array, int size)
+ {
+ return array == null ? 0 : hashCode(array, size);
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(byte[] array1, int size1,
+ byte[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ if (array1[index] < array2[index])
+ {
+ return -1;
+ }
+ else if (array1[index] > array2[index])
+ {
+ return 1;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(short[] array1, int size1,
+ short[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ if (array1[index] < array2[index])
+ {
+ return -1;
+ }
+ else if (array1[index] > array2[index])
+ {
+ return 1;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(int[] array1, int size1,
+ int[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ if (array1[index] < array2[index])
+ {
+ return -1;
+ }
+ else if (array1[index] > array2[index])
+ {
+ return 1;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Compares the elements of the two given arrays.
+ * @param array1 the first array.
+ * @param size1 the size of the first array.
+ * @param array2 the second array.
+ * @param size2 the size of the second array.
+ * @return 0 if all elements are the same,
+ * -1 if the first different element in the first array is smaller
+ * than the corresponding element in the second array,
+ * or 1 if it is larger.
+ */
+ public static int compare(Comparable[] array1, int size1,
+ Comparable[] array2, int size2)
+ {
+ int minSize = Math.min(size1, size2);
+
+ for (int index = 0; index < minSize; index++)
+ {
+ int comparison = ObjectUtil.compare(array1[index], array2[index]);
+ if (comparison != 0)
+ {
+ return comparison;
+ }
+ }
+
+ return size1 < size2 ? -1 :
+ size1 == size2 ? 0 :
+ 1;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static boolean[] extendArray(boolean[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ boolean[] newArray = new boolean[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static boolean[] ensureArraySize(boolean[] array,
+ int size,
+ boolean initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new boolean[size];
+
+ if (initialValue)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static byte[] add(byte[] array, int size, byte element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static byte[] insert(byte[] array, int size, int index, byte element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(byte[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static byte[] extendArray(byte[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ byte[] newArray = new byte[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static byte[] ensureArraySize(byte[] array,
+ int size,
+ byte initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new byte[size];
+
+ if (initialValue != 0)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static short[] add(short[] array, int size, short element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static short[] insert(short[] array, int size, int index, short element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(short[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static short[] extendArray(short[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ short[] newArray = new short[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static short[] ensureArraySize(short[] array,
+ int size,
+ short initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new short[size];
+
+ if (initialValue != 0)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static int[] add(int[] array, int size, int element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static int[] insert(int[] array, int size, int index, int element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(int[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static int[] extendArray(int[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ int[] newArray = new int[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static int[] ensureArraySize(int[] array,
+ int size,
+ int initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new int[size];
+
+ if (initialValue != 0)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static long[] add(long[] array, int size, long element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static long[] insert(long[] array, int size, int index, long element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(long[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = 0;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static long[] extendArray(long[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ long[] newArray = new long[size];
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static long[] ensureArraySize(long[] array,
+ int size,
+ long initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = new long[size];
+
+ if (initialValue != 0L)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+
+
+ /**
+ * Adds the given element to the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static Object[] add(Object[] array, int size, Object element)
+ {
+ array = extendArray(array, size + 1);
+
+ array[size] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Inserts the given element in the given array.
+ * The array is extended if necessary.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index at which the element is to be added.
+ * @param element the element to be added.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static Object[] insert(Object[] array, int size, int index, Object element)
+ {
+ array = extendArray(array, size + 1);
+
+ // Move the last part.
+ System.arraycopy(array, index,
+ array, index + 1,
+ size - index);
+
+ array[index] = element;
+
+ return array;
+ }
+
+
+ /**
+ * Removes the specified element from the given array.
+ * @param array the array.
+ * @param size the original size of the array.
+ * @param index the index of the element to be removed.
+ */
+ public static void remove(Object[] array, int size, int index)
+ {
+ System.arraycopy(array, index + 1,
+ array, index,
+ array.length - index - 1);
+
+ array[size - 1] = null;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @return the original array, or a copy if it had to be extended.
+ */
+ public static Object[] extendArray(Object[] array, int size)
+ {
+ // Reuse the existing array if possible.
+ if (array.length >= size)
+ {
+ return array;
+ }
+
+ // Otherwise create and initialize a new array.
+ Object[] newArray = (Object[])Array.newInstance(array.getClass().getComponentType(), size);
+
+ System.arraycopy(array, 0,
+ newArray, 0,
+ array.length);
+
+ return newArray;
+ }
+
+
+ /**
+ * Ensures the given array has a given size.
+ * @param array the array.
+ * @param size the target size of the array.
+ * @param initialValue the initial value of the elements.
+ * @return the original array, or a copy if it had to be
+ * extended.
+ */
+ public static Object[] ensureArraySize(Object[] array,
+ int size,
+ Object initialValue)
+ {
+ // Is the existing array large enough?
+ if (array.length >= size)
+ {
+ // Reinitialize the existing array.
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ else
+ {
+ // Otherwise create and initialize a new array.
+ array = (Object[])Array.newInstance(array.getClass().getComponentType(), size);
+
+ if (initialValue != null)
+ {
+ Arrays.fill(array, 0, size, initialValue);
+ }
+ }
+
+ return array;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/ClassNameParser.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ClassNameParser.java
new file mode 100644
index 0000000000..82a2a85180
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ClassNameParser.java
@@ -0,0 +1,215 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+import proguard.classfile.ClassConstants;
+
+/**
+ * This StringParser can create StringMatcher instances for regular expressions
+ * matching internal class names (or descriptors containing class names).
+ * The regular expressions can contain the following wildcards:
+ * '%' for a single internal primitive type character (V, Z, B, C, S, I, F,
+ * J, or D),
+ * '?' for a single regular class name character,
+ * '*' for any number of regular class name characters,
+ * '**' for any number of regular class name characters or package separator
+ * characters ('/'),
+ * 'L***;' for a single internal type (class name or primitive type,
+ * array or non-array), and
+ * 'L///;' for any number of internal types (class names and primitive
+ * types).
+ *
+ * @author Eric Lafortune
+ */
+public class ClassNameParser implements StringParser
+{
+ private static final char[] INTERNAL_PRIMITIVE_TYPES = new char[]
+ {
+ ClassConstants.TYPE_VOID,
+ ClassConstants.TYPE_BOOLEAN,
+ ClassConstants.TYPE_BYTE,
+ ClassConstants.TYPE_CHAR,
+ ClassConstants.TYPE_SHORT,
+ ClassConstants.TYPE_INT,
+ ClassConstants.TYPE_LONG,
+ ClassConstants.TYPE_FLOAT,
+ ClassConstants.TYPE_DOUBLE,
+ };
+
+
+ // Implementations for StringParser.
+
+ public StringMatcher parse(String regularExpression)
+ {
+ int index;
+ StringMatcher nextMatcher = new EmptyStringMatcher();
+
+ // Look for wildcards.
+ for (index = 0; index < regularExpression.length(); index++)
+ {
+ // Is there an 'L///;' wildcard?
+ if (regularExpression.regionMatches(index, "L///;", 0, 5))
+ {
+ SettableMatcher settableMatcher = new SettableMatcher();
+
+ // Create a matcher, recursively, for the remainder of the
+ // string, optionally preceded by any type.
+ nextMatcher =
+ new OrMatcher(parse(regularExpression.substring(index + 5)),
+ createAnyTypeMatcher(settableMatcher));
+
+ settableMatcher.setMatcher(nextMatcher);
+
+ break;
+ }
+
+ // Is there an 'L***;' wildcard?
+ if (regularExpression.regionMatches(index, "L***;", 0, 5))
+ {
+ // Create a matcher for the wildcard and, recursively, for the
+ // remainder of the string.
+ nextMatcher =
+ createAnyTypeMatcher(parse(regularExpression.substring(index + 5)));
+ break;
+ }
+
+ // Is there a '**' wildcard?
+ if (regularExpression.regionMatches(index, "**", 0, 2))
+ {
+ // Create a matcher for the wildcard and, recursively, for the
+ // remainder of the string.
+ nextMatcher =
+ new VariableStringMatcher(null,
+ new char[] { ClassConstants.TYPE_CLASS_END },
+ 0,
+ Integer.MAX_VALUE,
+ parse(regularExpression.substring(index + 2)));
+ break;
+ }
+
+ // Is there a '*' wildcard?
+ else if (regularExpression.charAt(index) == '*')
+ {
+ // Create a matcher for the wildcard and, recursively, for the
+ // remainder of the string.
+ nextMatcher =
+ new VariableStringMatcher(null,
+ new char[] { ClassConstants.TYPE_CLASS_END, ClassConstants.PACKAGE_SEPARATOR },
+ 0,
+ Integer.MAX_VALUE,
+ parse(regularExpression.substring(index + 1)));
+ break;
+ }
+
+ // Is there a '?' wildcard?
+ else if (regularExpression.charAt(index) == '?')
+ {
+ // Create a matcher for the wildcard and, recursively, for the
+ // remainder of the string.
+ nextMatcher =
+ new VariableStringMatcher(null,
+ new char[] { ClassConstants.TYPE_CLASS_END, ClassConstants.PACKAGE_SEPARATOR },
+ 1,
+ 1,
+ parse(regularExpression.substring(index + 1)));
+ break;
+ }
+
+ // Is there a '%' wildcard?
+ else if (regularExpression.charAt(index) == '%')
+ {
+ // Create a matcher for the wildcard and, recursively, for the
+ // remainder of the string.
+ nextMatcher =
+ new VariableStringMatcher(INTERNAL_PRIMITIVE_TYPES,
+ null,
+ 1,
+ 1,
+ parse(regularExpression.substring(index + 1)));
+ break;
+ }
+ }
+
+ // Return a matcher for the fixed first part of the regular expression,
+ // if any, and the remainder.
+ return index != 0 ?
+ (StringMatcher)new FixedStringMatcher(regularExpression.substring(0, index), nextMatcher) :
+ (StringMatcher)nextMatcher;
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Creates a StringMatcher that matches any type (class or primitive type,
+ * array or non-array) and then the given matcher.
+ */
+ private VariableStringMatcher createAnyTypeMatcher(StringMatcher nextMatcher)
+ {
+ return new VariableStringMatcher(new char[] { ClassConstants.TYPE_ARRAY },
+ null,
+ 0,
+ 255,
+ new OrMatcher(
+ new VariableStringMatcher(INTERNAL_PRIMITIVE_TYPES,
+ null,
+ 1,
+ 1,
+ nextMatcher),
+ new VariableStringMatcher(new char[] { ClassConstants.TYPE_CLASS_START },
+ null,
+ 1,
+ 1,
+ new VariableStringMatcher(null,
+ new char[] { ClassConstants.TYPE_CLASS_END },
+ 0,
+ Integer.MAX_VALUE,
+ new VariableStringMatcher(new char[] { ClassConstants.TYPE_CLASS_END },
+ null,
+ 1,
+ 1,
+ nextMatcher)))));
+ }
+
+
+ /**
+ * A main method for testing class name matching.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ System.out.println("Regular expression ["+args[0]+"]");
+ ClassNameParser parser = new ClassNameParser();
+ StringMatcher matcher = parser.parse(args[0]);
+ for (int index = 1; index < args.length; index++)
+ {
+ String string = args[index];
+ System.out.print("String ["+string+"]");
+ System.out.println(" -> match = "+matcher.matches(args[index]));
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/ConstantMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ConstantMatcher.java
new file mode 100644
index 0000000000..b640eca60f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ConstantMatcher.java
@@ -0,0 +1,48 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This StringMatcher matches any string or no string at all.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantMatcher extends StringMatcher
+{
+ private boolean matches;
+
+
+ /**
+ * Creates a new ConstantMatcher that always returns the given result.
+ */
+ public ConstantMatcher(boolean matches)
+ {
+ this.matches = matches;
+ }
+
+
+ // Implementations for StringMatcher.
+
+ protected boolean matches(String string, int offset, int length)
+ {
+ return matches;
+ }
+} \ No newline at end of file
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/EmptyStringMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/EmptyStringMatcher.java
new file mode 100644
index 0000000000..a183157176
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/EmptyStringMatcher.java
@@ -0,0 +1,36 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This StringMatcher tests whether strings are empty.
+ *
+ * @author Eric Lafortune
+ */
+public class EmptyStringMatcher extends StringMatcher
+{
+ // Implementations for StringMatcher.
+
+ protected boolean matches(String string, int offset, int length)
+ {
+ return length == 0;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/ExtensionMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ExtensionMatcher.java
new file mode 100644
index 0000000000..94cca054ce
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ExtensionMatcher.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This StringMatcher tests whether strings end in a given extension, ignoring
+ * its case.
+ *
+ * @author Eric Lafortune
+ */
+public class ExtensionMatcher extends StringMatcher
+{
+ private final String extension;
+
+
+ /**
+ * Creates a new StringMatcher.
+ * @param extension the extension against which strings will be matched.
+ */
+ public ExtensionMatcher(String extension)
+ {
+ this.extension = extension;
+ }
+
+
+ // Implementations for StringMatcher.
+
+ protected boolean matches(String string, int offset, int length)
+ {
+ return endsWithIgnoreCase(string, offset, length, extension);
+ }
+
+
+ /**
+ * Returns whether the given string ends with the given suffix, ignoring its
+ * case.
+ */
+ private static boolean endsWithIgnoreCase(String string, int offset, int length, String suffix)
+ {
+ int suffixLength = suffix.length();
+
+ return string.regionMatches(true, offset + length - suffixLength, suffix, 0, suffixLength);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/FileNameParser.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/FileNameParser.java
new file mode 100644
index 0000000000..144ff578a0
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/FileNameParser.java
@@ -0,0 +1,121 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+import java.io.File;
+
+/**
+ * This StringParser can create StringMatcher instances for regular expressions
+ * matching file names. The regular expressions can contain the following
+ * wildcards:
+ * '?' for a single regular file name character,
+ * '*' for any number of regular file name characters, and
+ * '**' for any number of regular file name characters or directory separator
+ * characters (always including '/').
+ *
+ * @author Eric Lafortune
+ */
+public class FileNameParser implements StringParser
+{
+ // Implementations for StringParser.
+
+ public StringMatcher parse(String regularExpression)
+ {
+ int index;
+ StringMatcher nextMatcher = new EmptyStringMatcher();
+
+ // Look for wildcards.
+ for (index = 0; index < regularExpression.length(); index++)
+ {
+ // Is there a '**' wildcard?
+ if (regularExpression.regionMatches(index, "**", 0, 2))
+ {
+ // Create a matcher for the wildcard and, recursively, for the
+ // remainder of the string.
+ nextMatcher =
+ new VariableStringMatcher(null,
+ null,
+ 0,
+ Integer.MAX_VALUE,
+ parse(regularExpression.substring(index + 2)));
+ break;
+ }
+
+ // Is there a '*' wildcard?
+ else if (regularExpression.charAt(index) == '*')
+ {
+ // Create a matcher for the wildcard and, recursively, for the
+ // remainder of the string.
+ nextMatcher =
+ new VariableStringMatcher(null,
+ new char[] { File.pathSeparatorChar, '/' },
+ 0,
+ Integer.MAX_VALUE,
+ parse(regularExpression.substring(index + 1)));
+ break;
+ }
+
+ // Is there a '?' wildcard?
+ else if (regularExpression.charAt(index) == '?')
+ {
+ // Create a matcher for the wildcard and, recursively, for the
+ // remainder of the string.
+ nextMatcher =
+ new VariableStringMatcher(null,
+ new char[] { File.pathSeparatorChar, '/' },
+ 1,
+ 1,
+ parse(regularExpression.substring(index + 1)));
+ break;
+ }
+ }
+
+ // Return a matcher for the fixed first part of the regular expression,
+ // if any, and the remainder.
+ return index != 0 ?
+ (StringMatcher)new FixedStringMatcher(regularExpression.substring(0, index), nextMatcher) :
+ (StringMatcher)nextMatcher;
+ }
+
+
+ /**
+ * A main method for testing file name matching.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ System.out.println("Regular expression ["+args[0]+"]");
+ FileNameParser parser = new FileNameParser();
+ StringMatcher matcher = parser.parse(args[0]);
+ for (int index = 1; index < args.length; index++)
+ {
+ String string = args[index];
+ System.out.print("String ["+string+"]");
+ System.out.println(" -> match = "+matcher.matches(args[index]));
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/FixedStringMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/FixedStringMatcher.java
new file mode 100644
index 0000000000..d8e7bf7d9f
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/FixedStringMatcher.java
@@ -0,0 +1,60 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This StringMatcher tests whether strings start with a given fixed string
+ * and then match another optional given StringMatcher.
+ *
+ * @author Eric Lafortune
+ */
+public class FixedStringMatcher extends StringMatcher
+{
+ private final String fixedString;
+ private final StringMatcher nextMatcher;
+
+
+ public FixedStringMatcher(String fixedString)
+ {
+ this(fixedString, null);
+ }
+
+
+ public FixedStringMatcher(String fixedString, StringMatcher nextMatcher)
+ {
+ this.fixedString = fixedString;
+ this.nextMatcher = nextMatcher;
+ }
+
+
+ // Implementations for StringMatcher.
+
+ protected boolean matches(String string, int offset, int length)
+ {
+ int fixedStringLength = fixedString.length();
+ return length >= fixedStringLength &&
+ string.startsWith(fixedString, offset) &&
+ (nextMatcher == null ||
+ nextMatcher.matches(string,
+ offset + fixedStringLength,
+ length - fixedStringLength));
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/ListMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ListMatcher.java
new file mode 100644
index 0000000000..bdf1b904da
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ListMatcher.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This StringMatcher tests whether strings match a given list of StringMatcher
+ * instances. The instances are considered sequentially. Each instance in the
+ * list can optionally be negated, meaning that a match makes the entire
+ * remaining match fail.
+ *
+ * @author Eric Lafortune
+ */
+public class ListMatcher extends StringMatcher
+{
+ private final StringMatcher[] matchers;
+ private final boolean[] negate;
+
+
+ public ListMatcher(StringMatcher[] matchers)
+ {
+ this(matchers, null);
+ }
+
+
+ public ListMatcher(StringMatcher[] matchers, boolean[] negate)
+ {
+ this.matchers = matchers;
+ this.negate = negate;
+ }
+
+
+ // Implementations for StringMatcher.
+
+ protected boolean matches(String string, int offset, int length)
+ {
+ // Check the list of matchers.
+ for (int index = 0; index < matchers.length; index++)
+ {
+ StringMatcher matcher = matchers[index];
+ if (matcher.matches(string, offset, length))
+ {
+ return negate == null ||
+ !negate[index];
+ }
+ }
+
+ return negate != null &&
+ negate[negate.length - 1];
+
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/ListParser.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ListParser.java
new file mode 100644
index 0000000000..91448b2ee1
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ListParser.java
@@ -0,0 +1,137 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+import java.util.List;
+
+/**
+ * This StringParser can create StringMatcher instances for regular expressions.
+ * The regular expressions are either presented as a list, or they are
+ * interpreted as comma-separated lists, optionally prefixed with '!' negators.
+ * If an entry with a negator matches, a negative match is returned, without
+ * considering any subsequent entries in the list. The creation of StringMatcher
+ * instances for the entries is delegated to the given StringParser.
+ *
+ * @author Eric Lafortune
+ */
+public class ListParser implements StringParser
+{
+ private final StringParser stringParser;
+
+
+ /**
+ * Creates a new ListParser that parses individual elements in the
+ * comma-separated list with the given StringParser.
+ */
+ public ListParser(StringParser stringParser)
+ {
+ this.stringParser = stringParser;
+ }
+
+
+ // Implementations for StringParser.
+
+ public StringMatcher parse(String regularExpression)
+ {
+ // Does the regular expression contain a ',' list separator?
+ return parse(ListUtil.commaSeparatedList(regularExpression));
+ }
+
+
+ /**
+ * Creates a StringMatcher for the given regular expression, which can
+ * be a list of optionally negated simple entries.
+ * <p>
+ * An empty list results in a StringMatcher that matches any string.
+ */
+ public StringMatcher parse(List regularExpressions)
+ {
+ StringMatcher listMatcher = null;
+
+ // Loop over all simple regular expressions, backward, creating a
+ // linked list of matchers.
+ for (int index = regularExpressions.size()-1; index >= 0; index--)
+ {
+ String regularExpression = (String)regularExpressions.get(index);
+
+ StringMatcher entryMatcher = parseEntry(regularExpression);
+
+ // Prepend the entry matcher.
+ listMatcher =
+ listMatcher == null ?
+ (StringMatcher)entryMatcher :
+ isNegated(regularExpression) ?
+ (StringMatcher)new AndMatcher(entryMatcher, listMatcher) :
+ (StringMatcher)new OrMatcher(entryMatcher, listMatcher);
+ }
+
+ return listMatcher != null ? listMatcher : new ConstantMatcher(true);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Creates a StringMatcher for the given regular expression, which is a
+ * an optionally negated simple expression.
+ */
+ private StringMatcher parseEntry(String regularExpression)
+ {
+ // Wrap the matcher if the regular expression starts with a '!' negator.
+ return isNegated(regularExpression) ?
+ new NotMatcher(stringParser.parse(regularExpression.substring(1))) :
+ stringParser.parse(regularExpression);
+ }
+
+
+ /**
+ * Returns whether the given simple regular expression is negated.
+ */
+ private boolean isNegated(String regularExpression)
+ {
+ return regularExpression.length() > 0 &&
+ regularExpression.charAt(0) == '!';
+ }
+
+
+ /**
+ * A main method for testing name matching.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ System.out.println("Regular expression ["+args[0]+"]");
+ ListParser parser = new ListParser(new NameParser());
+ StringMatcher matcher = parser.parse(args[0]);
+ for (int index = 1; index < args.length; index++)
+ {
+ String string = args[index];
+ System.out.print("String ["+string+"]");
+ System.out.println(" -> match = "+matcher.matches(args[index]));
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/ListUtil.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ListUtil.java
new file mode 100644
index 0000000000..6b63669cbd
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ListUtil.java
@@ -0,0 +1,180 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+import java.util.*;
+
+
+/**
+ * This class provides some utility methods for working with
+ * <code>java.util.List</code> objects.
+ *
+ * @author Eric Lafortune
+ */
+public class ListUtil
+{
+ /**
+ * Creates a comma-separated String from the given List of String objects.
+ */
+ public static String commaSeparatedString(List list, boolean quoteStrings)
+ {
+ if (list == null)
+ {
+ return null;
+ }
+
+ StringBuffer buffer = new StringBuffer();
+
+ for (int index = 0; index < list.size(); index++)
+ {
+ if (index > 0)
+ {
+ buffer.append(',');
+ }
+
+ String string = (String)list.get(index);
+
+ if (quoteStrings)
+ {
+ string = quotedString(string);
+ }
+
+ buffer.append(string);
+ }
+
+ return buffer.toString();
+ }
+
+
+ /**
+ * Creates a List of String objects from the given comma-separated String.
+ */
+ public static List commaSeparatedList(String string)
+ {
+ if (string == null)
+ {
+ return null;
+ }
+
+ List list = new ArrayList();
+ int index = 0;
+ while ((index = skipWhitespace(string, index)) < string.length())
+ {
+ int nextIndex;
+
+ // Do we have an opening quote?
+ if (string.charAt(index) == '\'')
+ {
+ // Parse a quoted string.
+ nextIndex = string.indexOf('\'', index + 1);
+ if (nextIndex < 0)
+ {
+ nextIndex = string.length();
+ }
+
+ list.add(string.substring(index + 1, nextIndex));
+ }
+ else
+ {
+ // Parse a non-quoted string.
+ nextIndex = string.indexOf(',', index);
+ if (nextIndex < 0)
+ {
+ nextIndex = string.length();
+ }
+
+ String substring = string.substring(index, nextIndex).trim();
+ if (substring.length() > 0)
+ {
+ list.add(substring);
+ }
+ }
+
+ index = nextIndex + 1;
+ }
+
+ return list;
+ }
+
+
+ /**
+ * Skips any whitespace characters.
+ */
+ private static int skipWhitespace(String string, int index)
+ {
+ while (index < string.length() &&
+ Character.isWhitespace(string.charAt(index)))
+ {
+ index++;
+ }
+ return index;
+ }
+
+
+ /**
+ * Returns a quoted version of the given string, if necessary.
+ */
+ private static String quotedString(String string)
+ {
+ return string.length() == 0 ||
+ string.indexOf(' ') >= 0 ||
+ string.indexOf('@') >= 0 ||
+ string.indexOf('{') >= 0 ||
+ string.indexOf('}') >= 0 ||
+ string.indexOf('(') >= 0 ||
+ string.indexOf(')') >= 0 ||
+ string.indexOf(':') >= 0 ||
+ string.indexOf(';') >= 0 ||
+ string.indexOf(',') >= 0 ? ("'" + string + "'") :
+ ( string );
+ }
+
+
+ public static void main(String[] args)
+ {
+ if (args.length == 1)
+ {
+ System.out.println("Input string: ["+args[0]+"]");
+
+ List list = commaSeparatedList(args[0]);
+
+ System.out.println("Resulting list:");
+ for (int index = 0; index < list.size(); index++)
+ {
+ System.out.println("["+list.get(index)+"]");
+ }
+ }
+ else
+ {
+ List list = Arrays.asList(args);
+
+ System.out.println("Input list:");
+ for (int index = 0; index < list.size(); index++)
+ {
+ System.out.println("["+list.get(index)+"]");
+ }
+
+ String string = commaSeparatedString(list, true);
+
+ System.out.println("Resulting string: ["+string+"]");
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/NameParser.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/NameParser.java
new file mode 100644
index 0000000000..351ef0232e
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/NameParser.java
@@ -0,0 +1,106 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This StringParser can create StringMatcher instances for regular expressions
+ * matching names. The regular expressions are interpreted as comma-separated
+ * lists of names, optionally prefixed with '!' negators.
+ * If a name with a negator matches, a negative match is returned, without
+ * considering any subsequent entries in the list.
+ * Names can contain the following wildcards:
+ * '?' for a single character, and
+ * '*' for any number of characters.
+ *
+ * @author Eric Lafortune
+ */
+public class NameParser implements StringParser
+{
+ // Implementations for StringParser.
+
+ public StringMatcher parse(String regularExpression)
+ {
+ int index;
+ StringMatcher nextMatcher = new EmptyStringMatcher();
+
+ // Look for wildcards.
+ for (index = 0; index < regularExpression.length(); index++)
+ {
+ // Is there a '*' wildcard?
+ if (regularExpression.charAt(index) == '*')
+ {
+ // Create a matcher for the wildcard and, recursively, for the
+ // remainder of the string.
+ nextMatcher =
+ new VariableStringMatcher(null,
+ null,
+ 0,
+ Integer.MAX_VALUE,
+ parse(regularExpression.substring(index + 1)));
+ break;
+ }
+
+ // Is there a '?' wildcard?
+ else if (regularExpression.charAt(index) == '?')
+ {
+ // Create a matcher for the wildcard and, recursively, for the
+ // remainder of the string.
+ nextMatcher =
+ new VariableStringMatcher(null,
+ null,
+ 1,
+ 1,
+ parse(regularExpression.substring(index + 1)));
+ break;
+ }
+ }
+
+ // Return a matcher for the fixed first part of the regular expression,
+ // if any, and the remainder.
+ return index != 0 ?
+ (StringMatcher)new FixedStringMatcher(regularExpression.substring(0, index), nextMatcher) :
+ (StringMatcher)nextMatcher;
+ }
+
+
+ /**
+ * A main method for testing name matching.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ System.out.println("Regular expression ["+args[0]+"]");
+ NameParser parser = new NameParser();
+ StringMatcher matcher = parser.parse(args[0]);
+ for (int index = 1; index < args.length; index++)
+ {
+ String string = args[index];
+ System.out.print("String ["+string+"]");
+ System.out.println(" -> match = "+matcher.matches(args[index]));
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/NotMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/NotMatcher.java
new file mode 100644
index 0000000000..8f67b85e24
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/NotMatcher.java
@@ -0,0 +1,46 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This StringMatcher tests whether strings does not match the given
+ * StringMatcher.
+ *
+ * @author Eric Lafortune
+ */
+public class NotMatcher extends StringMatcher
+{
+ private final StringMatcher matcher;
+
+
+ public NotMatcher(StringMatcher matcher)
+ {
+ this.matcher = matcher;
+ }
+
+
+ // Implementations for StringMatcher.
+
+ protected boolean matches(String string, int offset, int length)
+ {
+ return !matcher.matches(string, offset, length);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/ObjectUtil.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ObjectUtil.java
new file mode 100644
index 0000000000..c698fef997
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/ObjectUtil.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package proguard.util;
+
+/**
+ * This class contains utility methods operating on objects.
+ */
+public class ObjectUtil
+{
+ /**
+ * Returns whether the given objects are the same.
+ * @param object1 the first object, may be null.
+ * @param object2 the second object, may be null.
+ * @return whether the objects are the same.
+ */
+ public static boolean equal(Object object1, Object object2)
+ {
+ return object1 == null ?
+ object2 == null :
+ object1.equals(object2);
+ }
+
+
+ /**
+ * Returns the hash code of the given object, or 0 if it is null.
+ * @param object the object, may be null.
+ * @return the hash code.
+ */
+ public static int hashCode(Object object)
+ {
+ return object == null ? 0 : object.hashCode();
+ }
+
+
+ /**
+ * Returns a comparison of the two given objects.
+ * @param object1 the first object, may be null.
+ * @param object2 the second object, may be null.
+ * @return -1, 0, or 1.
+ * @see Comparable#compareTo(Object)
+ */
+ public static int compare(Comparable object1, Comparable object2)
+ {
+ return object1 == null ?
+ object2 == null ? 0 : -1 :
+ object2 == null ? 1 : object1.compareTo(object2);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/OrMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/OrMatcher.java
new file mode 100644
index 0000000000..953f6b9085
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/OrMatcher.java
@@ -0,0 +1,49 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This StringMatcher tests whether strings matches either of the given
+ * StringMatcher instances.
+ *
+ * @author Eric Lafortune
+ */
+public class OrMatcher extends StringMatcher
+{
+ private final StringMatcher matcher1;
+ private final StringMatcher matcher2;
+
+
+ public OrMatcher(StringMatcher matcher1, StringMatcher matcher2)
+ {
+ this.matcher1 = matcher1;
+ this.matcher2 = matcher2;
+ }
+
+
+ // Implementations for StringMatcher.
+
+ protected boolean matches(String string, int offset, int length)
+ {
+ return matcher1.matches(string, offset, length) ||
+ matcher2.matches(string, offset, length);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/SettableMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/SettableMatcher.java
new file mode 100644
index 0000000000..6a2093b527
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/SettableMatcher.java
@@ -0,0 +1,46 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This StringMatcher delegates to a another StringMatcher that can be set
+ * after this StringMatcher has been constructed.
+ *
+ * @author Eric Lafortune
+ */
+public class SettableMatcher extends StringMatcher
+{
+ private StringMatcher matcher;
+
+
+ public void setMatcher(StringMatcher matcher)
+ {
+ this.matcher = matcher;
+ }
+
+
+ // Implementations for StringMatcher.
+
+ protected boolean matches(String string, int offset, int length)
+ {
+ return matcher.matches(string, offset, length);
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/StringMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/StringMatcher.java
new file mode 100644
index 0000000000..3e4c3d9a1a
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/StringMatcher.java
@@ -0,0 +1,51 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+
+/**
+ * This abstract class provides methods to determine whether strings match
+ * a given criterion, which is specified by the implementation.
+ *
+ * @author Eric Lafortune
+ */
+public abstract class StringMatcher
+{
+ /**
+ * Checks whether the given string matches.
+ * @param string the string to match.
+ * @return a boolean indicating whether the string matches the criterion.
+ */
+ public boolean matches(String string)
+ {
+ return matches(string, 0, string.length());
+ }
+
+
+ /**
+ * Checks whether the given substring matches.
+ * @param string the string to match.
+ * @param offset the start offset of the substring.
+ * @param length the length of the substring.
+ * @return a boolean indicating whether the substring matches the criterion.
+ */
+ protected abstract boolean matches(String string, int offset, int length);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/StringParser.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/StringParser.java
new file mode 100644
index 0000000000..1691445ede
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/StringParser.java
@@ -0,0 +1,35 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This interface provides a method to create a SringMatcher for a given
+ * regular expression.
+ *
+ * @author Eric Lafortune
+ */
+public interface StringParser
+{
+ /**
+ * Creates a StringMatcher for the given regular expression.
+ */
+ public StringMatcher parse(String regularExpression);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/VariableStringMatcher.java b/third_party/java/proguard/proguard5.3.3/src/proguard/util/VariableStringMatcher.java
new file mode 100644
index 0000000000..8673ce12df
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/VariableStringMatcher.java
@@ -0,0 +1,126 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.util;
+
+/**
+ * This StringMatcher tests whether strings start with a specified variable
+ * string and then match another given StringMatcher.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableStringMatcher extends StringMatcher
+{
+ private final char[] allowedCharacters;
+ private final char[] disallowedCharacters;
+ private final int minimumLength;
+ private final int maximumLength;
+ private final StringMatcher nextMatcher;
+
+
+ public VariableStringMatcher(char[] allowedCharacters,
+ char[] disallowedCharacters,
+ int minimumLength,
+ int maximumLength,
+ StringMatcher nextMatcher)
+ {
+ this.allowedCharacters = allowedCharacters;
+ this.disallowedCharacters = disallowedCharacters;
+ this.minimumLength = minimumLength;
+ this.maximumLength = maximumLength;
+ this.nextMatcher = nextMatcher;
+ }
+
+ // Implementations for StringMatcher.
+
+ protected boolean matches(String string, int offset, int length)
+ {
+ if (length < minimumLength)
+ {
+ return false;
+ }
+
+ // Check the first minimum number of characters.
+ for (int index = offset; index < offset + minimumLength; index++)
+ {
+ if (!isAllowedCharacter(string.charAt(index)))
+ {
+ return false;
+ }
+ }
+
+ int maximumLength = Math.min(this.maximumLength, length);
+
+ // Check the remaining characters, up to the maximum number.
+ for (int index = offset + minimumLength; index < offset + maximumLength; index++)
+ {
+ if (nextMatcher.matches(string, index, length + offset - index))
+ {
+ return true;
+ }
+
+ if (!isAllowedCharacter(string.charAt(index)))
+ {
+ return false;
+ }
+ }
+
+ // Check the remaining characters in the string.
+ return nextMatcher.matches(string, offset + maximumLength, length - maximumLength);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the given character is allowed in the variable string.
+ */
+ private boolean isAllowedCharacter(char character)
+ {
+ // Check the allowed characters.
+ if (allowedCharacters != null)
+ {
+ for (int index = 0; index < allowedCharacters.length; index++)
+ {
+ if (allowedCharacters[index] == character)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // Check the disallowed characters.
+ if (disallowedCharacters != null)
+ {
+ for (int index = 0; index < disallowedCharacters.length; index++)
+ {
+ if (disallowedCharacters[index] == character)
+ {
+ return false;
+ }
+ }
+ }
+
+ // Any remaining character is allowed.
+ return true;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/util/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/util/package.html
new file mode 100644
index 0000000000..cb14fdc0aa
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/util/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains utility classes for regular expression matching,...
+</body>
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/wtk/ProGuardObfuscator.java b/third_party/java/proguard/proguard5.3.3/src/proguard/wtk/ProGuardObfuscator.java
new file mode 100644
index 0000000000..0003ccee30
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/wtk/ProGuardObfuscator.java
@@ -0,0 +1,142 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.wtk;
+
+import com.sun.kvem.environment.Obfuscator;
+import proguard.*;
+
+import java.io.*;
+
+
+/**
+ * ProGuard plug-in for the J2ME Wireless Toolkit.
+ * <p>
+ * In order to integrate this plug-in in the toolkit, you'll have to put the
+ * following lines in the file
+ * {j2mewtk.dir}<code>/wtklib/Linux/ktools.properties</code> or
+ * {j2mewtk.dir}<code>\wtklib\Windows\ktools.properties</code> (whichever is
+ * applicable).
+ * <p>
+ * <pre>
+ * obfuscator.runner.class.name: proguard.wtk.ProGuardObfuscator
+ * obfuscator.runner.classpath: /usr/local/java/proguard1.6/lib/proguard.jar
+ * </pre>
+ * Please make sure the class path is set correctly for your system.
+ *
+ * @author Eric Lafortune
+ */
+public class ProGuardObfuscator implements Obfuscator
+{
+ private static final String DEFAULT_CONFIGURATION = "default.pro";
+
+
+ // Implementations for Obfuscator.
+
+ public void createScriptFile(File jadFile,
+ File projectDir)
+ {
+ // We don't really need to create a script file;
+ // we'll just fill out all options in the run method.
+ }
+
+
+ public void run(File obfuscatedJarFile,
+ String wtkBinDir,
+ String wtkLibDir,
+ String jarFileName,
+ String projectDirName,
+ String classPath,
+ String emptyAPI)
+ throws IOException
+ {
+ // Create the ProGuard configuration.
+ Configuration configuration = new Configuration();
+
+ // Parse the default configuration file.
+ ConfigurationParser parser = new ConfigurationParser(this.getClass().getResource(DEFAULT_CONFIGURATION),
+ System.getProperties());
+
+ try
+ {
+ parser.parse(configuration);
+
+ // Fill out the library class path.
+ configuration.libraryJars = classPath(classPath);
+
+ // Fill out the program class path (input and output).
+ configuration.programJars = new ClassPath();
+ configuration.programJars.add(new ClassPathEntry(new File(jarFileName), false));
+ configuration.programJars.add(new ClassPathEntry(obfuscatedJarFile, true));
+
+ // The preverify tool seems to unpack the resulting classes,
+ // so we must not use mixed-case class names on Windows.
+ configuration.useMixedCaseClassNames =
+ !System.getProperty("os.name").regionMatches(true, 0, "windows", 0, 7);
+
+ // Run ProGuard with these options.
+ ProGuard proGuard = new ProGuard(configuration);
+ proGuard.execute();
+
+ }
+ catch (ParseException ex)
+ {
+ throw new IOException(ex.getMessage());
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+
+
+ /**
+ * Converts the given class path String into a ClassPath object.
+ */
+ private ClassPath classPath(String classPathString)
+ {
+ ClassPath classPath = new ClassPath();
+
+ String separator = System.getProperty("path.separator");
+
+ int index = 0;
+ while (index < classPathString.length())
+ {
+ // Find the next separator, or the end of the String.
+ int next_index = classPathString.indexOf(separator, index);
+ if (next_index < 0)
+ {
+ next_index = classPathString.length();
+ }
+
+ // Create and add the found class path entry.
+ ClassPathEntry classPathEntry =
+ new ClassPathEntry(new File(classPathString.substring(index, next_index)),
+ false);
+
+ classPath.add(classPathEntry);
+
+ // Continue after the separator.
+ index = next_index + 1;
+ }
+
+ return classPath;
+ }
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/wtk/default.pro b/third_party/java/proguard/proguard5.3.3/src/proguard/wtk/default.pro
new file mode 100644
index 0000000000..d31714f0d5
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/wtk/default.pro
@@ -0,0 +1,114 @@
+-dontnote
+-microedition
+-mergeinterfacesaggressively
+-overloadaggressively
+-repackageclasses ''
+-allowaccessmodification
+
+# Keep all extensions of javax.microedition.midlet.MIDlet.
+-keep public class * extends javax.microedition.midlet.MIDlet
+
+# Keep all native class/method names.
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+# Remove all invocations of System methods without side effects
+# whose return values are not used.
+-assumenosideeffects public class java.lang.System {
+ public static native long currentTimeMillis();
+ static java.lang.Class getCallerClass();
+ public static native int identityHashCode(java.lang.Object);
+ public static java.lang.SecurityManager getSecurityManager();
+ public static java.util.Properties getProperties();
+ public static java.lang.String getProperty(java.lang.String);
+ public static java.lang.String getenv(java.lang.String);
+ public static native java.lang.String mapLibraryName(java.lang.String);
+ public static java.lang.String getProperty(java.lang.String,java.lang.String);
+}
+
+# Remove all invocations of String methods without side effects
+# whose return values are not used.
+-assumenosideeffects public class java.lang.String {
+ public java.lang.String();
+ public java.lang.String(byte[]);
+ public java.lang.String(byte[],int);
+ public java.lang.String(byte[],int,int);
+ public java.lang.String(byte[],int,int,int);
+ public java.lang.String(byte[],int,int,java.lang.String);
+ public java.lang.String(byte[],java.lang.String);
+ public java.lang.String(char[]);
+ public java.lang.String(char[],int,int);
+ public java.lang.String(java.lang.String);
+ public java.lang.String(java.lang.StringBuffer);
+ public static java.lang.String copyValueOf(char[]);
+ public static java.lang.String copyValueOf(char[],int,int);
+ public static java.lang.String valueOf(boolean);
+ public static java.lang.String valueOf(char);
+ public static java.lang.String valueOf(char[]);
+ public static java.lang.String valueOf(char[],int,int);
+ public static java.lang.String valueOf(double);
+ public static java.lang.String valueOf(float);
+ public static java.lang.String valueOf(int);
+ public static java.lang.String valueOf(java.lang.Object);
+ public static java.lang.String valueOf(long);
+ public boolean contentEquals(java.lang.StringBuffer);
+ public boolean endsWith(java.lang.String);
+ public boolean equalsIgnoreCase(java.lang.String);
+ public boolean equals(java.lang.Object);
+ public boolean matches(java.lang.String);
+ public boolean regionMatches(boolean,int,java.lang.String,int,int);
+ public boolean regionMatches(int,java.lang.String,int,int);
+ public boolean startsWith(java.lang.String);
+ public boolean startsWith(java.lang.String,int);
+ public byte[] getBytes();
+ public byte[] getBytes(java.lang.String);
+ public char charAt(int);
+ public char[] toCharArray();
+ public int compareToIgnoreCase(java.lang.String);
+ public int compareTo(java.lang.Object);
+ public int compareTo(java.lang.String);
+ public int hashCode();
+ public int indexOf(int);
+ public int indexOf(int,int);
+ public int indexOf(java.lang.String);
+ public int indexOf(java.lang.String,int);
+ public int lastIndexOf(int);
+ public int lastIndexOf(int,int);
+ public int lastIndexOf(java.lang.String);
+ public int lastIndexOf(java.lang.String,int);
+ public int length();
+ public java.lang.CharSequence subSequence(int,int);
+ public java.lang.String concat(java.lang.String);
+ public java.lang.String replaceAll(java.lang.String,java.lang.String);
+ public java.lang.String replace(char,char);
+ public java.lang.String replaceFirst(java.lang.String,java.lang.String);
+ public java.lang.String[] split(java.lang.String);
+ public java.lang.String[] split(java.lang.String,int);
+ public java.lang.String substring(int);
+ public java.lang.String substring(int,int);
+ public java.lang.String toLowerCase();
+ public java.lang.String toLowerCase(java.util.Locale);
+ public java.lang.String toString();
+ public java.lang.String toUpperCase();
+ public java.lang.String toUpperCase(java.util.Locale);
+ public java.lang.String trim();
+}
+
+
+# Remove all invocations of StringBuffer methods without side effects
+# whose return values are not used.
+-assumenosideeffects public class java.lang.StringBuffer {
+ public java.lang.StringBuffer();
+ public java.lang.StringBuffer(int);
+ public java.lang.StringBuffer(java.lang.String);
+ public java.lang.String toString();
+ public char charAt(int);
+ public int capacity();
+ public int indexOf(java.lang.String,int);
+ public int lastIndexOf(java.lang.String);
+ public int lastIndexOf(java.lang.String,int);
+ public int length();
+ public java.lang.String substring(int);
+ public java.lang.String substring(int,int);
+}
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/wtk/package.html b/third_party/java/proguard/proguard5.3.3/src/proguard/wtk/package.html
new file mode 100644
index 0000000000..6efc6441d8
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/wtk/package.html
@@ -0,0 +1,3 @@
+<body>
+This package contains the J2ME Wireless Toolkit plug-in for ProGuard.
+</body>