[proguard] 01/02: Imported Upstream version 4.3

Emmanuel Bourg ebourg-guest at moszumanska.debian.org
Thu Apr 10 09:00:40 UTC 2014


This is an automated email from the git hooks/post-receive script.

ebourg-guest pushed a commit to annotated tag debian/4.3-1
in repository proguard.

commit 09ddf2a29690cedfb7fb87ae9244bf2756745403
Author: Sam Clegg <samo at debian.org>
Date:   Thu Apr 10 10:41:59 2014 +0200

    Imported Upstream version 4.3
---
 README                                             |  37 +-
 bin/proguard.bat                                   |  10 +
 bin/proguard.sh                                    |   9 +
 bin/proguardgui.bat                                |  10 +
 bin/proguardgui.sh                                 |   9 +
 bin/retrace.bat                                    |  10 +
 bin/retrace.sh                                     |   9 +
 build/README                                       |  34 +
 build/build.sh                                     |  80 ++
 build/build.xml                                    | 166 ++++
 build/makefile                                     |  94 ++
 docs/FAQ.html                                      |  28 +-
 docs/GPL_exception.html                            |   4 +-
 docs/acknowledgements.html                         |   9 +-
 docs/alternatives.html                             |  32 +-
 docs/downloads.html                                |  42 +-
 docs/feedback.html                                 |   2 +-
 docs/index.html                                    |   2 +-
 docs/license.html                                  |   4 +-
 docs/main.html                                     |   2 +-
 docs/manual/ant.html                               |  45 +-
 docs/manual/attention.gif                          | Bin 0 -> 896 bytes
 docs/manual/examples.html                          |   6 +-
 docs/manual/gui.html                               |   5 +-
 docs/manual/index.html                             |   2 +-
 docs/manual/introduction.html                      |   6 +-
 docs/manual/limitations.html                       |  12 +-
 docs/manual/refcard.html                           |  25 +-
 docs/manual/retrace/examples.html                  |   2 +-
 docs/manual/retrace/index.html                     |   2 +-
 docs/manual/retrace/introduction.html              |   2 +-
 docs/manual/retrace/usage.html                     |   2 +-
 docs/manual/troubleshooting.html                   | 187 +++-
 docs/manual/usage.html                             | 110 ++-
 docs/manual/wtk.html                               |  10 +-
 docs/quality.html                                  |   8 +-
 docs/results.html                                  |   2 +-
 docs/screenshots.html                              |   2 +-
 docs/testimonials.html                             |  11 +-
 docs/title.html                                    |   2 +-
 examples/annotations/lib/annotations.jar           | Bin 6123 -> 6123 bytes
 examples/ant/proguard.xml                          |  14 +-
 examples/dictionaries/shakespeare.txt              |   0
 examples/dictionaries/windows.txt                  | 209 +++++
 examples/proguard.pro                              |   9 +-
 examples/proguardall.pro                           |  11 +-
 examples/proguardgui.pro                           |   7 +-
 src/proguard/ArgumentWordReader.java               |   2 +-
 src/proguard/ClassPath.java                        |   2 +-
 src/proguard/ClassPathEntry.java                   |   2 +-
 src/proguard/ClassSpecification.java               |   2 +-
 src/proguard/ClassSpecificationVisitorFactory.java |   2 +-
 src/proguard/Configuration.java                    |  17 +-
 src/proguard/ConfigurationConstants.java           |  13 +-
 src/proguard/ConfigurationParser.java              |  91 +-
 src/proguard/ConfigurationWriter.java              |  14 +-
 src/proguard/DataEntryReaderFactory.java           |   2 +-
 src/proguard/DataEntryWriterFactory.java           |   2 +-
 src/proguard/DescriptorKeepChecker.java            |   2 +-
 src/proguard/DuplicateClassPrinter.java            |   2 +-
 src/proguard/FileWordReader.java                   |   2 +-
 src/proguard/FullyQualifiedClassNameChecker.java   |   2 +-
 src/proguard/GPL.java                              |   3 +-
 src/proguard/Initializer.java                      | 135 ++-
 src/proguard/InputReader.java                      |   2 +-
 src/proguard/KeepSpecification.java                |   2 +-
 src/proguard/MANIFEST.MF                           |   2 +
 src/proguard/MemberSpecification.java              |   2 +-
 src/proguard/OutputWriter.java                     |   2 +-
 src/proguard/ParseException.java                   |   2 +-
 src/proguard/ProGuard.java                         |   4 +-
 src/proguard/SubclassedClassFilter.java            |   2 +-
 src/proguard/Targeter.java                         |  16 +-
 src/proguard/UpToDateChecker.java                  |   2 +-
 src/proguard/WordReader.java                       |   2 +-
 src/proguard/ant/ClassPathElement.java             |   2 +-
 src/proguard/ant/ClassSpecificationElement.java    |  13 +-
 src/proguard/ant/ConfigurationElement.java         |   2 +-
 src/proguard/ant/ConfigurationTask.java            |   2 +-
 src/proguard/ant/FilterElement.java                |   2 +-
 src/proguard/ant/KeepAttributeElement.java         |   2 +-
 src/proguard/ant/KeepSpecificationElement.java     |   2 +-
 src/proguard/ant/MemberSpecificationElement.java   |   2 +-
 src/proguard/ant/ProGuardTask.java                 |  20 +-
 src/proguard/classfile/ClassConstants.java         |  18 +-
 src/proguard/classfile/ClassPool.java              |  16 +-
 src/proguard/classfile/Clazz.java                  | 120 +--
 src/proguard/classfile/Field.java                  |  16 +-
 src/proguard/classfile/LibraryClass.java           | 256 ++----
 src/proguard/classfile/LibraryField.java           |  27 +-
 src/proguard/classfile/LibraryMember.java          |  36 +-
 src/proguard/classfile/LibraryMethod.java          |  27 +-
 src/proguard/classfile/Member.java                 |  24 +-
 src/proguard/classfile/Method.java                 |  16 +-
 src/proguard/classfile/ProgramClass.java           | 229 ++---
 src/proguard/classfile/ProgramField.java           |  33 +-
 src/proguard/classfile/ProgramMember.java          |  40 +-
 src/proguard/classfile/ProgramMethod.java          |  33 +-
 src/proguard/classfile/VisitorAccepter.java        |  16 +-
 src/proguard/classfile/attribute/Attribute.java    |  33 +-
 .../classfile/attribute/CodeAttribute.java         |  42 +-
 .../attribute/ConstantValueAttribute.java          |  28 +-
 .../classfile/attribute/DeprecatedAttribute.java   |  25 +-
 .../attribute/EnclosingMethodAttribute.java        |  30 +-
 .../classfile/attribute/ExceptionInfo.java         |  16 +-
 .../classfile/attribute/ExceptionsAttribute.java   |  30 +-
 .../classfile/attribute/InnerClassesAttribute.java |  31 +-
 .../classfile/attribute/InnerClassesInfo.java      |  61 +-
 .../classfile/attribute/LineNumberInfo.java        |  16 +-
 .../attribute/LineNumberTableAttribute.java        |  30 +-
 .../classfile/attribute/LocalVariableInfo.java     |  16 +-
 .../attribute/LocalVariableTableAttribute.java     |  30 +-
 .../classfile/attribute/LocalVariableTypeInfo.java |  16 +-
 .../attribute/LocalVariableTypeTableAttribute.java |  30 +-
 .../classfile/attribute/SignatureAttribute.java    |  28 +-
 .../classfile/attribute/SourceDirAttribute.java    |  28 +-
 .../classfile/attribute/SourceFileAttribute.java   |  28 +-
 .../classfile/attribute/SyntheticAttribute.java    |  25 +-
 .../classfile/attribute/UnknownAttribute.java      |  30 +-
 .../classfile/attribute/annotation/Annotation.java |  37 +-
 .../annotation/AnnotationDefaultAttribute.java     |  28 +-
 .../annotation/AnnotationElementValue.java         |  28 +-
 .../attribute/annotation/AnnotationsAttribute.java |  33 +-
 .../attribute/annotation/ArrayElementValue.java    |  30 +-
 .../attribute/annotation/ClassElementValue.java    |  28 +-
 .../attribute/annotation/ConstantElementValue.java |  32 +-
 .../attribute/annotation/ElementValue.java         |  33 +-
 .../annotation/EnumConstantElementValue.java       |  30 +-
 .../annotation/ParameterAnnotationsAttribute.java  |  35 +-
 .../RuntimeInvisibleAnnotationsAttribute.java      |  29 +-
 ...timeInvisibleParameterAnnotationsAttribute.java |  31 +-
 .../RuntimeVisibleAnnotationsAttribute.java        |  27 +-
 ...untimeVisibleParameterAnnotationsAttribute.java |  31 +-
 .../annotation/visitor/AllAnnotationVisitor.java   |   2 +-
 .../annotation/visitor/AnnotatedClassVisitor.java  |   2 +-
 .../visitor/AnnotationToMemberVisitor.java         |   2 +-
 .../annotation/visitor/AnnotationTypeFilter.java   |   2 +-
 .../annotation/visitor/AnnotationVisitor.java      |   2 +-
 .../annotation/visitor/ElementValueVisitor.java    |   2 +-
 .../attribute/preverification/DoubleType.java      |  16 +-
 .../attribute/preverification/FloatType.java       |  16 +-
 .../attribute/preverification/FullFrame.java       |  18 +-
 .../attribute/preverification/IntegerType.java     |  16 +-
 .../attribute/preverification/LessZeroFrame.java   |  16 +-
 .../attribute/preverification/LongType.java        |  16 +-
 .../attribute/preverification/MoreZeroFrame.java   |  18 +-
 .../attribute/preverification/NullType.java        |  16 +-
 .../attribute/preverification/ObjectType.java      |  16 +-
 .../attribute/preverification/SameOneFrame.java    |  16 +-
 .../attribute/preverification/SameZeroFrame.java   |  16 +-
 .../preverification/StackMapAttribute.java         |  16 +-
 .../attribute/preverification/StackMapFrame.java   |  16 +-
 .../preverification/StackMapTableAttribute.java    |  16 +-
 .../attribute/preverification/TopType.java         |  16 +-
 .../preverification/UninitializedThisType.java     |  16 +-
 .../preverification/UninitializedType.java         |  16 +-
 .../preverification/VerificationType.java          |  16 +-
 .../preverification/VerificationTypeFactory.java   |   2 +-
 .../visitor/StackMapFrameVisitor.java              |   2 +-
 .../visitor/VerificationTypeVisitor.java           |   2 +-
 .../attribute/visitor/AllAttributeVisitor.java     |   2 +-
 .../attribute/visitor/AttributeNameFilter.java     |   2 +-
 .../attribute/visitor/AttributeVisitor.java        |   2 +-
 .../attribute/visitor/ExceptionInfoVisitor.java    |   2 +-
 .../attribute/visitor/InnerClassesInfoVisitor.java |   2 +-
 .../attribute/visitor/LineNumberInfoVisitor.java   |   2 +-
 .../visitor/LocalVariableInfoVisitor.java          |   2 +-
 .../visitor/LocalVariableTypeInfoVisitor.java      |   2 +-
 .../attribute/visitor/MultiAttributeVisitor.java   |   2 +-
 .../attribute/visitor/RequiredAttributeFilter.java |   2 +-
 .../attribute/visitor/StackSizeComputer.java       |  19 +-
 src/proguard/classfile/constant/ClassConstant.java |  16 +-
 src/proguard/classfile/constant/Constant.java      |  16 +-
 .../classfile/constant/DoubleConstant.java         |  16 +-
 .../classfile/constant/FieldrefConstant.java       |  16 +-
 src/proguard/classfile/constant/FloatConstant.java |  16 +-
 .../classfile/constant/IntegerConstant.java        |  16 +-
 .../constant/InterfaceMethodrefConstant.java       |  16 +-
 src/proguard/classfile/constant/LongConstant.java  |  16 +-
 .../classfile/constant/MethodrefConstant.java      |  16 +-
 .../classfile/constant/NameAndTypeConstant.java    |  16 +-
 src/proguard/classfile/constant/RefConstant.java   |  16 +-
 .../classfile/constant/StringConstant.java         |  16 +-
 src/proguard/classfile/constant/Utf8Constant.java  |  16 +-
 .../constant/visitor/AllConstantVisitor.java       |   2 +-
 .../constant/visitor/ConstantVisitor.java          |   2 +-
 .../visitor/ExceptClassConstantFilter.java}        |  46 +-
 src/proguard/classfile/editor/AccessFixer.java     |  48 +-
 src/proguard/classfile/editor/AnnotationAdder.java | 116 +++
 .../editor/AnnotationsAttributeEditor.java         |  67 ++
 src/proguard/classfile/editor/AttributeAdder.java  | 279 ++++--
 src/proguard/classfile/editor/AttributeSorter.java |  16 +-
 .../classfile/editor/AttributesEditor.java         | 309 ++++---
 src/proguard/classfile/editor/ClassEditor.java     | 255 ++++++
 .../classfile/editor/ClassElementSorter.java       |  16 +-
 .../classfile/editor/ClassMemberSorter.java        |  16 +-
 .../classfile/editor/ClassReferenceFixer.java      |  50 +-
 .../classfile/editor/CodeAttributeComposer.java    |  43 +-
 .../classfile/editor/CodeAttributeEditor.java      |   6 +-
 .../editor/CodeAttributeEditorResetter.java        |   2 +-
 .../classfile/editor/ComparableConstant.java       |  36 +-
 src/proguard/classfile/editor/ConstantAdder.java   |  82 +-
 .../classfile/editor/ConstantPoolEditor.java       | 474 +++++-----
 .../classfile/editor/ConstantPoolRemapper.java     |   2 +-
 .../classfile/editor/ConstantPoolSorter.java       | 114 +--
 .../classfile/editor/ElementValueAdder.java        | 218 +++++
 .../classfile/editor/ElementValuesEditor.java      | 238 +++++
 src/proguard/classfile/editor/ExceptionAdder.java  |  26 +-
 .../classfile/editor/ExceptionInfoAdder.java       |  67 ++
 ...sEditor.java => ExceptionsAttributeEditor.java} |  39 +-
 .../classfile/editor/InstructionAdder.java         |  76 ++
 .../classfile/editor/InstructionWriter.java        |  16 +-
 .../{ExceptionAdder.java => InterfaceAdder.java}   |  37 +-
 src/proguard/classfile/editor/InterfaceSorter.java |  48 +-
 .../classfile/editor/InterfacesEditor.java         | 122 +++
 src/proguard/classfile/editor/MemberAdder.java     | 238 +++--
 .../classfile/editor/MemberReferenceFixer.java     |  35 +-
 src/proguard/classfile/editor/MembersEditor.java   |  92 --
 .../classfile/editor/MethodInvocationFixer.java    |   2 +-
 .../NamedAttributeDeleter.java}                    |  29 +-
 .../classfile/editor/StackSizeUpdater.java         |   2 +-
 .../editor/SubclassAdder.java}                     |  26 +-
 .../editor/SubclassToAdder.java}                   |  27 +-
 src/proguard/classfile/editor/VariableEditor.java  |   2 +-
 .../classfile/editor/VariableRemapper.java         |   2 +-
 .../classfile/editor/VariableSizeUpdater.java      |  16 +-
 .../classfile/instruction/BranchInstruction.java   |   2 +-
 .../classfile/instruction/ConstantInstruction.java |   2 +-
 .../classfile/instruction/Instruction.java         |   4 +-
 .../instruction/InstructionConstants.java          |   2 +-
 .../classfile/instruction/InstructionFactory.java  |   2 +-
 .../classfile/instruction/InstructionUtil.java     |   2 +-
 .../instruction/LookUpSwitchInstruction.java       |   2 +-
 .../classfile/instruction/SimpleInstruction.java   |   2 +-
 .../classfile/instruction/SwitchInstruction.java   |   2 +-
 .../instruction/TableSwitchInstruction.java        |   2 +-
 .../classfile/instruction/VariableInstruction.java |   2 +-
 .../instruction/visitor/AllInstructionVisitor.java |   2 +-
 .../instruction/visitor/InstructionCounter.java    |   2 +-
 .../instruction/visitor/InstructionVisitor.java    |   2 +-
 .../visitor/MultiInstructionVisitor.java           |   2 +-
 src/proguard/classfile/io/LibraryClassReader.java  |   8 +-
 src/proguard/classfile/io/ProgramClassReader.java  |  16 +-
 src/proguard/classfile/io/ProgramClassWriter.java  |   2 +-
 src/proguard/classfile/io/RuntimeDataInput.java    |   2 +-
 src/proguard/classfile/io/RuntimeDataOutput.java   |   2 +-
 src/proguard/classfile/util/AccessUtil.java        |   2 +-
 .../classfile/util/ClassReferenceInitializer.java  | 122 ++-
 .../util/ClassSubHierarchyInitializer.java         |   2 +-
 .../util/ClassSuperHierarchyInitializer.java       |  59 +-
 src/proguard/classfile/util/ClassUtil.java         |  10 +-
 .../classfile/util/DescriptorClassEnumeration.java |  21 +-
 .../util/DynamicClassReferenceInitializer.java     |  49 +-
 .../util/DynamicMemberReferenceInitializer.java    |   2 +-
 .../classfile/util/ExternalTypeEnumeration.java    |   2 +-
 .../classfile/util/InstructionSequenceMatcher.java |   2 +-
 .../classfile/util/InternalTypeEnumeration.java    | 180 ++--
 src/proguard/classfile/util/MemberFinder.java      |   2 +-
 src/proguard/classfile/util/MethodLinker.java      |  49 +-
 src/proguard/classfile/util/SimplifiedVisitor.java |   2 +-
 src/proguard/classfile/util/StringSharer.java      |   2 +-
 src/proguard/classfile/util/WarningPrinter.java    |   2 +-
 .../classfile/visitor/AllClassVisitor.java         |   2 +-
 .../classfile/visitor/AllFieldVisitor.java         |   2 +-
 .../classfile/visitor/AllMemberVisitor.java        |   2 +-
 .../classfile/visitor/AllMethodVisitor.java        |   2 +-
 .../classfile/visitor/BottomClassFilter.java       |   2 +-
 .../classfile/visitor/ClassAccessFilter.java       |   2 +-
 src/proguard/classfile/visitor/ClassCleaner.java   |   8 +-
 src/proguard/classfile/visitor/ClassCollector.java |  16 +-
 src/proguard/classfile/visitor/ClassCounter.java   |   2 +-
 .../visitor/ClassForNameClassVisitor.java          |   2 +-
 .../classfile/visitor/ClassHierarchyTraveler.java  |   2 +-
 .../classfile/visitor/ClassMemberVisitor.java      |  88 --
 .../classfile/visitor/ClassNameFilter.java         |  19 +-
 .../classfile/visitor/ClassPoolFiller.java         |   2 +-
 .../classfile/visitor/ClassPoolVisitor.java        |   2 +-
 .../classfile/visitor/ClassPresenceFilter.java     |   2 +-
 src/proguard/classfile/visitor/ClassPrinter.java   |  39 +-
 .../classfile/visitor/ClassVersionFilter.java      |  16 +-
 .../classfile/visitor/ClassVersionSetter.java      |  16 +-
 src/proguard/classfile/visitor/ClassVisitor.java   |   2 +-
 .../visitor/ConcreteClassDownTraveler.java         |   2 +-
 .../classfile/visitor/DotClassClassVisitor.java    |   2 +-
 ...ttomClassFilter.java => ExceptClassFilter.java} |  28 +-
 ...omClassFilter.java => ExceptClassesFilter.java} |  51 +-
 .../classfile/visitor/ExceptionCounter.java        |   2 +-
 .../visitor/ExceptionExcludedOffsetFilter.java     |  16 +-
 .../classfile/visitor/ExceptionOffsetFilter.java   |  16 +-
 .../classfile/visitor/ExceptionRangeFilter.java    |  16 +-
 .../ImplementedClassConstantFilter.java}           |  48 +-
 ...lassFilter.java => ImplementedClassFilter.java} |  32 +-
 .../visitor/ImplementingClassConstantFilter.java   |  70 ++
 .../classfile/visitor/LibraryClassFilter.java      |   2 +-
 .../classfile/visitor/LibraryMemberFilter.java     |   2 +-
 .../classfile/visitor/MemberAccessFilter.java      |   2 +-
 .../classfile/visitor/MemberClassAccessFilter.java |   2 +-
 .../{ClassPoolFiller.java => MemberCollector.java} |  30 +-
 src/proguard/classfile/visitor/MemberCounter.java  |   4 +-
 .../classfile/visitor/MemberDescriptorFilter.java  |  18 +-
 .../classfile/visitor/MemberNameFilter.java        |  18 +-
 .../classfile/visitor/MemberToClassVisitor.java    |   4 +-
 src/proguard/classfile/visitor/MemberVisitor.java  |   2 +-
 .../visitor/MethodImplementationFilter.java        |   2 +-
 .../visitor/MethodImplementationTraveler.java      |  86 +-
 .../classfile/visitor/MultiClassPoolVisitor.java   |   2 +-
 .../classfile/visitor/MultiClassVisitor.java       |   2 +-
 .../classfile/visitor/MultiMemberVisitor.java      |   2 +-
 .../classfile/visitor/NamedClassVisitor.java       |   2 +-
 .../classfile/visitor/NamedFieldVisitor.java       |   4 +-
 .../classfile/visitor/NamedMethodVisitor.java      |   4 +-
 .../classfile/visitor/ProgramClassFilter.java      |   2 +-
 .../classfile/visitor/ProgramMemberFilter.java     |   2 +-
 .../classfile/visitor/ReferencedClassVisitor.java  |   6 +-
 .../classfile/visitor/ReferencedMemberVisitor.java |   2 +-
 .../classfile/visitor/SimilarMemberVisitor.java    | 125 +++
 .../classfile/visitor/SimpleClassPrinter.java      |   2 +-
 ...{BottomClassFilter.java => SubclassFilter.java} |  50 +-
 ...braryClassFilter.java => SubclassTraveler.java} |  22 +-
 .../classfile/visitor/VariableClassVisitor.java    |   2 +-
 .../classfile/visitor/VariableMemberVisitor.java   |   2 +-
 src/proguard/evaluation/BasicBranchUnit.java       |   2 +-
 src/proguard/evaluation/BasicInvocationUnit.java   |  60 +-
 src/proguard/evaluation/BranchUnit.java            |   2 +-
 src/proguard/evaluation/InvocationUnit.java        |   2 +-
 src/proguard/evaluation/MutableValue.java          | 149 ---
 src/proguard/evaluation/Processor.java             |  44 +-
 src/proguard/evaluation/Stack.java                 |   2 +-
 src/proguard/evaluation/TracedStack.java           |   7 +-
 src/proguard/evaluation/TracedVariables.java       |   7 +-
 src/proguard/evaluation/Variables.java             |   2 +-
 src/proguard/evaluation/value/Category1Value.java  |   2 +-
 src/proguard/evaluation/value/Category2Value.java  |   2 +-
 .../value/{TopValue.java => ComparisonValue.java}  |  44 +-
 .../evaluation/value/CompositeDoubleValue.java     |  81 ++
 .../evaluation/value/CompositeFloatValue.java      |  81 ++
 .../evaluation/value/CompositeIntegerValue.java    |  87 ++
 .../evaluation/value/CompositeLongValue.java       |  87 ++
 .../{TopValue.java => ConvertedByteValue.java}     |  39 +-
 ...{TopValue.java => ConvertedCharacterValue.java} |  39 +-
 .../{TopValue.java => ConvertedDoubleValue.java}   |  39 +-
 .../{TopValue.java => ConvertedFloatValue.java}    |  39 +-
 .../{TopValue.java => ConvertedIntegerValue.java}  |  39 +-
 .../{TopValue.java => ConvertedLongValue.java}     |  39 +-
 .../{TopValue.java => ConvertedShortValue.java}    |  39 +-
 src/proguard/evaluation/value/DoubleValue.java     | 263 +++---
 src/proguard/evaluation/value/FloatValue.java      | 258 +++---
 .../{TopValue.java => IdentifiedDoubleValue.java}  |  42 +-
 .../{TopValue.java => IdentifiedFloatValue.java}   |  42 +-
 .../{TopValue.java => IdentifiedIntegerValue.java} |  42 +-
 .../{TopValue.java => IdentifiedLongValue.java}    |  42 +-
 .../evaluation/value/IdentifiedReferenceValue.java |  91 ++
 .../evaluation/value/IdentifiedValueFactory.java   |  75 ++
 .../evaluation/value/InstructionOffsetValue.java   |  16 +-
 src/proguard/evaluation/value/IntegerValue.java    | 735 +++++++++++----
 src/proguard/evaluation/value/LongValue.java       | 314 +++++--
 .../{TopValue.java => NegatedDoubleValue.java}     |  40 +-
 .../{TopValue.java => NegatedFloatValue.java}      |  40 +-
 .../{TopValue.java => NegatedIntegerValue.java}    |  40 +-
 .../value/{TopValue.java => NegatedLongValue.java} |  40 +-
 ...DoubleValue.java => ParticularDoubleValue.java} | 123 ++-
 .../evaluation/value/ParticularFloatValue.java     | 210 +++++
 ...tegerValue.java => ParticularIntegerValue.java} | 225 +++--
 .../evaluation/value/ParticularLongValue.java      | 271 ++++++
 src/proguard/evaluation/value/ReferenceValue.java  |  25 +-
 .../evaluation/value/SpecificDoubleValue.java      |  98 +-
 .../evaluation/value/SpecificFloatValue.java       |  98 +-
 .../evaluation/value/SpecificIntegerValue.java     | 180 ++--
 .../evaluation/value/SpecificLongValue.java        | 130 ++-
 .../evaluation/value/SpecificValueFactory.java     |  38 +-
 src/proguard/evaluation/value/TopValue.java        |  12 +-
 .../evaluation/value/UnknownDoubleValue.java       | 125 +++
 .../evaluation/value/UnknownFloatValue.java        | 125 +++
 .../evaluation/value/UnknownIntegerValue.java      | 216 +++++
 .../evaluation/value/UnknownLongValue.java         | 160 ++++
 src/proguard/evaluation/value/Value.java           |  17 +-
 src/proguard/evaluation/value/ValueFactory.java    |  28 +-
 src/proguard/gui/ClassPathPanel.java               |   8 +-
 src/proguard/gui/ClassSpecificationDialog.java     |  36 +-
 src/proguard/gui/ClassSpecificationsPanel.java     |   2 +-
 src/proguard/gui/ExtensionFileFilter.java          |   2 +-
 src/proguard/gui/FilterDialog.java                 |   2 +-
 src/proguard/gui/GUIResources.java                 |   2 +-
 src/proguard/gui/GUIResources.properties           |  18 +-
 src/proguard/gui/KeepSpecificationsPanel.java      |   2 +-
 src/proguard/gui/ListPanel.java                    |   8 +-
 src/proguard/gui/MANIFEST.MF                       |   3 +
 src/proguard/gui/MemberSpecificationDialog.java    |   2 +-
 src/proguard/gui/MemberSpecificationsPanel.java    |   2 +-
 src/proguard/gui/MessageDialogRunnable.java        |   2 +-
 src/proguard/gui/ProGuardGUI.java                  | 174 ++--
 src/proguard/gui/ProGuardRunnable.java             |   2 +-
 src/proguard/gui/ReTraceRunnable.java              |   2 +-
 src/proguard/gui/SwingUtil.java                    |   2 +-
 src/proguard/gui/TabbedPane.java                   |   2 +-
 src/proguard/gui/TextAreaOutputStream.java         |   2 +-
 src/proguard/gui/boilerplate.pro                   |   4 +-
 src/proguard/gui/default.pro                       |   2 +-
 src/proguard/gui/splash/BufferedSprite.java        |   2 +-
 src/proguard/gui/splash/CircleSprite.java          |   2 +-
 src/proguard/gui/splash/ClipSprite.java            |   2 +-
 src/proguard/gui/splash/ColorSprite.java           |   2 +-
 src/proguard/gui/splash/CompositeSprite.java       |   2 +-
 src/proguard/gui/splash/ConstantColor.java         |   2 +-
 src/proguard/gui/splash/ConstantDouble.java        |   2 +-
 src/proguard/gui/splash/ConstantFont.java          |   2 +-
 src/proguard/gui/splash/ConstantInt.java           |   2 +-
 src/proguard/gui/splash/ConstantString.java        |   2 +-
 src/proguard/gui/splash/ConstantTiming.java        |   2 +-
 src/proguard/gui/splash/FontSprite.java            |   2 +-
 src/proguard/gui/splash/ImageSprite.java           |   2 +-
 src/proguard/gui/splash/LinearColor.java           |   2 +-
 src/proguard/gui/splash/LinearDouble.java          |   2 +-
 src/proguard/gui/splash/LinearInt.java             |   2 +-
 src/proguard/gui/splash/LinearTiming.java          |   2 +-
 src/proguard/gui/splash/OverrideGraphics2D.java    |   2 +-
 src/proguard/gui/splash/RectangleSprite.java       |   2 +-
 src/proguard/gui/splash/SawToothTiming.java        |   2 +-
 src/proguard/gui/splash/ShadowedSprite.java        |   2 +-
 src/proguard/gui/splash/SineTiming.java            |   2 +-
 src/proguard/gui/splash/SmoothTiming.java          |   2 +-
 src/proguard/gui/splash/SplashPanel.java           |   2 +-
 src/proguard/gui/splash/Sprite.java                |   2 +-
 src/proguard/gui/splash/TextSprite.java            |   2 +-
 src/proguard/gui/splash/TimeSwitchSprite.java      |   2 +-
 src/proguard/gui/splash/Timing.java                |   2 +-
 src/proguard/gui/splash/TypeWriterString.java      |   2 +-
 src/proguard/gui/splash/VariableColor.java         |   2 +-
 src/proguard/gui/splash/VariableDouble.java        |   2 +-
 src/proguard/gui/splash/VariableFont.java          |   2 +-
 src/proguard/gui/splash/VariableInt.java           |   2 +-
 src/proguard/gui/splash/VariableSizeFont.java      |   2 +-
 src/proguard/gui/splash/VariableString.java        |   2 +-
 src/proguard/io/CascadingDataEntryWriter.java      |   2 +-
 src/proguard/io/ClassFilter.java                   |   2 +-
 src/proguard/io/ClassReader.java                   |   2 +-
 src/proguard/io/ClassRewriter.java                 |   2 +-
 src/proguard/io/DataEntry.java                     |   2 +-
 src/proguard/io/DataEntryCopier.java               |   2 +-
 src/proguard/io/DataEntryFilter.java               |   2 +-
 src/proguard/io/DataEntryNameFilter.java           |   2 +-
 src/proguard/io/DataEntryParentFilter.java         |   2 +-
 src/proguard/io/DataEntryPump.java                 |   2 +-
 src/proguard/io/DataEntryReader.java               |   2 +-
 src/proguard/io/DataEntryRenamer.java              |   4 +-
 src/proguard/io/DataEntryRewriter.java             |   2 +-
 src/proguard/io/DataEntryWriter.java               |   2 +-
 src/proguard/io/DirectoryPump.java                 |   2 +-
 src/proguard/io/DirectoryWriter.java               |   2 +-
 src/proguard/io/FileDataEntry.java                 |   2 +-
 src/proguard/io/FilteredDataEntryReader.java       |   2 +-
 src/proguard/io/FilteredDataEntryWriter.java       |   2 +-
 src/proguard/io/Finisher.java                      |   2 +-
 src/proguard/io/JarReader.java                     |   2 +-
 src/proguard/io/JarWriter.java                     |   2 +-
 src/proguard/io/ParentDataEntryWriter.java         |   2 +-
 src/proguard/io/RenamedDataEntry.java              |   2 +-
 src/proguard/io/ZipDataEntry.java                  |   2 +-
 src/proguard/obfuscate/AttributeShrinker.java      |   2 +-
 src/proguard/obfuscate/AttributeUsageMarker.java   |   2 +-
 src/proguard/obfuscate/ClassObfuscator.java        |  60 +-
 src/proguard/obfuscate/ClassOpener.java            | 127 ---
 src/proguard/obfuscate/ClassRenamer.java           |  21 +-
 src/proguard/obfuscate/DictionaryNameFactory.java  |  21 +-
 src/proguard/obfuscate/MapCleaner.java             |   2 +-
 src/proguard/obfuscate/MappingKeeper.java          |   2 +-
 src/proguard/obfuscate/MappingPrinter.java         |   2 +-
 src/proguard/obfuscate/MappingProcessor.java       |   2 +-
 src/proguard/obfuscate/MappingReader.java          |   2 +-
 src/proguard/obfuscate/MemberNameCleaner.java      |   2 +-
 src/proguard/obfuscate/MemberNameCollector.java    |   2 +-
 .../obfuscate/MemberNameConflictFixer.java         |   2 +-
 src/proguard/obfuscate/MemberObfuscator.java       |   2 +-
 .../obfuscate/MemberSpecialNameFilter.java         |   2 +-
 src/proguard/obfuscate/MultiMappingProcessor.java  |   2 +-
 src/proguard/obfuscate/NameAndTypeShrinker.java    |   2 +-
 src/proguard/obfuscate/NameAndTypeUsageMarker.java |   2 +-
 src/proguard/obfuscate/NameFactory.java            |   2 +-
 src/proguard/obfuscate/NameFactoryResetter.java    |   2 +-
 src/proguard/obfuscate/NameMarker.java             |  53 +-
 src/proguard/obfuscate/Obfuscator.java             |  51 +-
 src/proguard/obfuscate/SimpleNameFactory.java      |   2 +-
 src/proguard/obfuscate/SourceFileRenamer.java      |  10 +-
 src/proguard/obfuscate/SpecialNameFactory.java     |   2 +-
 src/proguard/obfuscate/Utf8Shrinker.java           |   2 +-
 src/proguard/obfuscate/Utf8UsageMarker.java        |   2 +-
 src/proguard/optimize/ChangedCodePrinter.java      |   2 +-
 src/proguard/optimize/ConstantMemberFilter.java    |  20 +-
 .../optimize/DuplicateInitializerFixer.java        |  13 +-
 .../DuplicateInitializerInvocationFixer.java       |  31 +-
 src/proguard/optimize/KeepMarker.java              |   2 +-
 .../optimize/MemberDescriptorSpecializer.java      |  16 +-
 .../optimize/MethodDescriptorShrinker.java         |  37 +-
 src/proguard/optimize/MethodStaticizer.java        |   2 +-
 .../optimize/OptimizationInfoMemberFilter.java     |  16 +-
 src/proguard/optimize/Optimizer.java               | 307 ++++---
 src/proguard/optimize/ParameterShrinker.java       |  16 +-
 src/proguard/optimize/TailRecursionSimplifier.java | 335 +++++++
 .../optimize/UnusedParameterInvocationUnit.java    | 132 ---
 src/proguard/optimize/WriteOnlyFieldFilter.java    |   2 +-
 .../optimize/evaluation/EvaluationSimplifier.java  | 995 +++++++++++++--------
 .../optimize/evaluation/LivenessAnalyzer.java      |  16 +-
 .../optimize/evaluation/LoadingInvocationUnit.java |  83 +-
 .../optimize/evaluation/PartialEvaluator.java      |  19 +-
 .../optimize/evaluation/StoringInvocationUnit.java |  25 +-
 .../optimize/evaluation/TracedBranchUnit.java      |   2 +-
 .../optimize/evaluation/VariableOptimizer.java     |  16 +-
 src/proguard/optimize/info/AccessMethodMarker.java |  16 +-
 .../optimize/info/BackwardBranchMarker.java        |   2 +-
 .../optimize/info/CatchExceptionMarker.java        |  16 +-
 .../optimize/info/ClassOptimizationInfo.java       |  63 +-
 .../info/ClassOptimizationInfoSetter.java}         |  36 +-
 .../info/DotClassFilter.java}                      |  19 +-
 .../info/DotClassMarker.java}                      |  79 +-
 .../optimize/info/ExceptionInstructionChecker.java |  99 +-
 .../optimize/info/FieldOptimizationInfo.java       |  16 +-
 .../info/InstanceofClassFilter.java}               |  19 +-
 .../info/InstanceofClassMarker.java}               |  80 +-
 .../info/InstantiationClassFilter.java}            |  18 +-
 .../info/InstantiationClassMarker.java}            |  80 +-
 .../info/MemberOptimizationInfoSetter.java         |   2 +-
 .../optimize/info/MethodInvocationMarker.java      |  16 +-
 .../optimize/info/MethodOptimizationInfo.java      |   2 +-
 .../optimize/info/NoSideEffectMethodMarker.java    |   2 +-
 .../optimize/info/NonPrivateMemberMarker.java      |   2 +-
 ...PackageVisibleMemberContainingClassMarker.java} |  38 +-
 .../PackageVisibleMemberInvokingClassMarker.java   |  81 ++
 .../optimize/info/ParameterUsageMarker.java        |  30 +-
 .../optimize/info/ReadWriteFieldMarker.java        |   2 +-
 .../info/SideEffectInstructionChecker.java         |  16 +-
 .../optimize/info/SideEffectMethodMarker.java      |   2 +-
 .../optimize/info/SingleImplementationMarker.java  | 179 ----
 .../optimize/info/SuperInvocationMarker.java       |  16 +-
 .../optimize/info/VariableUsageMarker.java         |   2 +-
 .../optimize/peephole/BranchTargetFinder.java      |  11 +-
 src/proguard/optimize/peephole/ClassFinalizer.java |   2 +-
 src/proguard/optimize/peephole/ClassMerger.java    | 541 +++++++++++
 .../optimize/peephole/GotoCommonCodeReplacer.java  |   2 +-
 .../optimize/peephole/GotoGotoReplacer.java        |   2 +-
 .../optimize/peephole/GotoReturnReplacer.java      |   2 +-
 .../optimize/peephole/HorizontalClassMerger.java   |  90 ++
 .../peephole/InstructionSequenceConstants.java     | 268 +++++-
 .../peephole/InstructionSequenceReplacer.java      |   2 +-
 .../peephole/InstructionSequencesReplacer.java     |   2 +-
 .../optimize/peephole/LoadStoreRemover.java        |   2 +-
 .../optimize/peephole/MemberPrivatizer.java        |   2 +-
 src/proguard/optimize/peephole/MethodInliner.java  |  81 +-
 src/proguard/optimize/peephole/NopRemover.java     |   2 +-
 .../optimize/peephole/PeepholeOptimizer.java       |   2 +-
 src/proguard/optimize/peephole/PushPopRemover.java |   2 +-
 .../optimize/peephole/ReachableCodeMarker.java     |   2 +-
 .../RetargetedInnerClassAttributeRemover.java      | 140 +++
 .../peephole/SingleImplementationFixer.java        | 169 ----
 .../peephole/SingleImplementationInliner.java      | 307 -------
 .../optimize/peephole/StoreLoadReplacer.java       |   2 +-
 .../optimize/peephole/TargetClassChanger.java      | 439 +++++++++
 .../optimize/peephole/UnreachableCodeRemover.java  |   2 +-
 .../peephole/UnreachableExceptionRemover.java      |   2 +-
 .../optimize/peephole/VariableShrinker.java        |  16 +-
 .../optimize/peephole/VerticalClassMerger.java     |  88 ++
 src/proguard/preverify/CodePreverifier.java        |  66 +-
 src/proguard/preverify/CodeSubroutineInliner.java  |  16 +-
 src/proguard/preverify/Preverifier.java            |   2 +-
 src/proguard/preverify/SubroutineInliner.java      |  16 +-
 src/proguard/retrace/MANIFEST.MF                   |   3 +
 src/proguard/retrace/ReTrace.java                  |   2 +-
 src/proguard/retrace/StackTrace.java               |   2 +-
 src/proguard/retrace/StackTraceItem.java           |   2 +-
 src/proguard/shrink/AnnotationUsageMarker.java     |  16 +-
 src/proguard/shrink/ClassShrinker.java             |  77 +-
 src/proguard/shrink/InnerUsageMarker.java          |  33 +-
 src/proguard/shrink/InterfaceUsageMarker.java      |  58 +-
 src/proguard/shrink/ShortestUsageMark.java         |  28 +-
 src/proguard/shrink/ShortestUsageMarker.java       |  28 +-
 src/proguard/shrink/ShortestUsagePrinter.java      |   4 +-
 src/proguard/shrink/Shrinker.java                  |   3 +-
 src/proguard/shrink/UsageMarker.java               | 139 +--
 src/proguard/shrink/UsagePrinter.java              |   2 +-
 src/proguard/shrink/UsedClassFilter.java           |   2 +-
 src/proguard/shrink/UsedMemberFilter.java          |  16 +-
 src/proguard/util/AndMatcher.java                  |   2 +-
 src/proguard/util/ClassNameParser.java             |   2 +-
 src/proguard/util/EmptyStringMatcher.java          |   2 +-
 src/proguard/util/ExtensionMatcher.java            |   2 +-
 src/proguard/util/FileNameParser.java              |   2 +-
 src/proguard/util/FixedStringMatcher.java          |   7 +-
 src/proguard/util/ListMatcher.java                 |   2 +-
 src/proguard/util/ListParser.java                  |   2 +-
 src/proguard/util/ListUtil.java                    |   2 +-
 src/proguard/util/NameParser.java                  |   2 +-
 src/proguard/util/NotMatcher.java                  |   2 +-
 src/proguard/util/OrMatcher.java                   |   2 +-
 src/proguard/util/SettableMatcher.java             |   4 +-
 src/proguard/util/StringMatcher.java               |   2 +-
 src/proguard/util/StringParser.java                |   2 +-
 src/proguard/util/VariableStringMatcher.java       |   2 +-
 src/proguard/wtk/ProGuardObfuscator.java           |   2 +-
 src/proguard/wtk/default.pro                       |   1 +
 598 files changed, 13678 insertions(+), 6916 deletions(-)

diff --git a/README b/README
index d08a410..6946bd0 100644
--- a/README
+++ b/README
@@ -1,12 +1,14 @@
-ProGuard, Java class file shrinker, optimizer, and obfuscator
-=============================================================
+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
+- build    : various alternative build scripts
 
 
 The best place to start is docs/index.html
@@ -15,40 +17,17 @@ The best place to start is docs/index.html
 Example
 =======
 
-If you want to give ProGuard a spin right away, try processing the jar itself:
+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!
-
-
-Development
-===========
-
-If you're interested in changing and extending ProGuard, you can start by
-compiling the source code yourself:
-
-    mkdir classes
-    javac -sourcepath src -d classes src/proguard/ProGuard.java
-    javac -sourcepath src -d classes src/proguard/retrace/ReTrace.java
-    javac -sourcepath src -d classes src/proguard/gui/ProGuardGUI.java
-
-If you want to compile the ProGuard Ant task as well:
-
-    javac -sourcepath src -d classes -classpath lib/ant.jar \
-        src/proguard/ant/ProGuardTask.java
-
-If you want to compile the JME WTK obfuscator plug-in:
-
-    javac -sourcepath src -d classes -classpath wtklib/kenv.zip \
-        src/proguard/wtk/ProGuardObfuscator.java
-
-Note that you'll have to install Ant and the J2ME WTK yourself.
+smaller.
 
 Enjoy!
 
 http://proguard.sourceforge.net/
 
-Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
diff --git a/bin/proguard.bat b/bin/proguard.bat
new file mode 100644
index 0000000..7989253
--- /dev/null
+++ b/bin/proguard.bat
@@ -0,0 +1,10 @@
+ at ECHO OFF
+
+REM Start-up script for ProGuard -- free class file shrinker, optimizer,
+REM obfuscator, and preverifier for Java bytecode.
+
+IF EXIST "%PROGUARD_HOME%" GOTO home
+SET PROGUARD_HOME=..
+:home
+
+java -jar "%PROGUARD_HOME%"\lib\proguard.jar %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/bin/proguard.sh b/bin/proguard.sh
new file mode 100755
index 0000000..228d044
--- /dev/null
+++ b/bin/proguard.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# Start-up script for ProGuard -- free class file shrinker, optimizer,
+# obfuscator, and preverifier for Java bytecode.
+
+PROGUARD_HOME=`dirname "$0"`
+PROGUARD_HOME=`dirname "$PROGUARD_HOME"`
+
+java -jar $PROGUARD_HOME/lib/proguard.jar "$@"
diff --git a/bin/proguardgui.bat b/bin/proguardgui.bat
new file mode 100644
index 0000000..073d98a
--- /dev/null
+++ b/bin/proguardgui.bat
@@ -0,0 +1,10 @@
+ at ECHO OFF
+
+REM Start-up script for the GUI of ProGuard -- free class file shrinker,
+REM optimizer, obfuscator, and preverifier for Java bytecode.
+
+IF EXIST "%PROGUARD_HOME%" GOTO home
+SET PROGUARD_HOME=..
+:home
+
+java -jar "%PROGUARD_HOME%"\lib\proguardgui.jar %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/bin/proguardgui.sh b/bin/proguardgui.sh
new file mode 100755
index 0000000..5a25d7b
--- /dev/null
+++ b/bin/proguardgui.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# Start-up script for the GUI of ProGuard -- free class file shrinker,
+# optimizer, obfuscator, and preverifier for Java bytecode.
+
+PROGUARD_HOME=`dirname "$0"`
+PROGUARD_HOME=`dirname "$PROGUARD_HOME"`
+
+java -jar $PROGUARD_HOME/lib/proguardgui.jar "$@"
diff --git a/bin/retrace.bat b/bin/retrace.bat
new file mode 100644
index 0000000..70603d3
--- /dev/null
+++ b/bin/retrace.bat
@@ -0,0 +1,10 @@
+ at ECHO OFF
+
+REM Start-up script for Retrace -- companion tool for ProGuard, free class file
+REM shrinker, optimizer, obfuscator, and preverifier for Java bytecode.
+
+IF EXIST "%PROGUARD_HOME%" GOTO home
+SET PROGUARD_HOME=..
+:home
+
+java -jar "%PROGUARD_HOME%"\lib\retrace.jar %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/bin/retrace.sh b/bin/retrace.sh
new file mode 100755
index 0000000..5db744e
--- /dev/null
+++ b/bin/retrace.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# Start-up script for Retrace -- companion tool for ProGuard, free class file
+# shrinker, optimizer, obfuscator, and preverifier for Java bytecode.
+
+PROGUARD_HOME=`dirname "$0"`
+PROGUARD_HOME=`dirname "$PROGUARD_HOME"`
+
+java -jar $PROGUARD_HOME/lib/retrace.jar "$@"
diff --git a/build/README b/build/README
new file mode 100644
index 0000000..fa5f5a4
--- /dev/null
+++ b/build/README
@@ -0,0 +1,34 @@
+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.xml : an Ant build file for all platforms
+
+- 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 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
+
+Note that you'll have to install Ant and the JME WTK yourself.
+
+Enjoy!
+
+http://proguard.sourceforge.net/
+
+Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
diff --git a/build/build.sh b/build/build.sh
new file mode 100755
index 0000000..b829aa1
--- /dev/null
+++ b/build/build.sh
@@ -0,0 +1,80 @@
+#!/bin/bash
+#
+# GNU/Linux build script for ProGuard.
+
+ANT_HOME=${ANT_HOME:-/usr/local/java/ant}
+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
+WTK_PLUGIN=proguard/wtk/ProGuardObfuscator
+
+ANT_JAR=$ANT_HOME/lib/ant.jar
+WTK_JAR=$WTK_HOME/wtklib/kenv.jar
+
+PROGUARD_JAR=$LIB/proguard.jar
+PROGUARD_GUI_JAR=$LIB/proguardgui.jar
+RETRACE_JAR=$LIB/retrace.jar
+
+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 \*.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)
+}
+
+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 "$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/build/build.xml b/build/build.xml
new file mode 100644
index 0000000..3b5dd71
--- /dev/null
+++ b/build/build.xml
@@ -0,0 +1,166 @@
+<!-- Ant build script for ProGuard. -->
+
+<project name    = "proguard"
+         default = "all"
+         basedir = "..">
+
+  <property file = "build/build.properties"/>
+  <property name = "src"     value = "src"/>
+  <property name = "classes" value = "classes"/>
+  <property name = "lib"     value = "lib"/>
+
+  <property name = "ant.jar" value = "${ant.home}/lib/ant.jar"/>
+  <property name = "wtk.jar" value = "${wtk.home}/wtklib/kenv.jar"/>
+
+  <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"
+           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/*.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"
+           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/*.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"
+           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/*.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">
+    <fail message="Please set the value of the property ant.home in the file build/build.properties, if you want to build the optional ProGuard Ant task.">
+      <condition>
+        <not>
+          <available file="${ant.jar}"/>
+        </not>
+      </condition>
+    </fail>
+
+    <javac nowarn      = "true"
+           deprecation = "false"
+           classpath   = "${ant.jar}"
+           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/*.gif"/>
+        <include name = "proguard/ant/*.pro"/>
+      </fileset>
+    </copy>
+
+    <jar jarfile  = "${lib}/proguard.jar"
+         update   = "true"
+         basedir  = "${classes}"
+         includes = "proguard/ant/**"/>
+  </target>
+
+  <target name = "wtkplugin" depends = "proguard">
+    <fail message="Please set the value of the property wtk.home in the file build/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"
+           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/*.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/build/makefile b/build/makefile
new file mode 100644
index 0000000..bb4af4f
--- /dev/null
+++ b/build/makefile
@@ -0,0 +1,94 @@
+# GNU/Linux makefile for ProGuard.
+
+ANT_HOME = /usr/local/java/ant
+WTK_HOME = /usr/local/java/wtk
+
+PROGUARD_HOME := $(subst ./..,..,$(subst /build/..,/,$(dir $(MAKEFILE_LIST))..))
+SRC     = $(PROGUARD_HOME)/src
+CLASSES = $(PROGUARD_HOME)/classes
+LIB     = $(PROGUARD_HOME)/lib
+
+ANT_JAR = $(ANT_HOME)/lib/ant.jar
+WTK_JAR = $(WTK_HOME)/wtklib/kenv.zip
+
+CLASSPATH = $(ANT_JAR):$(WTK_JAR)
+
+PROGUARD     = proguard/ProGuard
+PROGUARD_GUI = proguard/gui/ProGuardGUI
+RETRACE      = proguard/retrace/ReTrace
+ANT_TASK     = proguard/ant/ProGuardTask
+WTK_PLUGIN   = proguard/wtk/ProGuardObfuscator
+
+TARGETS = $(PROGUARD) $(PROGUARD_GUI) $(RETRACE) $(ANT_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 wtkplugin
+
+proguard: $(PROGUARD)
+	$(createjar)
+
+proguardgui: proguard
+proguardgui: $(PROGUARD_GUI)
+	$(createjar)
+
+retrace: $(RETRACE)
+	$(createjar)
+
+anttask: $(ANT_JAR)
+anttask: $(PROGUARD)
+anttask: $(ANT_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 \*.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)/%.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."
+	find $@
+
+.PHONY: all basic options proguard proguardgui retrace anttask wtkplugin clean $(TARGETS) $(OPTIONAL_TARGETS)
diff --git a/docs/FAQ.html b/docs/FAQ.html
index ef1c145..04897dc 100644
--- a/docs/FAQ.html
+++ b/docs/FAQ.html
@@ -23,6 +23,7 @@
 <li><a href="#jdk1.4">Does <b>ProGuard</b> work with Java 2? Java 5? Java
     6?</a>
 <li><a href="#jme">Does <b>ProGuard</b> work with Java Micro Edition?</a>
+<li><a href="#android">Does <b>ProGuard</b> work for Google Android code?</a>
 <li><a href="#blackberry">Does <b>ProGuard</b> work for Blackberry code?</a>
 <li><a href="#ant">Does <b>ProGuard</b> have support for Ant?</a>
 <li><a href="#gui">Does <b>ProGuard</b> come with a GUI?</a>
@@ -82,7 +83,8 @@ class files at Java 6.
 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, and liveness analysis, <b>ProGuard</b> can:
+analysis, partial evaluation, static single assignment, global value numbering,
+and liveness analysis, <b>ProGuard</b> can:
 
 <ul>
 <li>Evaluate constant expressions.
@@ -95,6 +97,8 @@ analysis, partial evaluation, and liveness analysis, <b>ProGuard</b> can:
 <li>Remove write-only fields and unused method parameters.
 <li>Inline constant fields, method parameters, and return values.
 <li>Inline methods that are short or only called once.
+<li>Simplify tail recursion calls.
+<li>Merge classes and interfaces.
 <li>Make methods private, static, and final when possible.
 <li>Make classes static and final when possible.
 <li>Replace interfaces that have single implementations.
@@ -140,8 +144,16 @@ preverifier.
 <b>ProGuard</b> also comes with an obfuscator plug-in for the JME Wireless
 Toolkit.
 
+<a name="android"> </a>
+<h3>Does <b>ProGuard</b> work for Google Android code?</h3>
+
+Yes. Google's <code>dx</code> compiler converts ordinary jar files into files
+that run on Android devices. By preprocessing the original jar files,
+<b>ProGuard</b> can significantly reduce the file sizes and boost the run-time
+performance of the code.
+
 <a name="blackberry"> </a>
-<h3>Does <b>ProGuard</b> work with Blackberry code?</h3>
+<h3>Does <b>ProGuard</b> work for Blackberry code?</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
@@ -170,14 +182,14 @@ loading, editing, executing, and saving ProGuard configurations.
 <a name="forname"> </a>
 <h3>Does <b>ProGuard</b> handle <code>Class.forName</code> calls?</h3>
 
-Yes. <b>ProGuard</b> automatically handles
-<code>Class.forName("SomeClass")</code> and <code>SomeClass.class</code>
-constructs. The referenced classes are preserved in the shrinking phase, and
-the string arguments are properly replaced in the obfuscation phase.
+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 constructs like
+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 user can adapt his configuration
@@ -235,7 +247,7 @@ Manual</a> for more details.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/GPL_exception.html b/docs/GPL_exception.html
index ab26e86..0955cf8 100644
--- a/docs/GPL_exception.html
+++ b/docs/GPL_exception.html
@@ -7,7 +7,7 @@
 <H1>Special Exception to the GNU General Public License</H1>
 
 <P>
-Copyright © 2002-2007 Eric Lafortune
+Copyright © 2002-2008 Eric Lafortune
 </P>
 
 <P>
@@ -35,7 +35,7 @@ the code of this program with the following stand-alone applications:
 <ul>
 <li>Apache Ant,
 <li>Apache Maven,
-<li>the Eclipse Java IDE,
+<li>the EclipseME JME IDE,
 <li>the Sun NetBeans Java IDE,
 <li>the Sun JME Wireless Toolkit, and
 <li>the Javaground Tools,
diff --git a/docs/acknowledgements.html b/docs/acknowledgements.html
index 0d266fb..5713ae1 100644
--- a/docs/acknowledgements.html
+++ b/docs/acknowledgements.html
@@ -32,13 +32,12 @@ Sherington, David Sitsky, James Manning, Ptolemy Oberin, Frank-Michael Moser,
 QZ Shines, Thomas Singer, Michele Puccini, Roman Bednarek, Natalia Pujol,
 Daniel Sjöblom, Jan Filipsky, Charles Smith, Gerrit Telkamp, Noel
 Grandin, Torbjörn Söderstedt, Clemens Eisserer, Clark Bassett,
-Eduard Welch, Dawid Weiss, Andrew Wilson,
+Eduard Welch, Dawid Weiss, Andrew Wilson, Sean Owen, Niels Gron,
 and many others. Thanks! Your feedback has been invaluable.
 <p>
 
-I am developing ProGuard in my spare time, in part on equipment that my
-employer <a href="http://www.luciad.com/" target="other">Luciad</a> is kindly
-allowing me to use.
+I am developing ProGuard in my spare time, which is possible thanks to my
+day-time job at <a href="http://www.luciad.com/" target="other">Luciad</a>.
 <p>
 
 <a href="http://sourceforge.net/projects/proguard/"
@@ -60,7 +59,7 @@ href="http://www.javadocking.com/" target="other">Java Docking Library</a>.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 
diff --git a/docs/alternatives.html b/docs/alternatives.html
index 20d5564..7a09b34 100644
--- a/docs/alternatives.html
+++ b/docs/alternatives.html
@@ -134,6 +134,36 @@ below is incorrect.
 </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/OptionalTypes/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.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="https://dcd.dev.java.net/">Emeric Vernat</a></td>
+<td><a target="other" href="https://dcd.dev.java.net/">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>
@@ -609,7 +639,7 @@ All trademarks are property of their respective holders.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 
diff --git a/docs/downloads.html b/docs/downloads.html
index b607d43..dfaee8d 100644
--- a/docs/downloads.html
+++ b/docs/downloads.html
@@ -11,8 +11,9 @@
 
 <h2>Downloads</h2>
 
-<b>ProGuard</b> is distributed under the GNU General Public License.
-Please consult the <a href="license.html">license page</a> for more details.
+<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. It requires a Java 2 runtime environment.
 <p>
@@ -42,6 +43,32 @@ interest too, because they typically contain any less urgent bug fixes
 collected since the previous release.
 <p>
 
+<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 -keepclassmembers 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.
@@ -118,7 +145,7 @@ collected since the previous release.
 <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 over 250 new peephole optimizations.
+<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.
@@ -432,12 +459,7 @@ Upgrade considerations:
 <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, like:
-    <pre>
-    class A     { m() {...} }
-    interface I { m();      }
-    class B extends A implements I
-    </pre>
+<li>Fixed processing of retrofitted interfaces.
 <li>Added handling of missing/invalid manifest file in input jar.
 <li>Updated documentation and examples.
 </ul>
@@ -450,7 +472,7 @@ Upgrade considerations:
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 
diff --git a/docs/feedback.html b/docs/feedback.html
index 6e10a3f..60bc4a9 100644
--- a/docs/feedback.html
+++ b/docs/feedback.html
@@ -98,7 +98,7 @@ projects.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 
diff --git a/docs/index.html b/docs/index.html
index ce67e21..8787906 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -64,7 +64,7 @@ You can go straight to the <a href="main.html">main page</a>.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/license.html b/docs/license.html
index d01ca05..b393294 100644
--- a/docs/license.html
+++ b/docs/license.html
@@ -29,7 +29,7 @@ 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: Apache Ant, Apache Maven, the Eclipse Java IDE, the Sun NetBeans
+applications: Apache Ant, Apache Maven, the EclipseME JME IDE, the Sun NetBeans
 Java IDE, the Sun JME Wireless Toolkit, and the Javaground Tools.
 
 <p>
@@ -39,7 +39,7 @@ version of the code.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/main.html b/docs/main.html
index 14b1d4c..2e4e117 100644
--- a/docs/main.html
+++ b/docs/main.html
@@ -85,7 +85,7 @@ The following sections provide more detailed information:
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/ant.html b/docs/manual/ant.html
index b9c8cc6..6088991 100644
--- a/docs/manual/ant.html
+++ b/docs/manual/ant.html
@@ -36,10 +36,11 @@ depending on practical circumstances and personal preference.
 
 <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"><code>configuration</code></a> attribute of your
+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>
 
@@ -116,10 +117,12 @@ elements:
 
 <dl>
 
-<dt><a name="configuration"><code><b>configuration</b></code></a>
+<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.</dd>
+    file. Note: for reading XML-style configurations, use the <a
+    href="#configuration_element"><code>configuration</code></a>
+    <i>element</i>.</dd>
 
 <dt><a href="usage.html#dontskipnonpubliclibraryclasses"><code><b>skipnonpubliclibraryclasses</b></code></a>
     = "<i>boolean</i>"
@@ -174,6 +177,11 @@ elements:
 <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>
@@ -193,7 +201,18 @@ elements:
 <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 method names.</dd>
+<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>"
@@ -248,7 +267,8 @@ elements:
 <dt><a href="usage.html#dontnote"><code><b>note</b></code></a>
     = "<i>boolean</i>"
    (default = true)</dt>
-<dd>Print notes about class casts of variable dynamically created objects.</dd>
+<dd>Print notes about potential mistakes or omissions in the
+    configuration.</dd>
 
 <dt><a href="usage.html#dontwarn"><code><b>warn</b></code></a>
     = "<i>boolean</i>"
@@ -372,13 +392,16 @@ elements:
 <dd>Update the contents of the specified resource files, based on the
     obfuscated names of the class files.</dd>
 
-<dt><code><b><configuration refid = </b></code>"<i>ref_id</i>"
+<dt><a name="configuration_element"><code><b><configuration refid = </b></code></a>"<i>ref_id</i>"
     <code><b>/></b></code></dt>
 <dd>Includes the configuration specified in the
     <code><proguardconfiguration></code> task (or
     <code><proguard></code> task) with the attribute <code>id</code> =
     "<i>ref_id</i>". Note that only the nested elements of this configuration
-    are considered, not the attributes.</dd>
+    are considered, not the attributes. Also note: for reading ProGuard-style
+    configuration files, use the <a
+    href="#configuration_attribute"><code>configuration</code></a>
+    <i>attribute</i>.</dd>
 
 </dl>
 
@@ -537,7 +560,7 @@ attributes:
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/attention.gif b/docs/manual/attention.gif
new file mode 100644
index 0000000..1a0c712
Binary files /dev/null and b/docs/manual/attention.gif differ
diff --git a/docs/manual/examples.html b/docs/manual/examples.html
index 9422a82..33a8ecc 100644
--- a/docs/manual/examples.html
+++ b/docs/manual/examples.html
@@ -317,7 +317,7 @@ serialization code:
     native <methods>;
 }
 
--keepclassmembers class * extends java.lang.Enum {
+-keepclassmembers enum * {
     public static **[] values();
     public static ** valueOf(java.lang.String);
 }
@@ -416,7 +416,7 @@ 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 class * extends java.lang.Enum {
+-keepclassmembers enum * {
     public static **[] values();
     public static ** valueOf(java.lang.String);
 }
@@ -1143,7 +1143,7 @@ illustrate some of the possibilities.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/gui.html b/docs/manual/gui.html
index 4c2585c..033fcd8 100644
--- a/docs/manual/gui.html
+++ b/docs/manual/gui.html
@@ -340,6 +340,8 @@ Corresponding configuration options:
 <li>-<a href="usage.html#printmapping">printmapping</a>
 <li>-<a href="usage.html#applymapping">applymapping</a>
 <li>-<a href="usage.html#obfuscationdictionary">obfuscationdictionary</a>
+<li>-<a href="usage.html#classobfuscationdictionary">classobfuscationdictionary</a>
+<li>-<a href="usage.html#packageobfuscationdictionary">packageobfuscationdictionary</a>
 <li>-<a href="usage.html#overloadaggressively">overloadaggressively</a>
 <li>-<a href="usage.html#useuniqueclassmembernames">useuniqueclassmembernames</a>
 <li>-<a href="usage.html#dontusemixedcaseclassnames">dontusemixedcaseclassnames</a>
@@ -374,6 +376,7 @@ Corresponding configuration options:
 <li>-<a href="usage.html#dontoptimize">dontoptimize</a>
 <li>-<a href="usage.html#optimizationpasses">optimizationpasses</a>
 <li>-<a href="usage.html#allowaccessmodification">allowaccessmodification</a>
+<li>-<a href="usage.html#mergeinterfacesaggressively">mergeinterfacesaggressively</a>
 <li>-<a href="usage.html#assumenosideeffects">assumenosideeffects</a>
 <li><a href="usage.html#classspecification"><i>class_specification</i></a>
 </ul>
@@ -460,7 +463,7 @@ There are two buttons at the bottom:
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/index.html b/docs/manual/index.html
index ce88ea0..65db3c8 100644
--- a/docs/manual/index.html
+++ b/docs/manual/index.html
@@ -32,7 +32,7 @@
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/introduction.html b/docs/manual/introduction.html
index 4fd2bc6..5035057 100644
--- a/docs/manual/introduction.html
+++ b/docs/manual/introduction.html
@@ -78,8 +78,8 @@ The library jars themselves always remain unchanged. You should still put them
 in the class path of your final application.
 <p>
 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 entry points to your
-code. These entry points are typically classes with main methods, applets,
+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, etc.
 <ul>
 <li>In the <b>shrinking step</b>, ProGuard starts from these seeds and
@@ -149,7 +149,7 @@ about the internals of the code.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/limitations.html b/docs/manual/limitations.html
index 3318ea6..68c27da 100644
--- a/docs/manual/limitations.html
+++ b/docs/manual/limitations.html
@@ -29,11 +29,11 @@ which are easily avoided or resolved:
     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 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.
+    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.
     <p>
 
 <li>If an input jar and a library jar contain classes in the <b>same
@@ -57,7 +57,7 @@ which are easily avoided or resolved:
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/refcard.html b/docs/manual/refcard.html
index a983f18..9ef9d78 100644
--- a/docs/manual/refcard.html
+++ b/docs/manual/refcard.html
@@ -179,6 +179,11 @@
 </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>
@@ -199,7 +204,19 @@
 <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 method names.</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>
@@ -282,8 +299,8 @@
 
 <tr>
 <td valign="top"><a href="usage.html#dontnote"><code><b>-dontnote</b></code></a></td>
-<td>Don't print notes about class casts of variable dynamically created
-    objects.</td>
+<td>Don't print notes about potential mistakes or omissions in the
+    configuration.</td>
 </tr>
 
 <tr>
@@ -413,7 +430,7 @@ Notes:
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/retrace/examples.html b/docs/manual/retrace/examples.html
index 16a2631..7829efb 100644
--- a/docs/manual/retrace/examples.html
+++ b/docs/manual/retrace/examples.html
@@ -328,7 +328,7 @@ Exception in thread "main" java.lang.Error: Random exception
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/retrace/index.html b/docs/manual/retrace/index.html
index 29d6841..d87163c 100644
--- a/docs/manual/retrace/index.html
+++ b/docs/manual/retrace/index.html
@@ -18,7 +18,7 @@
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/retrace/introduction.html b/docs/manual/retrace/introduction.html
index b154159..8be230f 100644
--- a/docs/manual/retrace/introduction.html
+++ b/docs/manual/retrace/introduction.html
@@ -60,7 +60,7 @@ original class names and class member names to their obfuscated names.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/retrace/usage.html b/docs/manual/retrace/usage.html
index 8741e9d..5355fff 100644
--- a/docs/manual/retrace/usage.html
+++ b/docs/manual/retrace/usage.html
@@ -74,7 +74,7 @@ will be left unchanged.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/troubleshooting.html b/docs/manual/troubleshooting.html
index 8669e37..68ce0f5 100644
--- a/docs/manual/troubleshooting.html
+++ b/docs/manual/troubleshooting.html
@@ -12,21 +12,79 @@
 
 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="#descriptorclass">Note: the configuration keeps the entry point '...', but not the descriptor class '...'</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="#unresolvedclassmember">Warning: can't find referenced field/method</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="#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="#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="#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="#processing">Problems while processing</a>
-<li><a href="#afterprocessing">Unexpected observations after processing</a>
-<li><a href="#preverifying">Problems while preverifying for Java Micro
-    Edition</a>
-<li><a href="#runtime">Problems at run-time</a>
+<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="#nosuchmethodexception">NoSuchMethodException</a></li>
+<li><a href="#missingresourceexception">MissingResourceException or NullPointerException</a></li>
+<li><a href="#invalidjarfile">Invalid or corrupt jarfile</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="#compilererror">CompilerError: duplicate addition</a></li>
+<li><a href="#classformaterror">ClassFormatError: repetitive field name/signature</a></li>
+<li><a href="#nosuchmethoderror">NoSuchMethodError or AbstractMethodError</a></li>
+<li><a href="#verifyerror">VerifyError</a></li>
 </ul>
 
+
 <a name="processing"> </a>
 <h2>Problems while processing</h2>
 
 ProGuard may print out some notes and non-fatal warnings:
 
 <dl>
-<dt><a name="dynamicalclass"><b>Note: ... calls '(...)Class.forName(variable).newInstance()'</b></a></dt>
+<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 check if you want to add the jar that
+    contains this class.</dd>
+
+<dt><a name="dynamicalclasscast"><b>Note: ... calls '(...)Class.forName(variable).newInstance()'</b></a></dt>
 
 <dd>ProGuard lists all class casts of dynamically created class instances,
     like "<code>(MyClass)Class.forName(variable).newInstance()</code>".
@@ -42,8 +100,22 @@ ProGuard may print out some notes and non-fatal warnings:
     "<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>". You can switch off these notes by specifying the
-    <a href="usage.html#dontnote"><code>-dontnote</code></a> option.</dd>
+    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="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 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>
 
@@ -126,6 +198,17 @@ some more serious warnings:
     removing all class files, recompiling them, zipping them up, and running
     ProGuard again.</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 and library code, and try again.</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
@@ -186,7 +269,7 @@ some more serious warnings:
 <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 character, on all
+    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>
@@ -222,6 +305,15 @@ Should ProGuard crash while processing your application:
     #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
@@ -289,9 +381,7 @@ 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>
+<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
@@ -355,8 +445,7 @@ might be several reasons:
     href="usage.html#keep"><code>-keep</code></a> option, e.g. "<code>-keep
     class mypackage.MyClass { void myMethod(); }</code>".</dd>
 
-<dt><a name="missingresourceexception"><b>MissingResourceException</b> or
-    <b>NullPointerException</b></a></dt>
+<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.
@@ -382,15 +471,41 @@ might be several reasons:
     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="invalidclassexception2"><b>InvalidClassException</b>,
-    <b>class loading error</b>, or
-    <b>verification error</b> (in Java Micro Edition)</a></dt>
+<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
@@ -403,26 +518,17 @@ might be several reasons:
     <a href="usage.html#dontoptimize"><code>-dontoptimize</code></a>
     option.</dd>
 
-<dt><a name="failingmidlets"><b>Failing midlets</b> (in Java Micro Edition)</a></dt>
-
-<dd>If your midlet simply won't start, you might try using the <a
-    href="usage.html#dontusemixedcaseclassnames"><code>-dontusemixedcaseclassnames</code></a>
-    option. Even if it 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="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>
+<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 examples.</dd>
+    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>
 
@@ -430,19 +536,6 @@ might be several reasons:
     should make sure you're preserving the special methods of the enumeration
     type, as shown in the examples.</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="compilererror"><b>CompilerError: duplicate addition</b></a></dt>
 
 <dd>You are probably compiling or running some code that has been obfuscated
@@ -460,12 +553,12 @@ might be several reasons:
     option. You should then use the same option again in the second processing
     round.</dd>
 
-<dt><a name="nosuchmethoderror"><b>NoSuchMethodError</b> or
-    <b>AbstractMethodError</b></a></dt>
+<dt><a name="nosuchmethoderror"><b>NoSuchMethodError</b> or <b>AbstractMethodError</b></a></dt>
 
-<dd>Again, you should make sure you're not writing your output class files to a
+<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 first item on this list for details.
+    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,
@@ -489,7 +582,7 @@ might be several reasons:
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/usage.html b/docs/manual/usage.html
index a680ff9..7a0a694 100644
--- a/docs/manual/usage.html
+++ b/docs/manual/usage.html
@@ -86,11 +86,11 @@ The sections below provide more details:
 
 <dd>Specifies the input jars (or wars, ears, zips, or directories) of the
     application to be processed. The class files in these jars will be
-    processed and written to the output jars. 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="#filters">filters</a> section. For better
+    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="#filters">filters</a> section. For better
     readability, class path entries can be specified using multiple
     <code>-injars</code> options.</dd>
 
@@ -298,7 +298,7 @@ The sections below provide more details:
     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 reasonings -- these do not
+    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
@@ -344,19 +344,39 @@ The sections below provide more details:
     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 (cfr. <a href=
+    compatibility specifications formally do not require this (cfr. <a href=
     "http://java.sun.com/docs/books/jls/second_edition/html/j.title.doc.html"
     >The Java Language Specification, Second Edition</a>, <a href=
     "http://java.sun.com/docs/books/jls/second_edition/html/binaryComp.doc.html#47259"
-    >Section 13.4.6</a>) formally do not require this, 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).
+    >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>
     Counter-indication: 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://java.sun.com/docs/books/jls/second_edition/html/j.title.doc.html"
+    >The Java Language Specification, Second Edition</a>, <a href=
+    "http://java.sun.com/docs/books/jls/second_edition/html/binaryComp.doc.html#45347"
+    >Section 13.5.3</a>), even if they are not allowed in the Java language
+    (cfr. <a href=
+    "http://java.sun.com/docs/books/jls/second_edition/html/j.title.doc.html"
+    >The Java Language Specification, Second Edition</a>, <a href=
+    "http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#34031"
+    >Section 8.1.4</a>). Only applicable when optimizing.
+    <p>
+    Counter-indication: setting this option can reduce the performance of the
+    processed code on some JVMs, since advanced just-in-time compilation tend
+    to favor more interfaces with fewer implementing classes.</dd>
+
 </dl>
 <p>
 
@@ -414,6 +434,24 @@ The sections below provide more details:
     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
@@ -615,24 +653,26 @@ The sections below provide more details:
 
 <dt><a name="dontnote"><code><b>-dontnote</b></code></a></dt>
 
-<dd>Specifies not to print notes about class casts of variable dynamically
-    created objects. These notes provide hints about classes that may have to
-    be kept.</dd>
+<dd>Specifies not to print notes about potential mistakes or omissions in the
+    configuration, like typos in class names, or missing options that might be
+    useful.</dd>
 
 <dt><a name="dontwarn"><code><b>-dontwarn</b></code></a></dt>
 
 <dd>Specifies not to warn about unresolved references and other important
-    problems at all. 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>
+    problems at all. 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. 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>
+<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>
@@ -853,6 +893,21 @@ 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>
+<table>
+<tr><td valign="top">
+<img src="attention.gif" width="64" height="64"alt="attention">
+</td><td>
+Always remember:
+<ul>
+<li>Specifying a class without class members only preserves the class as an
+    entry point — any class members may then still be removed, optimized,
+    or obfuscated.</li>
+<li>Specifying a class member only preserves the class member as an entry
+    point — any associated code may still be optimized and adapted.</li>
+</ul>
+</td></tr>
+</table>
+<p>
 
 <a name="keepoptionmodifiers"> </a>
 <h2>Keep Option Modifiers</h2>
@@ -899,7 +954,7 @@ definition:
 <p>
 
 <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>@</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><fields></b> |
@@ -924,9 +979,10 @@ files.
 
 <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. Preceding the <code><b>interface</b></code> keyword by a
-    <code><b>!</b></code> restricts matches to classes that are not
-    interfaces.
+    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.
     <p>
 
 <li>Every <i>classname</i> must be fully qualified, e.g.
@@ -1072,7 +1128,7 @@ files.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/manual/wtk.html b/docs/manual/wtk.html
index 77bfb90..30fde13 100644
--- a/docs/manual/wtk.html
+++ b/docs/manual/wtk.html
@@ -15,10 +15,10 @@ for Java Micro Edition (JME).
 <p>
 
 The WTK already comes with a plug-in for ProGuard. Alternatively, ProGuard
-offers its own implementation. The latter implementation solves some problems
-and is somewhat more efficient. It invokes the ProGuard engine directly,
-instead of writing out a configuration file and running ProGuard in a separate
-virtual machine.
+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
@@ -51,7 +51,7 @@ that's inside the <code>proguard.jar</code>.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/quality.html b/docs/quality.html
index fe927fe..4a375f1 100644
--- a/docs/quality.html
+++ b/docs/quality.html
@@ -11,7 +11,7 @@
 <h2>Quality</h2>
 
 In order to get a feel for the quality of the <b>ProGuard</b> code, it is run
-through a nightly automatic build process. This process produces numerous
+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
@@ -31,13 +31,13 @@ full-screen size.
 <p>
 
 In addition, <b>ProGuard</b> is tested against a constantly growing test suite
-(over 450 tests at this time of writing). These small programs contain a wide
-range of common and uncommon constructs, in order to detect any regression
+(more than 500 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 © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/results.html b/docs/results.html
index 240f773..3ef8470 100644
--- a/docs/results.html
+++ b/docs/results.html
@@ -147,7 +147,7 @@ is governed by the basic java virtual machine and by the total size of the
 library jars and program jars.
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 
diff --git a/docs/screenshots.html b/docs/screenshots.html
index c6b2254..954fea0 100644
--- a/docs/screenshots.html
+++ b/docs/screenshots.html
@@ -49,7 +49,7 @@ You can click on the image to see the full-size version.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 </body>
diff --git a/docs/testimonials.html b/docs/testimonials.html
index 73c3b89..79becde 100644
--- a/docs/testimonials.html
+++ b/docs/testimonials.html
@@ -14,10 +14,11 @@ 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 Sun, IBM, HP, Siemens, Nokia, and NATO. It is the default
-tool in many development environments like Sun's Wireless Toolkit, Netbeans,
-EclipseME, and more. Although the quotes below probably don't represent
-official views of any kind, encouragements like these do keep me happy.
+organizations like Sun, IBM, HP, Siemens, Nokia, Google, and NATO. It is the
+default tool in many development environments like Sun's Wireless Toolkit,
+Netbeans, EclipseME, 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">
@@ -113,7 +114,7 @@ You could've been rich.
 
 <hr>
 <address>
-Copyright © 2002-2007
+Copyright © 2002-2008
 <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
 </address>
 
diff --git a/docs/title.html b/docs/title.html
index cbad69f..841d5be 100644
--- a/docs/title.html
+++ b/docs/title.html
@@ -10,7 +10,7 @@
 
 <div class="title">
 <h1><img src="title.gif" width="154" height="29" alt="ProGuard"></h1>
-<div>Version 4.2</div>
+<div>Version 4.3</div>
 </div>
 
 </body>
diff --git a/examples/annotations/lib/annotations.jar b/examples/annotations/lib/annotations.jar
index d2434cb..8dd8fa7 100644
Binary files a/examples/annotations/lib/annotations.jar and b/examples/annotations/lib/annotations.jar differ
diff --git a/examples/ant/proguard.xml b/examples/ant/proguard.xml
index b7e1e25..13ca2ae 100644
--- a/examples/ant/proguard.xml
+++ b/examples/ant/proguard.xml
@@ -9,7 +9,8 @@
   <taskdef resource="proguard/ant/task.properties"
            classpath="lib/proguard.jar" />
 
-  <proguard printmapping="proguard.map"
+  <proguard skipnonpubliclibraryclasses="off"
+            printmapping="proguard.map"
             overloadaggressively="on"
             repackageclasses="">
 
@@ -22,13 +23,14 @@
     <outjar file="examples/ant/proguard_out.jar" />
 
     <libraryjar file="${java.home}/lib/rt.jar" />
-    <libraryjar file="/usr/local/java/ant1.6.5/lib/ant.jar" />
+    <libraryjar file="/usr/local/java/ant1.7.0/lib/ant.jar" />
     <libraryjar file="/usr/local/java/wtk2.1/wtklib/kenv.zip" />
 
     <!-- Adapt the resource file names, based on the corresponding obfuscated
          class names. -->
 
-    <adaptresourcefilenames filter="**.properties,**.gif,**.jpg" />
+    <adaptresourcefilenames    filter="**.properties,**.gif,**.jpg"  />
+    <adaptresourcefilecontents filter="proguard/ant/task.properties" />
 
     <!-- The main seeds: ProGuard and its companion tool ReTrace. -->
 
@@ -53,10 +55,12 @@
 
     <!-- If we have ant.jar, we can properly process the Ant task. -->
 
-    <keep access="public" 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="***" />
-    </keep>
+    </keepclassmembers>
 
     <!-- If we have kenv.zip, we can process the J2ME WTK plugin. -->
 
diff --git a/examples/dictionaries/shakespeare.txt b/examples/dictionaries/shakespeare.txt
old mode 100644
new mode 100755
diff --git a/examples/dictionaries/windows.txt b/examples/dictionaries/windows.txt
new file mode 100644
index 0000000..fd65dc9
--- /dev/null
+++ b/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/examples/proguard.pro b/examples/proguard.pro
index a44fae9..c48b87e 100644
--- a/examples/proguard.pro
+++ b/examples/proguard.pro
@@ -40,13 +40,16 @@
 # If you want to preserve the Ant task as well, you'll have to specify the
 # main ant.jar.
 
-#-libraryjars /usr/local/java/ant1.6.5/lib/ant.jar
-#-keep public class proguard.ant.* {
+#-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 WTK obfuscation plug-in, you'll have to specify
 # the kenv.zip file.
 
diff --git a/examples/proguardall.pro b/examples/proguardall.pro
index 8a24d25..8dc042e 100644
--- a/examples/proguardall.pro
+++ b/examples/proguardall.pro
@@ -17,7 +17,7 @@
 # You may have to adapt the paths below.
 
 -libraryjars <java.home>/lib/rt.jar
--libraryjars /usr/local/java/ant1.6.5/lib/ant.jar
+-libraryjars /usr/local/java/ant1.5.0/lib/ant.jar
 -libraryjars /usr/local/java/wtk2.1/wtklib/kenv.zip
 
 # Allow methods with the same signature, except for the return type,
@@ -29,6 +29,11 @@
 
 -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 {
@@ -45,7 +50,9 @@
 
 # If we have ant.jar, we can properly process the Ant task.
 
--keep public class proguard.ant.* {
+-keep,allowobfuscation class proguard.ant.*
+-keepclassmembers public class proguard.ant.* {
+    <init>(org.apache.tools.ant.Project);
     public void set*(***);
     public void add*(***);
 }
diff --git a/examples/proguardgui.pro b/examples/proguardgui.pro
index 1539274..2cb83ed 100644
--- a/examples/proguardgui.pro
+++ b/examples/proguardgui.pro
@@ -16,6 +16,11 @@
 
 -libraryjars <java.home>/lib/rt.jar
 
+# In recent JREs, some public Swing classes depend on package visible classes,
+# so don't skip these package visible classes while parsing the library jar.
+
+-dontskipnonpubliclibraryclasses
+
 # 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.
@@ -41,7 +46,7 @@
 # class names. Notably, in this case, the GUI resource properties file will
 # have to be renamed.
 
--adaptresourcefilenames
+-adaptresourcefilenames **.properties,**.gif,**.jpg
 
 # The entry point: ProGuardGUI and its main method.
 
diff --git a/src/proguard/ArgumentWordReader.java b/src/proguard/ArgumentWordReader.java
index 512c600..4d0bc2b 100644
--- a/src/proguard/ArgumentWordReader.java
+++ b/src/proguard/ArgumentWordReader.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ClassPath.java b/src/proguard/ClassPath.java
index 8cb27c8..80fb1ca 100644
--- a/src/proguard/ClassPath.java
+++ b/src/proguard/ClassPath.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ClassPathEntry.java b/src/proguard/ClassPathEntry.java
index ec1f9ce..e7b4240 100644
--- a/src/proguard/ClassPathEntry.java
+++ b/src/proguard/ClassPathEntry.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ClassSpecification.java b/src/proguard/ClassSpecification.java
index b6d0cf7..cfc318b 100644
--- a/src/proguard/ClassSpecification.java
+++ b/src/proguard/ClassSpecification.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ClassSpecificationVisitorFactory.java b/src/proguard/ClassSpecificationVisitorFactory.java
index 17148d1..727e51b 100644
--- a/src/proguard/ClassSpecificationVisitorFactory.java
+++ b/src/proguard/ClassSpecificationVisitorFactory.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/Configuration.java b/src/proguard/Configuration.java
index 590eaaf..473a4fb 100644
--- a/src/proguard/Configuration.java
+++ b/src/proguard/Configuration.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -136,6 +136,11 @@ public class Configuration
      */
     public boolean   allowAccessModification          = false;
 
+    /**
+     * Specifies whether interfaces may be merged aggressively.
+     */
+    public boolean   mergeInterfacesAggressively      = false;
+
     ///////////////////////////////////////////////////////////////////////////
     // Obfuscation options.
     ///////////////////////////////////////////////////////////////////////////
@@ -162,6 +167,16 @@ public class Configuration
     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;
diff --git a/src/proguard/ConfigurationConstants.java b/src/proguard/ConfigurationConstants.java
index 3cbed61..1baf79f 100644
--- a/src/proguard/ConfigurationConstants.java
+++ b/src/proguard/ConfigurationConstants.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -52,15 +52,18 @@ class ConfigurationConstants
     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 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 DONT_OPTIMIZE_OPTION                 = "-dontoptimize";
+    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";
diff --git a/src/proguard/ConfigurationParser.java b/src/proguard/ConfigurationParser.java
index fd77af8..7897763 100644
--- a/src/proguard/ConfigurationParser.java
+++ b/src/proguard/ConfigurationParser.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -131,11 +131,14 @@ public class ConfigurationParser
             else if (ConfigurationConstants.OPTIMIZATION_PASSES                              .startsWith(nextWord)) configuration.optimizationPasses               = parseIntegerArgument();
             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);
@@ -423,7 +426,8 @@ public class ConfigurationParser
         while (true)
         {
             readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
-                         "' or '" + ClassConstants.EXTERNAL_ACC_INTERFACE + "'", true);
+                         "', '"      + ClassConstants.EXTERNAL_ACC_INTERFACE +
+                         "', or '"   + ClassConstants.EXTERNAL_ACC_ENUM + "'", true);
 
             if (!ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD.equals(nextWord))
             {
@@ -431,10 +435,9 @@ public class ConfigurationParser
                 break;
             }
 
-            readNextWord("keyword '" +
-                         ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION + "', '" +
-                         ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION + "', or '" +
-                         ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION + "'");
+            readNextWord("keyword '" + ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION +
+                         "', '"      + ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION +
+                         "', or '"   + ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION + "'");
 
             if      (ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION   .startsWith(nextWord))
             {
@@ -450,11 +453,10 @@ public class ConfigurationParser
             }
             else
             {
-                throw new ParseException("Expecting keyword '" +
-                                         ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION + "', '" +
-                                         ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION + "', or '" +
-                                         ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION + "' before " +
-                                         reader.locationDescription());
+                throw new ParseException("Expecting keyword '" + ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION +
+                                         "', '"                + ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION +
+                                         "', or '"             + ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION +
+                                         "' before " + reader.locationDescription());
             }
         }
 
@@ -485,7 +487,8 @@ public class ConfigurationParser
 
         // Read and add the class configuration.
         readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
-                     "' or '" + ClassConstants.EXTERNAL_ACC_INTERFACE + "'", true);
+                     "', '"      + ClassConstants.EXTERNAL_ACC_INTERFACE +
+                     "', or '"   + ClassConstants.EXTERNAL_ACC_ENUM + "'", true);
 
         classSpecifications.add(parseClassSpecificationArguments());
 
@@ -507,16 +510,16 @@ public class ConfigurationParser
         while (!ConfigurationConstants.CLASS_KEYWORD.equals(nextWord))
         {
             // Parse the annotation type, if any.
-            if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
-            {
-                annotationType =
-                    ClassUtil.internalType(
-                    ListUtil.commaSeparatedString(
-                    parseCommaSeparatedList("annotation type",
-                                            true, false, false, true, false, null)));
-
-                continue;
-            }
+//            if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
+//            {
+//                annotationType =
+//                    ClassUtil.internalType(
+//                    ListUtil.commaSeparatedString(
+//                    parseCommaSeparatedList("annotation type",
+//                                            true, false, false, true, false, null)));
+//
+//                continue;
+//            }
 
             // Strip the negating sign, if any.
             String strippedWord = nextWord.startsWith(ConfigurationConstants.NEGATOR_KEYWORD) ?
@@ -524,12 +527,37 @@ public class ConfigurationParser
                 nextWord;
 
             // Parse the class access modifiers.
+            // TODO: Distinguish annotation from annotation modifier.
             int accessFlag =
-                strippedWord.equals(ClassConstants.EXTERNAL_ACC_PUBLIC)    ? ClassConstants.INTERNAL_ACC_PUBLIC    :
-                strippedWord.equals(ClassConstants.EXTERNAL_ACC_FINAL)     ? ClassConstants.INTERNAL_ACC_FINAL     :
-                strippedWord.equals(ClassConstants.EXTERNAL_ACC_INTERFACE) ? ClassConstants.INTERNAL_ACC_INTERFACE :
-                strippedWord.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT)  ? ClassConstants.INTERNAL_ACC_ABSTRACT  :
-                                                                             unknownAccessFlag();
+                strippedWord.equals(ClassConstants.EXTERNAL_ACC_PUBLIC)     ? ClassConstants.INTERNAL_ACC_PUBLIC      :
+                strippedWord.equals(ClassConstants.EXTERNAL_ACC_FINAL)      ? ClassConstants.INTERNAL_ACC_FINAL       :
+                strippedWord.equals(ClassConstants.EXTERNAL_ACC_INTERFACE)  ? ClassConstants.INTERNAL_ACC_INTERFACE   :
+                strippedWord.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT)   ? ClassConstants.INTERNAL_ACC_ABSTRACT    :
+                strippedWord.equals(ClassConstants.EXTERNAL_ACC_ANNOTATION) ? ClassConstants.INTERNAL_ACC_ANNOTATTION :
+                strippedWord.equals(ClassConstants.EXTERNAL_ACC_ENUM)       ? ClassConstants.INTERNAL_ACC_ENUM        :
+                                                                              unknownAccessFlag();
+
+            // Is it an annotation modifier?
+            if (accessFlag == ClassConstants.INTERNAL_ACC_ANNOTATTION)
+            {
+                // Is the next word actually an annotation type?
+                readNextWord("annotation type or keyword '" + ClassConstants.EXTERNAL_ACC_INTERFACE + "'", false);
+
+                if (!nextWord.equals(ClassConstants.EXTERNAL_ACC_INTERFACE) &&
+                    !nextWord.equals(ClassConstants.EXTERNAL_ACC_ENUM)      &&
+                    !nextWord.equals(ConfigurationConstants.CLASS_KEYWORD))
+                {
+                    // Parse the annotation type.
+                    annotationType =
+                        ClassUtil.internalType(
+                        ListUtil.commaSeparatedString(
+                        parseCommaSeparatedList("annotation type",
+                                                false, false, false, true, false, null)));
+
+                    continue;
+                }
+            }
+
             if (strippedWord.equals(nextWord))
             {
                 requiredSetClassAccessFlags   |= accessFlag;
@@ -547,14 +575,17 @@ public class ConfigurationParser
                                          "' before " + reader.locationDescription());
             }
 
-            if (ClassConstants.EXTERNAL_ACC_INTERFACE.equals(strippedWord))
+            if (strippedWord.equals(ClassConstants.EXTERNAL_ACC_INTERFACE) ||
+                strippedWord.equals(ClassConstants.EXTERNAL_ACC_ENUM)      ||
+                strippedWord.equals(ConfigurationConstants.CLASS_KEYWORD))
             {
-                // The interface keyword. Stop parsing the class flags.
+                // The interface or enum keyword. Stop parsing the class flags.
                 break;
             }
 
             readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
-                         "' or '" + ClassConstants.EXTERNAL_ACC_INTERFACE + "'");
+                         "', '"      + ClassConstants.EXTERNAL_ACC_INTERFACE +
+                         "', or '"   + ClassConstants.EXTERNAL_ACC_ENUM + "'", true);
         }
 
        // Parse the class name part.
diff --git a/src/proguard/ConfigurationWriter.java b/src/proguard/ConfigurationWriter.java
index 16a5182..654dfec 100644
--- a/src/proguard/ConfigurationWriter.java
+++ b/src/proguard/ConfigurationWriter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -113,14 +113,17 @@ public class ConfigurationWriter
         writeOption(ConfigurationConstants.DONT_SHRINK_OPTION, !configuration.shrink);
         writeOption(ConfigurationConstants.PRINT_USAGE_OPTION, configuration.printUsage);
 
-        writeOption(ConfigurationConstants.DONT_OPTIMIZE_OPTION,             !configuration.optimize);
-        writeOption(ConfigurationConstants.OPTIMIZATION_PASSES,              configuration.optimizationPasses);
-        writeOption(ConfigurationConstants.ALLOW_ACCESS_MODIFICATION_OPTION, configuration.allowAccessModification);
+        writeOption(ConfigurationConstants.DONT_OPTIMIZE_OPTION,                 !configuration.optimize);
+        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);
@@ -355,7 +358,8 @@ public class ConfigurationWriter
         // keyword earlier.
         if (((classSpecification.requiredSetAccessFlags |
               classSpecification.requiredUnsetAccessFlags) &
-             ClassConstants.INTERNAL_ACC_INTERFACE) == 0)
+             (ClassConstants.INTERNAL_ACC_INTERFACE |
+              ClassConstants.INTERNAL_ACC_ENUM)) == 0)
         {
             writer.print(ConfigurationConstants.CLASS_KEYWORD);
         }
diff --git a/src/proguard/DataEntryReaderFactory.java b/src/proguard/DataEntryReaderFactory.java
index ad7a4e6..68e8eb7 100644
--- a/src/proguard/DataEntryReaderFactory.java
+++ b/src/proguard/DataEntryReaderFactory.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/DataEntryWriterFactory.java b/src/proguard/DataEntryWriterFactory.java
index 40bdc31..1adc75f 100644
--- a/src/proguard/DataEntryWriterFactory.java
+++ b/src/proguard/DataEntryWriterFactory.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/DescriptorKeepChecker.java b/src/proguard/DescriptorKeepChecker.java
index 18cc1a5..e8547f7 100644
--- a/src/proguard/DescriptorKeepChecker.java
+++ b/src/proguard/DescriptorKeepChecker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/DuplicateClassPrinter.java b/src/proguard/DuplicateClassPrinter.java
index 33295f3..09a8b0c 100644
--- a/src/proguard/DuplicateClassPrinter.java
+++ b/src/proguard/DuplicateClassPrinter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/FileWordReader.java b/src/proguard/FileWordReader.java
index 0f8cd57..8ea9767 100644
--- a/src/proguard/FileWordReader.java
+++ b/src/proguard/FileWordReader.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/FullyQualifiedClassNameChecker.java b/src/proguard/FullyQualifiedClassNameChecker.java
index c58bcf7..aeb7398 100644
--- a/src/proguard/FullyQualifiedClassNameChecker.java
+++ b/src/proguard/FullyQualifiedClassNameChecker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/GPL.java b/src/proguard/GPL.java
index f7249bb..64e37cb 100644
--- a/src/proguard/GPL.java
+++ b/src/proguard/GPL.java
@@ -2,14 +2,13 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- *
  * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
diff --git a/src/proguard/Initializer.java b/src/proguard/Initializer.java
index e7e6d3b..03048f2 100644
--- a/src/proguard/Initializer.java
+++ b/src/proguard/Initializer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -59,23 +59,58 @@ public class Initializer
     {
         int originalLibraryClassPoolSize = libraryClassPool.size();
 
-        // Initialize the superclass hierarchy for program classes.
-        WarningPrinter hierarchyWarningPrinter = configuration.warn ?
+        // 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 = configuration.warn ?
             new WarningPrinter(System.err) :
             null;
 
+        WarningPrinter dependencyWarningPrinter = configuration.warn ?
+            new WarningPrinter(System.err) :
+            null;
+
+        // Initialize the superclass hierarchies for program classes.
         programClassPool.classesAccept(
             new ClassSuperHierarchyInitializer(programClassPool,
                                                libraryClassPool,
-                                               hierarchyWarningPrinter));
+                                               classReferenceWarningPrinter,
+                                               null));
+
+        if (reducedLibraryClassPool != null)
+        {
+            // Collect the library classes that are referenced by program
+            // classes.
+            programClassPool.classesAccept(
+                new ReferencedClassVisitor(
+                new LibraryClassFilter(
+                new ClassPoolFiller(reducedLibraryClassPool))));
+
+            // Initialize the superclass hierarchy for referenced library
+            // classes, with warnings.
+            reducedLibraryClassPool.classesAccept(
+                new ClassSuperHierarchyInitializer(programClassPool,
+                                                   libraryClassPool,
+                                                   classReferenceWarningPrinter,
+                                                   dependencyWarningPrinter));
+        }
 
-        // Initialize the superclass hierarchy for library classes.
+        // Initialize the superclass hierarchy for library classes, without
+        // warnings.
         libraryClassPool.classesAccept(
             new ClassSuperHierarchyInitializer(programClassPool,
                                                libraryClassPool,
-                                               null));
+                                               null,
+                                               dependencyWarningPrinter));
+
+        WarningPrinter dynamicClassReferenceNotePrinter = configuration.warn ?
+            new WarningPrinter(System.err) :
+            null;
 
-        // Initialize the Class.forName and .class references.
         WarningPrinter classForNameNotePrinter = configuration.note ?
             new WarningPrinter(System.out) :
             null;
@@ -86,18 +121,21 @@ public class Initializer
             new AllInstructionVisitor(
             new DynamicClassReferenceInitializer(programClassPool,
                                                  libraryClassPool,
+                                                 dynamicClassReferenceNotePrinter,
+                                                 null,
                                                  classForNameNotePrinter,
                                                  createClassNoteExceptionMatcher(configuration.keep))))));
 
         // Initialize the class references of program class members and attributes.
-        WarningPrinter referenceWarningPrinter = configuration.warn ?
+        WarningPrinter memberReferenceWarningPrinter = configuration.warn ?
             new WarningPrinter(System.err) :
             null;
 
         programClassPool.classesAccept(
             new ClassReferenceInitializer(programClassPool,
                                           libraryClassPool,
-                                          referenceWarningPrinter));
+                                          memberReferenceWarningPrinter,
+                                          null));
 
         // Initialize the Class.get[Declared]{Field,Method} references.
         WarningPrinter getMemberNotePrinter = configuration.note ?
@@ -137,22 +175,9 @@ public class Initializer
                                       descriptorKeepNotePrinter).checkClassSpecifications(configuration.keep);
         }
 
-        // Reconstruct a 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.
-        if (configuration.useUniqueClassMemberNames)
+        // Initialize the class references of library class members.
+        if (reducedLibraryClassPool != null)
         {
-            // Initialize the class references of library class members.
-            libraryClassPool.classesAccept(
-                new ClassReferenceInitializer(programClassPool,
-                                              libraryClassPool,
-                                              null));
-        }
-        else
-        {
-            ClassPool referencedLibraryClassPool = new ClassPool();
-
             // Collect the library classes that are referenced by program
             // classes.
             programClassPool.classesAccept(
@@ -160,13 +185,14 @@ public class Initializer
                 new LibraryClassFilter(
                 new ClassHierarchyTraveler(true, true, true, false,
                 new LibraryClassFilter(
-                new ClassPoolFiller(referencedLibraryClassPool))))));
+                new ClassPoolFiller(reducedLibraryClassPool))))));
 
             // Initialize the class references of library class members.
-            referencedLibraryClassPool.classesAccept(
+            reducedLibraryClassPool.classesAccept(
                 new ClassReferenceInitializer(programClassPool,
                                               libraryClassPool,
-                                              null));
+                                              null,
+                                              dependencyWarningPrinter));
 
             // Reset the library class pool.
             libraryClassPool.clear();
@@ -174,7 +200,7 @@ public class Initializer
             // Copy the library classes that are referenced directly by program
             // classes and the library classes that are referenced by referenced
             // library classes.
-            referencedLibraryClassPool.classesAccept(
+            reducedLibraryClassPool.classesAccept(
                 new MultiClassVisitor(new ClassVisitor[]
                 {
                     new ClassHierarchyTraveler(true, true, true, false,
@@ -188,6 +214,15 @@ public class Initializer
                     new ClassPoolFiller(libraryClassPool)))))
                 }));
         }
+        else
+        {
+            // Initialize the class references of all library class members.
+            libraryClassPool.classesAccept(
+                new ClassReferenceInitializer(programClassPool,
+                                              libraryClassPool,
+                                              null,
+                                              dependencyWarningPrinter));
+        }
 
         // Initialize the subclass hierarchies.
         programClassPool.classesAccept(new ClassSubHierarchyInitializer());
@@ -221,6 +256,17 @@ public class Initializer
             }
         }
 
+        if (dynamicClassReferenceNotePrinter != null)
+        {
+            int dynamicClassReferenceNoteCount = dynamicClassReferenceNotePrinter.getWarningCount();
+            if (dynamicClassReferenceNoteCount > 0)
+            {
+                System.out.println("Note: there were " + dynamicClassReferenceNoteCount +
+                                   " unresolved dynamic references to classes or interfaces.");
+                System.err.println("      You should check if you need to specify additional program jars.");
+            }
+        }
+
         if (classForNameNotePrinter != null)
         {
             int classForNameNoteCount = classForNameNotePrinter.getWarningCount();
@@ -246,22 +292,32 @@ public class Initializer
         }
 
         // Print out a summary of the warnings, if necessary.
-        if (hierarchyWarningPrinter != null &&
-            referenceWarningPrinter != null)
+        if (classReferenceWarningPrinter  != null &&
+            dependencyWarningPrinter      != null &&
+            memberReferenceWarningPrinter != null   )
         {
-            int hierarchyWarningCount = hierarchyWarningPrinter.getWarningCount();
-            if (hierarchyWarningCount > 0)
+            int classReferenceWarningCount = classReferenceWarningPrinter.getWarningCount();
+            if (classReferenceWarningCount > 0)
             {
-                System.err.println("Warning: there were " + hierarchyWarningCount +
-                                   " unresolved references to superclasses or interfaces.");
+                System.err.println("Warning: there were " + classReferenceWarningCount +
+                                   " unresolved references to classes or interfaces.");
                 System.err.println("         You may need to specify additional library jars (using '-libraryjars'),");
                 System.err.println("         or perhaps the '-dontskipnonpubliclibraryclasses' option.");
             }
 
-            int referenceWarningCount = referenceWarningPrinter.getWarningCount();
-            if (referenceWarningCount > 0)
+            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.");
+            }
+
+            int memberReferenceWarningCount = memberReferenceWarningPrinter.getWarningCount();
+            if (memberReferenceWarningCount > 0)
             {
-                System.err.println("Warning: there were " + referenceWarningCount +
+                System.err.println("Warning: there were " + memberReferenceWarningCount +
                                    " unresolved references to program class members.");
                 System.err.println("         Your input classes appear to be inconsistent.");
                 System.err.println("         You may need to recompile them and try again.");
@@ -270,8 +326,9 @@ public class Initializer
                 System.err.println("         '-dontskipnonpubliclibraryclassmembers'.");
             }
 
-            if ((hierarchyWarningCount > 0 ||
-                 referenceWarningCount > 0) &&
+            if ((classReferenceWarningCount   > 0 ||
+                 dependencyWarningCount       > 0 ||
+                 memberReferenceWarningCount  > 0) &&
                 !configuration.ignoreWarnings)
             {
                 throw new IOException("Please correct the above warnings first.");
diff --git a/src/proguard/InputReader.java b/src/proguard/InputReader.java
index eda47c8..ebdc831 100644
--- a/src/proguard/InputReader.java
+++ b/src/proguard/InputReader.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/KeepSpecification.java b/src/proguard/KeepSpecification.java
index dcd4ec8..5fd4fae 100644
--- a/src/proguard/KeepSpecification.java
+++ b/src/proguard/KeepSpecification.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/MANIFEST.MF b/src/proguard/MANIFEST.MF
new file mode 100644
index 0000000..3bad15e
--- /dev/null
+++ b/src/proguard/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+Main-Class: proguard.ProGuard
diff --git a/src/proguard/MemberSpecification.java b/src/proguard/MemberSpecification.java
index 388fd37..1f9c2ca 100644
--- a/src/proguard/MemberSpecification.java
+++ b/src/proguard/MemberSpecification.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/OutputWriter.java b/src/proguard/OutputWriter.java
index 3e231ad..915e806 100644
--- a/src/proguard/OutputWriter.java
+++ b/src/proguard/OutputWriter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ParseException.java b/src/proguard/ParseException.java
index 98f1889..88378b3 100644
--- a/src/proguard/ParseException.java
+++ b/src/proguard/ParseException.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ProGuard.java b/src/proguard/ProGuard.java
index 0fcafca..a9f0e5c 100644
--- a/src/proguard/ProGuard.java
+++ b/src/proguard/ProGuard.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -37,7 +37,7 @@ import java.io.*;
  */
 public class ProGuard
 {
-    public static final String VERSION = "ProGuard, version 4.2";
+    public static final String VERSION = "ProGuard, version 4.3";
 
     private final Configuration configuration;
     private       ClassPool     programClassPool = new ClassPool();
diff --git a/src/proguard/SubclassedClassFilter.java b/src/proguard/SubclassedClassFilter.java
index 5ee9b1c..268a6fe 100644
--- a/src/proguard/SubclassedClassFilter.java
+++ b/src/proguard/SubclassedClassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/Targeter.java b/src/proguard/Targeter.java
index 1217a51..e2fcee8 100644
--- a/src/proguard/Targeter.java
+++ b/src/proguard/Targeter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard;
 
diff --git a/src/proguard/UpToDateChecker.java b/src/proguard/UpToDateChecker.java
index 4a2a964..0586d12 100644
--- a/src/proguard/UpToDateChecker.java
+++ b/src/proguard/UpToDateChecker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/WordReader.java b/src/proguard/WordReader.java
index f3b7c50..275f9b9 100644
--- a/src/proguard/WordReader.java
+++ b/src/proguard/WordReader.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/ClassPathElement.java b/src/proguard/ant/ClassPathElement.java
index 42724bd..c644c88 100644
--- a/src/proguard/ant/ClassPathElement.java
+++ b/src/proguard/ant/ClassPathElement.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/ClassSpecificationElement.java b/src/proguard/ant/ClassSpecificationElement.java
index 8910362..4356f15 100644
--- a/src/proguard/ant/ClassSpecificationElement.java
+++ b/src/proguard/ant/ClassSpecificationElement.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -219,9 +219,10 @@ public class ClassSpecificationElement extends DataType
                         token;
 
                     int accessFlag =
-                        strippedToken.equals(ClassConstants.EXTERNAL_ACC_PUBLIC)   ? ClassConstants.INTERNAL_ACC_PUBLIC   :
-                        strippedToken.equals(ClassConstants.EXTERNAL_ACC_FINAL)    ? ClassConstants.INTERNAL_ACC_FINAL    :
-                        strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
+                        strippedToken.equals(ClassConstants.EXTERNAL_ACC_PUBLIC)     ? ClassConstants.INTERNAL_ACC_PUBLIC      :
+                        strippedToken.equals(ClassConstants.EXTERNAL_ACC_FINAL)      ? ClassConstants.INTERNAL_ACC_FINAL       :
+                        strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT)   ? ClassConstants.INTERNAL_ACC_ABSTRACT    :
+                        strippedToken.equals(ClassConstants.EXTERNAL_ACC_ANNOTATION) ? ClassConstants.INTERNAL_ACC_ANNOTATTION :
                         0;
 
                     if (accessFlag == 0)
@@ -237,9 +238,11 @@ public class ClassSpecificationElement extends DataType
         if (type != null && (type.startsWith("!") ^ set))
         {
             int accessFlag =
+                type.equals("class")                                     ? 0                                     :
                 type.equals(      ClassConstants.EXTERNAL_ACC_INTERFACE) ||
                 type.equals("!" + ClassConstants.EXTERNAL_ACC_INTERFACE) ? ClassConstants.INTERNAL_ACC_INTERFACE :
-                type.equals("class")                                     ? 0                                     :
+                type.equals(      ClassConstants.EXTERNAL_ACC_ENUM)      ||
+                type.equals("!" + ClassConstants.EXTERNAL_ACC_ENUM)      ? ClassConstants.INTERNAL_ACC_ENUM      :
                                                                            -1;
             if (accessFlag == -1)
             {
diff --git a/src/proguard/ant/ConfigurationElement.java b/src/proguard/ant/ConfigurationElement.java
index 7332444..b9d52af 100644
--- a/src/proguard/ant/ConfigurationElement.java
+++ b/src/proguard/ant/ConfigurationElement.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/ConfigurationTask.java b/src/proguard/ant/ConfigurationTask.java
index 2024455..66b87b6 100644
--- a/src/proguard/ant/ConfigurationTask.java
+++ b/src/proguard/ant/ConfigurationTask.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/FilterElement.java b/src/proguard/ant/FilterElement.java
index 6c8fd3b..66d25ed 100644
--- a/src/proguard/ant/FilterElement.java
+++ b/src/proguard/ant/FilterElement.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/KeepAttributeElement.java b/src/proguard/ant/KeepAttributeElement.java
index b4b8aeb..ac066a8 100644
--- a/src/proguard/ant/KeepAttributeElement.java
+++ b/src/proguard/ant/KeepAttributeElement.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/KeepSpecificationElement.java b/src/proguard/ant/KeepSpecificationElement.java
index 13305ce..9bc2856 100644
--- a/src/proguard/ant/KeepSpecificationElement.java
+++ b/src/proguard/ant/KeepSpecificationElement.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/MemberSpecificationElement.java b/src/proguard/ant/MemberSpecificationElement.java
index a03dfff..a52541e 100644
--- a/src/proguard/ant/MemberSpecificationElement.java
+++ b/src/proguard/ant/MemberSpecificationElement.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/ant/ProGuardTask.java b/src/proguard/ant/ProGuardTask.java
index 967ea98..0dbd1e3 100644
--- a/src/proguard/ant/ProGuardTask.java
+++ b/src/proguard/ant/ProGuardTask.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -134,6 +134,12 @@ public class ProGuardTask extends ConfigurationTask
     }
 
 
+    public void setMergeinterfacesaggressively(boolean mergeinterfacesaggressively)
+    {
+        configuration.mergeInterfacesAggressively = mergeinterfacesaggressively;
+    }
+
+
     public void setObfuscate(boolean obfuscate)
     {
         configuration.obfuscate = obfuscate;
@@ -158,6 +164,18 @@ public class ProGuardTask extends ConfigurationTask
     }
 
 
+    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;
diff --git a/src/proguard/classfile/ClassConstants.java b/src/proguard/classfile/ClassConstants.java
index bf3d3ae..e873e1f 100644
--- a/src/proguard/classfile/ClassConstants.java
+++ b/src/proguard/classfile/ClassConstants.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
@@ -123,6 +123,8 @@ public interface ClassConstants
     public static final String EXTERNAL_ACC_INTERFACE    = "interface";
     public static final String EXTERNAL_ACC_ABSTRACT     = "abstract";
     public static final String EXTERNAL_ACC_STRICT       = "strictfp";
+    public static final String EXTERNAL_ACC_ANNOTATION   = "@";
+    public static final String EXTERNAL_ACC_ENUM         = "enum";
 
     public static final int CONSTANT_Utf8               = 1;
     public static final int CONSTANT_Integer            = 3;
diff --git a/src/proguard/classfile/ClassPool.java b/src/proguard/classfile/ClassPool.java
index 054e7df..3ccc787 100644
--- a/src/proguard/classfile/ClassPool.java
+++ b/src/proguard/classfile/ClassPool.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
diff --git a/src/proguard/classfile/Clazz.java b/src/proguard/classfile/Clazz.java
index 9919f46..e279598 100644
--- a/src/proguard/classfile/Clazz.java
+++ b/src/proguard/classfile/Clazz.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
@@ -159,6 +159,13 @@ public interface Clazz extends VisitorAccepter
                                 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.
      */
@@ -171,6 +178,24 @@ public interface Clazz extends VisitorAccepter
     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);
@@ -201,85 +226,6 @@ public interface Clazz extends VisitorAccepter
     public boolean mayHaveImplementations(Method method);
 
     /**
-     * Lets the given member info visitor visit all concrete implementations of
-     * the specified method in the class hierarchy.
-     * @param method            the method that may have concrete implementations.
-     * @param visitThisMethod   specifies whether to visit the method in
-     *                          this class.
-     * @param memberVisitor     the <code>MemberVisitor</code> that will
-     *                          visit the method hierarchy.
-     */
-    public void methodImplementationsAccept(Method        method,
-                                            boolean       visitThisMethod,
-                                            MemberVisitor memberVisitor);
-
-    /**
-     * Lets the given member info visitor visit all concrete implementations of
-     * the specified method in the class hierarchy.
-     * @param name              the method name.
-     * @param type              the method descriptor.
-     * @param visitThisMethod   specifies whether to visit the method in
-     *                          this class.
-     * @param memberVisitor     the <code>MemberVisitor</code> that will
-     *                          visit the method hierarchy.
-     */
-    public void methodImplementationsAccept(String        name,
-                                            String        type,
-                                            boolean       visitThisMethod,
-                                            MemberVisitor memberVisitor);
-
-    /**
-     * Lets the given member info visitor visit all concrete implementations of
-     * the specified method in the class hierarchy.
-     * @param name                   the method name.
-     * @param descriptor             the method descriptor.
-     * @param visitThisMethod        specifies whether to visit the method in
-     *                               this class.
-     * @param visitSpecialMethods    specifies whether to visit the special
-     *                               initializer methods.
-     * @param visitSuperMethods      specifies whether to visit the method in
-     *                               the super classes.
-     * @param visitOverridingMethods specifies whether to visit the method in
-     *                               the subclasses.
-     * @param visitSpecialMethods    specifies whether to visit special methods.
-     * @param memberVisitor          the <code>MemberVisitor</code> that
-     *                               will visit the method hierarchy.
-     */
-    public void methodImplementationsAccept(String        name,
-                                            String        descriptor,
-                                            boolean       visitThisMethod,
-                                            boolean       visitSpecialMethods,
-                                            boolean       visitSuperMethods,
-                                            boolean       visitOverridingMethods,
-                                            MemberVisitor memberVisitor);
-    /**
-     * Lets the given member info visitor visit all concrete implementations of
-     * the specified method in the class hierarchy.
-     * @param name                   the method name.
-     * @param descriptor             the method descriptor.
-     * @param method                 the method itself, if present.
-     * @param visitThisMethod        specifies whether to visit the method in
-     *                               this class.
-     * @param visitSpecialMethods    specifies whether to visit the method in
-     *                               the interfaces.
-     * @param visitSuperMethods      specifies whether to visit the method in
-     *                               the super classes.
-     * @param visitOverridingMethods specifies whether to visit the method in
-     *                               the subclasses.
-     * @param visitSpecialMethods    specifies whether to visit special methods.
-     * @param memberVisitor          the <code>MemberVisitor</code> that
-     *                               will visit the method hierarchy.
-     */
-    public void methodImplementationsAccept(String        name,
-                                            String        descriptor,
-                                            Method        method,
-                                            boolean       visitThisMethod,
-                                            boolean       visitSuperMethods,
-                                            boolean       visitOverridingMethods,
-                                            boolean       visitSpecialMethods,
-                                            MemberVisitor memberVisitor);
-
-    /**
      * Lets the given attribute info visitor visit all attributes of this class.
      */
     public void attributesAccept(AttributeVisitor attributeVisitor);
diff --git a/src/proguard/classfile/Field.java b/src/proguard/classfile/Field.java
index d516c10..03fe5cd 100644
--- a/src/proguard/classfile/Field.java
+++ b/src/proguard/classfile/Field.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
diff --git a/src/proguard/classfile/LibraryClass.java b/src/proguard/classfile/LibraryClass.java
index fef6938..77d5f33 100644
--- a/src/proguard/classfile/LibraryClass.java
+++ b/src/proguard/classfile/LibraryClass.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
@@ -277,6 +277,20 @@ public class LibraryClass implements Clazz
         // 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++)
@@ -285,7 +299,7 @@ public class LibraryClass implements Clazz
                     if (interfaceClass != null)
                     {
                         interfaceClass.hierarchyAccept(true,
-                                                       true,
+                                                       false,
                                                        true,
                                                        false,
                                                        classVisitor);
@@ -312,6 +326,53 @@ public class LibraryClass implements Clazz
     }
 
 
+    /**
+     * 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.
@@ -324,6 +385,24 @@ public class LibraryClass implements Clazz
     }
 
 
+    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++)
@@ -382,157 +461,6 @@ public class LibraryClass implements Clazz
     }
 
 
-    private boolean isSpecial(Method method)
-    {
-        return
-            (method.getAccessFlags() & (ClassConstants.INTERNAL_ACC_PRIVATE |
-                                        ClassConstants.INTERNAL_ACC_STATIC)) != 0 ||
-                                                                                  method.getName(this).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT);
-    }
-
-
-    public void methodImplementationsAccept(Method        method,
-                                            boolean       visitThisMethod,
-                                            MemberVisitor memberVisitor)
-    {
-        methodImplementationsAccept(method.getName(this),
-                                    method.getDescriptor(this),
-                                    method,
-                                    visitThisMethod,
-                                    true,
-                                    true,
-                                    true,
-                                    memberVisitor);
-    }
-
-
-    public void methodImplementationsAccept(String        name,
-                                            String        descriptor,
-                                            boolean       visitThisMethod,
-                                            MemberVisitor memberVisitor)
-    {
-        methodImplementationsAccept(name,
-                                    descriptor,
-                                    visitThisMethod,
-                                    true,
-                                    true,
-                                    true,
-                                    memberVisitor);
-    }
-
-
-    public void methodImplementationsAccept(String        name,
-                                            String        descriptor,
-                                            boolean       visitThisMethod,
-                                            boolean       visitSpecialMethods,
-                                            boolean       visitSuperMethods,
-                                            boolean       visitOverridingMethods,
-                                            MemberVisitor memberVisitor)
-    {
-        methodImplementationsAccept(name,
-                                    descriptor,
-                                    findMethod(name, descriptor),
-                                    visitThisMethod,
-                                    visitSpecialMethods,
-                                    visitSuperMethods,
-                                    visitOverridingMethods,
-                                    memberVisitor);
-    }
-
-
-    public void methodImplementationsAccept(String        name,
-                                            String        descriptor,
-                                            Method        method,
-                                            boolean       visitThisMethod,
-                                            boolean       visitSpecialMethods,
-                                            boolean       visitSuperMethods,
-                                            boolean       visitOverridingMethods,
-                                            MemberVisitor memberVisitor)
-    {
-        // Do we have the method in this class?
-        if (method != null)
-        {
-            // Is it a special method?
-            if (isSpecial(method))
-            {
-                // Visit the special method in this class, if allowed.
-                if (visitSpecialMethods)
-                {
-                    method.accept(this, memberVisitor);
-
-                    // The method can't have any other implementations.
-                    return;
-                }
-            }
-            else
-            {
-                // Visit the method in this class, if allowed.
-                if (visitThisMethod)
-                {
-                    method.accept(this, memberVisitor);
-                }
-
-                // We don't have to look in subclasses if there can't be
-                // any overriding implementations.
-                if (!mayHaveImplementations(method))
-                {
-                    visitOverridingMethods = false;
-                }
-
-                // We don't have to look in superclasses if we have a concrete
-                // implementation here.
-                if ((method.getAccessFlags() & ClassConstants.INTERNAL_ACC_ABSTRACT) == 0)
-                {
-                    visitSuperMethods = false;
-                }
-            }
-        }
-
-        // Then visit the method in its subclasses, recursively.
-        if (visitOverridingMethods)
-        {
-            // Go looking for implementations in all of the subclasses.
-            if (subClasses != null)
-            {
-                for (int index = 0; index < subClasses.length; index++)
-                {
-                    Clazz subClass = subClasses[index];
-                    subClass.methodImplementationsAccept(name,
-                                                         descriptor,
-                                                         true,
-                                                         false,
-                                                         visitSuperMethods,
-                                                         true,
-                                                         memberVisitor);
-                }
-            }
-
-            // We don't have to look in superclasses right away if we dont't
-            // have a concrete class here.
-            if ((u2accessFlags & (ClassConstants.INTERNAL_ACC_INTERFACE |
-                                  ClassConstants.INTERNAL_ACC_ABSTRACT)) != 0)
-            {
-                visitSuperMethods = false;
-            }
-        }
-
-        // Then visit the method in its superclass, recursively.
-        if (visitSuperMethods)
-        {
-            if (superClass != null)
-            {
-                superClass.methodImplementationsAccept(name,
-                                                       descriptor,
-                                                       true,
-                                                       false,
-                                                       true,
-                                                       false,
-                                                       memberVisitor);
-            }
-        }
-    }
-
-
     public void attributesAccept(AttributeVisitor attributeVisitor)
     {
         throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store attributes");
@@ -550,4 +478,12 @@ public class LibraryClass implements Clazz
     {
         this.visitorInfo = visitorInfo;
     }
+
+
+    // Implementations for Object.
+
+    public String toString()
+    {
+        return "LibraryClass("+getName()+")";
+    }
 }
diff --git a/src/proguard/classfile/LibraryField.java b/src/proguard/classfile/LibraryField.java
index 265b10e..91b9070 100644
--- a/src/proguard/classfile/LibraryField.java
+++ b/src/proguard/classfile/LibraryField.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
@@ -46,6 +46,17 @@ public class LibraryField extends LibraryMember implements Field
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/LibraryMember.java b/src/proguard/classfile/LibraryMember.java
index 92caf19..4dc29c2 100644
--- a/src/proguard/classfile/LibraryMember.java
+++ b/src/proguard/classfile/LibraryMember.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
@@ -43,7 +43,25 @@ public abstract class LibraryMember implements Member
     public Object visitorInfo;
 
 
-    protected LibraryMember() {}
+    /**
+     * 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;
+    }
 
 
     /**
diff --git a/src/proguard/classfile/LibraryMethod.java b/src/proguard/classfile/LibraryMethod.java
index 1f294f4..17e6208 100644
--- a/src/proguard/classfile/LibraryMethod.java
+++ b/src/proguard/classfile/LibraryMethod.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
@@ -46,6 +46,17 @@ public class LibraryMethod extends LibraryMember implements Method
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/Member.java b/src/proguard/classfile/Member.java
index c6cd3bc..170b296 100644
--- a/src/proguard/classfile/Member.java
+++ b/src/proguard/classfile/Member.java
@@ -2,45 +2,45 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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 program class.
+ * Representation of a field or method from a class.
  *
  * @author Eric Lafortune
  */
 public interface Member extends VisitorAccepter
 {
     /**
-     * Returns access flags.
+     * Returns the access flags.
      */
     public int getAccessFlags();
 
     /**
-     * Returns method/field string name.
+     * Returns the class member name.
      */
     public String getName(Clazz clazz);
 
     /**
-     * Returns descriptor string.
+     * Returns the class member's descriptor.
      */
     public String getDescriptor(Clazz clazz);
 
diff --git a/src/proguard/classfile/Method.java b/src/proguard/classfile/Method.java
index 4adf1fa..2131ca8 100644
--- a/src/proguard/classfile/Method.java
+++ b/src/proguard/classfile/Method.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
diff --git a/src/proguard/classfile/ProgramClass.java b/src/proguard/classfile/ProgramClass.java
index 27e678a..5b1333a 100644
--- a/src/proguard/classfile/ProgramClass.java
+++ b/src/proguard/classfile/ProgramClass.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
@@ -311,13 +311,28 @@ public class ProgramClass implements Clazz
         // 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,
-                                                   true,
+                                                   false,
                                                    true,
                                                    false,
                                                    classVisitor);
@@ -344,6 +359,18 @@ public class ProgramClass implements Clazz
     }
 
 
+    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++)
@@ -362,6 +389,30 @@ public class ProgramClass implements Clazz
     }
 
 
+    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++)
@@ -412,158 +463,6 @@ public class ProgramClass implements Clazz
     }
 
 
-    private boolean isSpecial(Method method)
-    {
-        return
-            (method.getAccessFlags() & (ClassConstants.INTERNAL_ACC_PRIVATE |
-                                        ClassConstants.INTERNAL_ACC_STATIC)) != 0 ||
-            method.getName(this).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT);
-    }
-
-
-    public void methodImplementationsAccept(Method        method,
-                                            boolean       visitThisMethod,
-                                            MemberVisitor memberVisitor)
-    {
-        methodImplementationsAccept(method.getName(this),
-                                    method.getDescriptor(this),
-                                    method,
-                                    visitThisMethod,
-                                    true,
-                                    true,
-                                    true,
-                                    memberVisitor);
-    }
-
-
-    public void methodImplementationsAccept(String        name,
-                                            String        descriptor,
-                                            boolean       visitThisMethod,
-                                            MemberVisitor memberVisitor)
-    {
-        methodImplementationsAccept(name,
-                                    descriptor,
-                                    visitThisMethod,
-                                    true,
-                                    true,
-                                    true,
-                                    memberVisitor);
-    }
-
-
-    public void methodImplementationsAccept(String        name,
-                                            String        descriptor,
-                                            boolean       visitThisMethod,
-                                            boolean       visitSpecialMethods,
-                                            boolean       visitSuperMethods,
-                                            boolean       visitOverridingMethods,
-                                            MemberVisitor memberVisitor)
-    {
-        methodImplementationsAccept(name,
-                                    descriptor,
-                                    findMethod(name, descriptor),
-                                    visitThisMethod,
-                                    visitSpecialMethods,
-                                    visitSuperMethods,
-                                    visitOverridingMethods,
-                                    memberVisitor);
-    }
-
-
-    public void methodImplementationsAccept(String        name,
-                                            String        descriptor,
-                                            Method        method,
-                                            boolean       visitThisMethod,
-                                            boolean       visitSpecialMethods,
-                                            boolean       visitSuperMethods,
-                                            boolean       visitOverridingMethods,
-                                            MemberVisitor memberVisitor)
-    {
-        // Do we have the method in this class?
-        if (method != null)
-        {
-            // Is it a special method?
-            if (isSpecial(method))
-            {
-                // Visit the special method in this class, if allowed.
-                if (visitSpecialMethods)
-                {
-                    method.accept(this, memberVisitor);
-
-                    // The method can't have any other implementations.
-                    return;
-                }
-            }
-            else
-            {
-                // Visit the method in this class, if allowed.
-                if (visitThisMethod)
-                {
-                    method.accept(this, memberVisitor);
-                }
-
-                // We don't have to look in subclasses if there can't be
-                // any overriding implementations.
-                if (!mayHaveImplementations(method))
-                {
-                    visitOverridingMethods = false;
-                }
-
-                // We don't have to look in superclasses if we have a concrete
-                // implementation here.
-                if ((method.getAccessFlags() & ClassConstants.INTERNAL_ACC_ABSTRACT) == 0)
-                {
-                    visitSuperMethods = false;
-                }
-            }
-        }
-
-        // Then visit the method in its subclasses, recursively.
-        if (visitOverridingMethods)
-        {
-            // Go looking for implementations in all of the subclasses.
-            if (subClasses != null)
-            {
-                for (int index = 0; index < subClasses.length; index++)
-                {
-                    Clazz subClass = subClasses[index];
-                    subClass.methodImplementationsAccept(name,
-                                                         descriptor,
-                                                         true,
-                                                         false,
-                                                         visitSuperMethods,
-                                                         true,
-                                                         memberVisitor);
-                }
-            }
-
-            // We don't have to look in superclasses right away if we dont't
-            // have a concrete class here.
-            if ((u2accessFlags & (ClassConstants.INTERNAL_ACC_INTERFACE |
-                                  ClassConstants.INTERNAL_ACC_ABSTRACT)) != 0)
-            {
-                visitSuperMethods = false;
-            }
-        }
-
-        // Then visit the method in its superclass, recursively.
-        if (visitSuperMethods)
-        {
-            Clazz superClass = getSuperClass();
-            if (superClass != null)
-            {
-                superClass.methodImplementationsAccept(name,
-                                                       descriptor,
-                                                       true,
-                                                       false,
-                                                       true,
-                                                       false,
-                                                       memberVisitor);
-            }
-        }
-    }
-
-
     public void attributesAccept(AttributeVisitor attributeVisitor)
     {
         for (int index = 0; index < u2attributesCount; index++)
@@ -584,4 +483,12 @@ public class ProgramClass implements Clazz
     {
         this.visitorInfo = visitorInfo;
     }
+
+
+    // Implementations for Object.
+
+    public String toString()
+    {
+        return "ProgramClass("+getName()+")";
+    }
 }
diff --git a/src/proguard/classfile/ProgramField.java b/src/proguard/classfile/ProgramField.java
index 58720b1..05b3b10 100644
--- a/src/proguard/classfile/ProgramField.java
+++ b/src/proguard/classfile/ProgramField.java
@@ -2,25 +2,26 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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.attribute.Attribute;
 import proguard.classfile.visitor.*;
 
 /**
@@ -47,6 +48,22 @@ public class ProgramField extends ProgramMember implements Field
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/ProgramMember.java b/src/proguard/classfile/ProgramMember.java
index 6fe5fb3..a81bf99 100644
--- a/src/proguard/classfile/ProgramMember.java
+++ b/src/proguard/classfile/ProgramMember.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
@@ -44,7 +44,29 @@ public abstract class ProgramMember implements Member
     public Object visitorInfo;
 
 
-    protected ProgramMember() {}
+    /**
+     * 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;
+    }
 
 
     /**
diff --git a/src/proguard/classfile/ProgramMethod.java b/src/proguard/classfile/ProgramMethod.java
index 89a09f7..70e6b8c 100644
--- a/src/proguard/classfile/ProgramMethod.java
+++ b/src/proguard/classfile/ProgramMethod.java
@@ -2,25 +2,26 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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.attribute.Attribute;
 import proguard.classfile.visitor.*;
 
 /**
@@ -47,6 +48,22 @@ public class ProgramMethod extends ProgramMember implements Method
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/VisitorAccepter.java b/src/proguard/classfile/VisitorAccepter.java
index a3fa6a2..a312767 100644
--- a/src/proguard/classfile/VisitorAccepter.java
+++ b/src/proguard/classfile/VisitorAccepter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 package proguard.classfile;
 
diff --git a/src/proguard/classfile/attribute/Attribute.java b/src/proguard/classfile/attribute/Attribute.java
index 6f326f9..0f46fbc 100644
--- a/src/proguard/classfile/attribute/Attribute.java
+++ b/src/proguard/classfile/attribute/Attribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -44,6 +44,23 @@ public abstract class Attribute implements VisitorAccepter
 
 
     /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/CodeAttribute.java b/src/proguard/classfile/attribute/CodeAttribute.java
index 2efbaf3..4206105 100644
--- a/src/proguard/classfile/attribute/CodeAttribute.java
+++ b/src/proguard/classfile/attribute/CodeAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -51,6 +51,32 @@ public class CodeAttribute extends Attribute
 
 
     /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/ConstantValueAttribute.java b/src/proguard/classfile/attribute/ConstantValueAttribute.java
index cbd9fa5..a3b5793 100644
--- a/src/proguard/classfile/attribute/ConstantValueAttribute.java
+++ b/src/proguard/classfile/attribute/ConstantValueAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -41,6 +41,18 @@ public class ConstantValueAttribute extends Attribute
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/DeprecatedAttribute.java b/src/proguard/classfile/attribute/DeprecatedAttribute.java
index c77850e..cd5b39a 100644
--- a/src/proguard/classfile/attribute/DeprecatedAttribute.java
+++ b/src/proguard/classfile/attribute/DeprecatedAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -38,6 +38,15 @@ public class DeprecatedAttribute extends Attribute
     }
 
 
+    /**
+     * Creates an initialized DeprecatedAttribute.
+     */
+    public DeprecatedAttribute(int u2attributeNameIndex)
+    {
+        super(u2attributeNameIndex);
+    }
+
+
     // Implementations for Attribute.
 
     public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
diff --git a/src/proguard/classfile/attribute/EnclosingMethodAttribute.java b/src/proguard/classfile/attribute/EnclosingMethodAttribute.java
index f7e7c22..4314865 100644
--- a/src/proguard/classfile/attribute/EnclosingMethodAttribute.java
+++ b/src/proguard/classfile/attribute/EnclosingMethodAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -60,6 +60,20 @@ public class EnclosingMethodAttribute extends Attribute
 
 
     /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/ExceptionInfo.java b/src/proguard/classfile/attribute/ExceptionInfo.java
index e8a3d3a..765c250 100644
--- a/src/proguard/classfile/attribute/ExceptionInfo.java
+++ b/src/proguard/classfile/attribute/ExceptionInfo.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/ExceptionsAttribute.java b/src/proguard/classfile/attribute/ExceptionsAttribute.java
index 25c5758..2e91add 100644
--- a/src/proguard/classfile/attribute/ExceptionsAttribute.java
+++ b/src/proguard/classfile/attribute/ExceptionsAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -43,6 +43,20 @@ public class ExceptionsAttribute extends Attribute
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/InnerClassesAttribute.java b/src/proguard/classfile/attribute/InnerClassesAttribute.java
index 877cf7d..15a5460 100644
--- a/src/proguard/classfile/attribute/InnerClassesAttribute.java
+++ b/src/proguard/classfile/attribute/InnerClassesAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -42,6 +42,21 @@ public class InnerClassesAttribute extends Attribute
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/InnerClassesInfo.java b/src/proguard/classfile/attribute/InnerClassesInfo.java
index 07db1fd..e8b7fc4 100644
--- a/src/proguard/classfile/attribute/InnerClassesInfo.java
+++ b/src/proguard/classfile/attribute/InnerClassesInfo.java
@@ -2,25 +2,26 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
+import proguard.classfile.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
 
 /**
  * Representation of an Inner Classes table entry.
@@ -65,6 +66,48 @@ public class InnerClassesInfo implements VisitorAccepter
     }
 
 
+    /**
+     * 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()
diff --git a/src/proguard/classfile/attribute/LineNumberInfo.java b/src/proguard/classfile/attribute/LineNumberInfo.java
index b2fbdd4..cbd42aa 100644
--- a/src/proguard/classfile/attribute/LineNumberInfo.java
+++ b/src/proguard/classfile/attribute/LineNumberInfo.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/LineNumberTableAttribute.java b/src/proguard/classfile/attribute/LineNumberTableAttribute.java
index c3cfa20..4e3784d 100644
--- a/src/proguard/classfile/attribute/LineNumberTableAttribute.java
+++ b/src/proguard/classfile/attribute/LineNumberTableAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -43,6 +43,20 @@ public class LineNumberTableAttribute extends Attribute
 
 
     /**
+     * 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.
      */
diff --git a/src/proguard/classfile/attribute/LocalVariableInfo.java b/src/proguard/classfile/attribute/LocalVariableInfo.java
index d3f5840..03bf668 100644
--- a/src/proguard/classfile/attribute/LocalVariableInfo.java
+++ b/src/proguard/classfile/attribute/LocalVariableInfo.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/LocalVariableTableAttribute.java b/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
index 3aaea6e..445b15f 100644
--- a/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
+++ b/src/proguard/classfile/attribute/LocalVariableTableAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -42,6 +42,20 @@ public class LocalVariableTableAttribute extends Attribute
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/LocalVariableTypeInfo.java b/src/proguard/classfile/attribute/LocalVariableTypeInfo.java
index 9c3248c..3f9a960 100644
--- a/src/proguard/classfile/attribute/LocalVariableTypeInfo.java
+++ b/src/proguard/classfile/attribute/LocalVariableTypeInfo.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java b/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
index 9e3bdaf..f037d2a 100644
--- a/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
+++ b/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -42,6 +42,20 @@ public class LocalVariableTypeTableAttribute extends Attribute
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/SignatureAttribute.java b/src/proguard/classfile/attribute/SignatureAttribute.java
index 9f7565c..71844f3 100644
--- a/src/proguard/classfile/attribute/SignatureAttribute.java
+++ b/src/proguard/classfile/attribute/SignatureAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -51,6 +51,18 @@ public class SignatureAttribute extends Attribute
 
 
     /**
+     * Creates an initialized SignatureAttribute.
+     */
+    public SignatureAttribute(int u2attributeNameIndex,
+                              int u2signatureIndex)
+    {
+        super(u2attributeNameIndex);
+
+        this.u2signatureIndex = u2signatureIndex;
+    }
+
+
+    /**
      * Lets the Clazz objects referenced in the signature string accept the
      * given visitor.
      */
diff --git a/src/proguard/classfile/attribute/SourceDirAttribute.java b/src/proguard/classfile/attribute/SourceDirAttribute.java
index 80c90bc..bdad238 100644
--- a/src/proguard/classfile/attribute/SourceDirAttribute.java
+++ b/src/proguard/classfile/attribute/SourceDirAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -41,6 +41,18 @@ public class SourceDirAttribute extends Attribute
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/SourceFileAttribute.java b/src/proguard/classfile/attribute/SourceFileAttribute.java
index 702a3f9..876eb60 100644
--- a/src/proguard/classfile/attribute/SourceFileAttribute.java
+++ b/src/proguard/classfile/attribute/SourceFileAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -41,6 +41,18 @@ public class SourceFileAttribute extends Attribute
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/SyntheticAttribute.java b/src/proguard/classfile/attribute/SyntheticAttribute.java
index 0e7444c..af9fc44 100644
--- a/src/proguard/classfile/attribute/SyntheticAttribute.java
+++ b/src/proguard/classfile/attribute/SyntheticAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -38,6 +38,15 @@ public class SyntheticAttribute extends Attribute
     }
 
 
+    /**
+     * Creates an initialized SyntheticAttribute.
+     */
+    public SyntheticAttribute(int u2attributeNameIndex)
+    {
+        super(u2attributeNameIndex);
+    }
+
+
     // Implementations for Attribute.
 
     public void accept(Clazz clazz, AttributeVisitor attributeVisitor)
diff --git a/src/proguard/classfile/attribute/UnknownAttribute.java b/src/proguard/classfile/attribute/UnknownAttribute.java
index b6f2a61..1c9a665 100644
--- a/src/proguard/classfile/attribute/UnknownAttribute.java
+++ b/src/proguard/classfile/attribute/UnknownAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -44,6 +44,20 @@ public class UnknownAttribute extends Attribute
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/annotation/Annotation.java b/src/proguard/classfile/attribute/annotation/Annotation.java
index d168b14..aa48e4d 100644
--- a/src/proguard/classfile/attribute/annotation/Annotation.java
+++ b/src/proguard/classfile/attribute/annotation/Annotation.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -51,6 +51,27 @@ public class Annotation implements VisitorAccepter
 
 
     /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java b/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java
index 9c8dc69..0bb2302 100644
--- a/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/AnnotationDefaultAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -44,6 +44,18 @@ public class AnnotationDefaultAttribute extends Attribute
 
 
     /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java b/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java
index 2ec0f48..59f888d 100644
--- a/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/AnnotationElementValue.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -42,6 +42,18 @@ public class AnnotationElementValue extends ElementValue
 
 
     /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java
index 68eb42d..2bd564d 100644
--- a/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -35,12 +35,29 @@ public abstract class AnnotationsAttribute extends Attribute
     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)
diff --git a/src/proguard/classfile/attribute/annotation/ArrayElementValue.java b/src/proguard/classfile/attribute/annotation/ArrayElementValue.java
index d63b4db..8bc9148 100644
--- a/src/proguard/classfile/attribute/annotation/ArrayElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ArrayElementValue.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -42,6 +42,20 @@ public class ArrayElementValue extends ElementValue
     }
 
 
+    /**
+     * Creates an initialized ArrayElementValue.
+     */
+    public ArrayElementValue(int            u2elementNameIndex,
+                             int            u2elementValuesCount,
+                             ElementValue[] elementValues)
+    {
+        super(u2elementNameIndex);
+
+        this.u2elementValuesCount = u2elementValuesCount;
+        this.elementValues        = elementValues;
+    }
+
+
     // Implementations for ElementValue.
 
     public int getTag()
diff --git a/src/proguard/classfile/attribute/annotation/ClassElementValue.java b/src/proguard/classfile/attribute/annotation/ClassElementValue.java
index 95ee572..91838b5 100644
--- a/src/proguard/classfile/attribute/annotation/ClassElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ClassElementValue.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -51,6 +51,18 @@ public class ClassElementValue extends ElementValue
 
 
     /**
+     * Creates an initialized ClassElementValue.
+     */
+    public ClassElementValue(int u2elementNameIndex,
+                             int u2classInfoIndex)
+    {
+        super(u2elementNameIndex);
+
+        this.u2classInfoIndex = u2classInfoIndex;
+    }
+
+
+    /**
      * Applies the given visitor to all referenced classes.
      */
     public void referencedClassesAccept(ClassVisitor classVisitor)
diff --git a/src/proguard/classfile/attribute/annotation/ConstantElementValue.java b/src/proguard/classfile/attribute/annotation/ConstantElementValue.java
index f31c244..4b54ad7 100644
--- a/src/proguard/classfile/attribute/annotation/ConstantElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ConstantElementValue.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -31,7 +31,7 @@ import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
 public class ConstantElementValue extends ElementValue
 {
     public final int u1tag;
-    public int u2constantValueIndex;
+    public       int u2constantValueIndex;
 
 
     /**
@@ -43,6 +43,20 @@ public class ConstantElementValue extends ElementValue
     }
 
 
+    /**
+     * Creates an initialized ConstantElementValue.
+     */
+    public ConstantElementValue(int u1tag,
+                                int u2elementNameIndex,
+                                int u2constantValueIndex)
+    {
+        super(u2elementNameIndex);
+
+        this.u1tag                = u1tag;
+        this.u2constantValueIndex = u2constantValueIndex;
+    }
+
+
     // Implementations for ElementValue.
 
     public int getTag()
diff --git a/src/proguard/classfile/attribute/annotation/ElementValue.java b/src/proguard/classfile/attribute/annotation/ElementValue.java
index 938d5a5..543f2d0 100644
--- a/src/proguard/classfile/attribute/annotation/ElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/ElementValue.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -60,6 +60,23 @@ public abstract class ElementValue implements VisitorAccepter
 
 
     /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java b/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java
index ae3dc2c..70c180a 100644
--- a/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java
+++ b/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -53,6 +53,20 @@ public class EnumConstantElementValue extends ElementValue
 
 
     /**
+     * Creates an initialized EnumConstantElementValue.
+     */
+    public EnumConstantElementValue(int u2elementNameIndex,
+                                    int u2typeNameIndex,
+                                    int u2constantNameIndex)
+    {
+        super(u2elementNameIndex);
+
+        this.u2typeNameIndex     = u2typeNameIndex;
+        this.u2constantNameIndex = u2constantNameIndex;
+    }
+
+
+    /**
      * Applies the given visitor to all referenced classes.
      */
     public void referencedClassesAccept(ClassVisitor classVisitor)
diff --git a/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java
index d3a6f14..672478a 100644
--- a/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -36,12 +36,31 @@ public abstract class ParameterAnnotationsAttribute extends Attribute
     public Annotation[][] parameterAnnotations;
 
 
+    /**
+     * Creates an uninitialized ParameterAnnotationsAttribute.
+     */
     protected ParameterAnnotationsAttribute()
     {
     }
 
 
     /**
+     * Creates an initialized ParameterAnnotationsAttribute.
+     */
+    protected ParameterAnnotationsAttribute(int            u2attributeNameIndex,
+                                            int            u2parametersCount,
+                                            int[]          u2parameterAnnotationsCount,
+                                            Annotation[][] parameterAnnotations)
+    {
+        super(u2attributeNameIndex);
+
+        this.u2parametersCount           = u2parametersCount;
+        this.u2parameterAnnotationsCount = u2parameterAnnotationsCount;
+        this.parameterAnnotations        = parameterAnnotations;
+    }
+
+
+    /**
      * Applies the given visitor to all annotations.
      */
     public void annotationsAccept(Clazz clazz, Method method, AnnotationVisitor annotationVisitor)
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java
index 2d5671e..5948cc1 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -38,7 +38,18 @@ public class RuntimeInvisibleAnnotationsAttribute extends AnnotationsAttribute
     }
 
 
-    // Implementations for Attribute.
+    /**
+     * 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)
     {
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java
index b25af56..55deb6b 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleParameterAnnotationsAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -38,6 +38,21 @@ public class RuntimeInvisibleParameterAnnotationsAttribute extends ParameterAnno
     }
 
 
+    /**
+     * Creates an initialized RuntimeInvisibleParameterAnnotationsAttribute.
+     */
+    public RuntimeInvisibleParameterAnnotationsAttribute(int            u2attributeNameIndex,
+                                                         int            u2parametersCount,
+                                                         int[]          u2parameterAnnotationsCount,
+                                                         Annotation[][] parameterAnnotations)
+    {
+        super(u2attributeNameIndex,
+              u2parametersCount,
+              u2parameterAnnotationsCount,
+              parameterAnnotations);
+    }
+
+
     // Implementations for Attribute.
 
     public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java
index 2c63647..9141f3a 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -38,6 +38,17 @@ public class RuntimeVisibleAnnotationsAttribute extends AnnotationsAttribute
     }
 
 
+    /**
+     * 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)
diff --git a/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java
index 5ddcbc7..d2c6b4d 100644
--- a/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java
+++ b/src/proguard/classfile/attribute/annotation/RuntimeVisibleParameterAnnotationsAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -38,6 +38,21 @@ public class RuntimeVisibleParameterAnnotationsAttribute extends ParameterAnnota
     }
 
 
+    /**
+     * Creates an initialized RuntimeVisibleParameterAnnotationsAttribute.
+     */
+    public RuntimeVisibleParameterAnnotationsAttribute(int            u2attributeNameIndex,
+                                                       int            u2parametersCount,
+                                                       int[]          u2parameterAnnotationsCount,
+                                                       Annotation[][] parameterAnnotations)
+    {
+        super(u2attributeNameIndex,
+              u2parametersCount,
+              u2parameterAnnotationsCount,
+              parameterAnnotations);
+    }
+
+
     // Implementations for Attribute.
 
     public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java
index f63cae1..412ebd7 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java
index 626e185..388fd0d 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java
index 6bc8f7f..d521b34 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotationToMemberVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java
index 6f0a9ae..bf11340 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotationTypeFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java
index 5634b49..73101f9 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java
index fe31534..0d5540a 100644
--- a/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java
+++ b/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/DoubleType.java b/src/proguard/classfile/attribute/preverification/DoubleType.java
index 5df3fec..7f151d4 100644
--- a/src/proguard/classfile/attribute/preverification/DoubleType.java
+++ b/src/proguard/classfile/attribute/preverification/DoubleType.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/FloatType.java b/src/proguard/classfile/attribute/preverification/FloatType.java
index 8d985f9..2d79cab 100644
--- a/src/proguard/classfile/attribute/preverification/FloatType.java
+++ b/src/proguard/classfile/attribute/preverification/FloatType.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/FullFrame.java b/src/proguard/classfile/attribute/preverification/FullFrame.java
index 41763b2..a4cc663 100644
--- a/src/proguard/classfile/attribute/preverification/FullFrame.java
+++ b/src/proguard/classfile/attribute/preverification/FullFrame.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -189,7 +189,7 @@ public class FullFrame extends StackMapFrame
         }
 
         buffer.append(", Stack: ");
-        
+
         for (int index = 0; index < stackCount; index++)
         {
             buffer = buffer.append('[')
diff --git a/src/proguard/classfile/attribute/preverification/IntegerType.java b/src/proguard/classfile/attribute/preverification/IntegerType.java
index 0526be4..fc72343 100644
--- a/src/proguard/classfile/attribute/preverification/IntegerType.java
+++ b/src/proguard/classfile/attribute/preverification/IntegerType.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/LessZeroFrame.java b/src/proguard/classfile/attribute/preverification/LessZeroFrame.java
index cafd31a..b60c3ca 100644
--- a/src/proguard/classfile/attribute/preverification/LessZeroFrame.java
+++ b/src/proguard/classfile/attribute/preverification/LessZeroFrame.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/LongType.java b/src/proguard/classfile/attribute/preverification/LongType.java
index 7498dbb..2142d68 100644
--- a/src/proguard/classfile/attribute/preverification/LongType.java
+++ b/src/proguard/classfile/attribute/preverification/LongType.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java b/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java
index 2f365bc..40af23c 100644
--- a/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java
+++ b/src/proguard/classfile/attribute/preverification/MoreZeroFrame.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -155,7 +155,7 @@ public class MoreZeroFrame extends StackMapFrame
         }
 
         buffer.append(", Stack: (empty)");
-        
+
         return buffer.toString();
     }
 }
diff --git a/src/proguard/classfile/attribute/preverification/NullType.java b/src/proguard/classfile/attribute/preverification/NullType.java
index add3094..a993a0f 100644
--- a/src/proguard/classfile/attribute/preverification/NullType.java
+++ b/src/proguard/classfile/attribute/preverification/NullType.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/ObjectType.java b/src/proguard/classfile/attribute/preverification/ObjectType.java
index 3762465..f414971 100644
--- a/src/proguard/classfile/attribute/preverification/ObjectType.java
+++ b/src/proguard/classfile/attribute/preverification/ObjectType.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/SameOneFrame.java b/src/proguard/classfile/attribute/preverification/SameOneFrame.java
index 6e329be..7b9d215 100644
--- a/src/proguard/classfile/attribute/preverification/SameOneFrame.java
+++ b/src/proguard/classfile/attribute/preverification/SameOneFrame.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/SameZeroFrame.java b/src/proguard/classfile/attribute/preverification/SameZeroFrame.java
index 04d8b79..f51df42 100644
--- a/src/proguard/classfile/attribute/preverification/SameZeroFrame.java
+++ b/src/proguard/classfile/attribute/preverification/SameZeroFrame.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/StackMapAttribute.java b/src/proguard/classfile/attribute/preverification/StackMapAttribute.java
index 805d9f6..1a99d0f 100644
--- a/src/proguard/classfile/attribute/preverification/StackMapAttribute.java
+++ b/src/proguard/classfile/attribute/preverification/StackMapAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/StackMapFrame.java b/src/proguard/classfile/attribute/preverification/StackMapFrame.java
index 2f3fad3..2214ed7 100644
--- a/src/proguard/classfile/attribute/preverification/StackMapFrame.java
+++ b/src/proguard/classfile/attribute/preverification/StackMapFrame.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java b/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java
index 658f155..7818804 100644
--- a/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java
+++ b/src/proguard/classfile/attribute/preverification/StackMapTableAttribute.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/TopType.java b/src/proguard/classfile/attribute/preverification/TopType.java
index ece00ed..c5176e6 100644
--- a/src/proguard/classfile/attribute/preverification/TopType.java
+++ b/src/proguard/classfile/attribute/preverification/TopType.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/UninitializedThisType.java b/src/proguard/classfile/attribute/preverification/UninitializedThisType.java
index 7b5639e..564ac1d 100644
--- a/src/proguard/classfile/attribute/preverification/UninitializedThisType.java
+++ b/src/proguard/classfile/attribute/preverification/UninitializedThisType.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/UninitializedType.java b/src/proguard/classfile/attribute/preverification/UninitializedType.java
index 9e406d6..aa61dd1 100644
--- a/src/proguard/classfile/attribute/preverification/UninitializedType.java
+++ b/src/proguard/classfile/attribute/preverification/UninitializedType.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/VerificationType.java b/src/proguard/classfile/attribute/preverification/VerificationType.java
index c6d546e..a1adc3c 100644
--- a/src/proguard/classfile/attribute/preverification/VerificationType.java
+++ b/src/proguard/classfile/attribute/preverification/VerificationType.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java b/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java
index 200ffb7..1c09367 100644
--- a/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java
+++ b/src/proguard/classfile/attribute/preverification/VerificationTypeFactory.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java b/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java
index 464fa0c..518d4a8 100644
--- a/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java
+++ b/src/proguard/classfile/attribute/preverification/visitor/StackMapFrameVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java b/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java
index 1d1f54f..669a28f 100644
--- a/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java
+++ b/src/proguard/classfile/attribute/preverification/visitor/VerificationTypeVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java b/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java
index 33de5a1..8c327d0 100644
--- a/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/AllAttributeVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java b/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
index fa747ea..d7ad85a 100644
--- a/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
+++ b/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/AttributeVisitor.java b/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
index 2b83db2..d55c4d9 100644
--- a/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/AttributeVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java b/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
index a9d7d11..2717aa7 100644
--- a/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java b/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java
index 835a5ae..0191bbb 100644
--- a/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/InnerClassesInfoVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java b/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java
index a84531a..397b8f2 100644
--- a/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/LineNumberInfoVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java b/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java
index df5770f..57901c9 100644
--- a/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/LocalVariableInfoVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java b/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java
index fccfa46..33a4f25 100644
--- a/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/LocalVariableTypeInfoVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java b/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java
index 44a65ea..a457a85 100644
--- a/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java
+++ b/src/proguard/classfile/attribute/visitor/MultiAttributeVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java b/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
index 0246379..df88bed 100644
--- a/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
+++ b/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/attribute/visitor/StackSizeComputer.java b/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
index e543275..28750ef 100644
--- a/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
+++ b/src/proguard/classfile/attribute/visitor/StackSizeComputer.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -91,6 +91,9 @@ implements   AttributeVisitor,
 
     // Implementations for AttributeVisitor.
 
+    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
     {
 //        DEBUG =
diff --git a/src/proguard/classfile/constant/ClassConstant.java b/src/proguard/classfile/constant/ClassConstant.java
index 33db73f..374affb 100644
--- a/src/proguard/classfile/constant/ClassConstant.java
+++ b/src/proguard/classfile/constant/ClassConstant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/Constant.java b/src/proguard/classfile/constant/Constant.java
index cd9ea2a..11e6177 100644
--- a/src/proguard/classfile/constant/Constant.java
+++ b/src/proguard/classfile/constant/Constant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/DoubleConstant.java b/src/proguard/classfile/constant/DoubleConstant.java
index 1f496b0..48cff3b 100644
--- a/src/proguard/classfile/constant/DoubleConstant.java
+++ b/src/proguard/classfile/constant/DoubleConstant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/FieldrefConstant.java b/src/proguard/classfile/constant/FieldrefConstant.java
index 0e73149..fd7b0ba 100644
--- a/src/proguard/classfile/constant/FieldrefConstant.java
+++ b/src/proguard/classfile/constant/FieldrefConstant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/FloatConstant.java b/src/proguard/classfile/constant/FloatConstant.java
index be2318a..399f0f9 100644
--- a/src/proguard/classfile/constant/FloatConstant.java
+++ b/src/proguard/classfile/constant/FloatConstant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/IntegerConstant.java b/src/proguard/classfile/constant/IntegerConstant.java
index 23fcfc3..760c856 100644
--- a/src/proguard/classfile/constant/IntegerConstant.java
+++ b/src/proguard/classfile/constant/IntegerConstant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/InterfaceMethodrefConstant.java b/src/proguard/classfile/constant/InterfaceMethodrefConstant.java
index 046fe9a..2bac149 100644
--- a/src/proguard/classfile/constant/InterfaceMethodrefConstant.java
+++ b/src/proguard/classfile/constant/InterfaceMethodrefConstant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/LongConstant.java b/src/proguard/classfile/constant/LongConstant.java
index 2a50142..2a8eb29 100644
--- a/src/proguard/classfile/constant/LongConstant.java
+++ b/src/proguard/classfile/constant/LongConstant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/MethodrefConstant.java b/src/proguard/classfile/constant/MethodrefConstant.java
index 9d71986..82cce97 100644
--- a/src/proguard/classfile/constant/MethodrefConstant.java
+++ b/src/proguard/classfile/constant/MethodrefConstant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/NameAndTypeConstant.java b/src/proguard/classfile/constant/NameAndTypeConstant.java
index 15f89a1..c224f36 100644
--- a/src/proguard/classfile/constant/NameAndTypeConstant.java
+++ b/src/proguard/classfile/constant/NameAndTypeConstant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/RefConstant.java b/src/proguard/classfile/constant/RefConstant.java
index 116feb9..c6179ef 100644
--- a/src/proguard/classfile/constant/RefConstant.java
+++ b/src/proguard/classfile/constant/RefConstant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/StringConstant.java b/src/proguard/classfile/constant/StringConstant.java
index 2c67715..0a4b3a9 100644
--- a/src/proguard/classfile/constant/StringConstant.java
+++ b/src/proguard/classfile/constant/StringConstant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/Utf8Constant.java b/src/proguard/classfile/constant/Utf8Constant.java
index 6d4fb86..ad677c7 100644
--- a/src/proguard/classfile/constant/Utf8Constant.java
+++ b/src/proguard/classfile/constant/Utf8Constant.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/constant/visitor/AllConstantVisitor.java b/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
index 01c5487..3530660 100644
--- a/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
+++ b/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/visitor/ConstantVisitor.java b/src/proguard/classfile/constant/visitor/ConstantVisitor.java
index 539c24d..6c7a851 100644
--- a/src/proguard/classfile/constant/visitor/ConstantVisitor.java
+++ b/src/proguard/classfile/constant/visitor/ConstantVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ExceptionAdder.java b/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
similarity index 51%
copy from src/proguard/classfile/editor/ExceptionAdder.java
copy to src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
index 91e9a22..fc823c8 100644
--- a/src/proguard/classfile/editor/ExceptionAdder.java
+++ b/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,40 +18,42 @@
  * with 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;
+package proguard.classfile.constant.visitor;
 
 import proguard.classfile.*;
-import proguard.classfile.attribute.ExceptionsAttribute;
+import proguard.classfile.editor.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
 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.
+ * 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 ExceptionAdder
+public class ExceptClassConstantFilter
 extends      SimplifiedVisitor
 implements   ConstantVisitor
 {
-    private final ExceptionsAttribute targetExceptionsAttribute;
-
-    private final ConstantAdder    constantAdder    = new ConstantAdder();
-    private final ExceptionsEditor exceptionsEditor = new ExceptionsEditor();
+    private final String           exceptClassName;
+    private final ConstantVisitor constantVisitor;
 
 
     /**
-     * Creates a new MemberAdder that will copy methods into the given target
-     * class.
+     * Creates a new ClassNameFilter.
+     * @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 ExceptionAdder(ProgramClass        targetClass,
-                        ExceptionsAttribute targetExceptionsAttribute)
+        public ExceptClassConstantFilter(String          exceptClassName,
+                                         ConstantVisitor constantVisitor)
     {
-        this.targetExceptionsAttribute = targetExceptionsAttribute;
-
-        constantAdder.setTargetClass(targetClass);
+            this.exceptClassName = exceptClassName;
+            this.constantVisitor = constantVisitor;
     }
 
 
@@ -59,9 +61,9 @@ implements   ConstantVisitor
 
     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
     {
-        constantAdder.visitClassConstant(clazz, classConstant);
-
-        exceptionsEditor.addException(targetExceptionsAttribute,
-                                      constantAdder.getConstantIndex());
+        if (!classConstant.getName(clazz).equals(exceptClassName))
+        {
+            constantVisitor.visitClassConstant(clazz, classConstant);
+        }
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/AccessFixer.java b/src/proguard/classfile/editor/AccessFixer.java
index 28d2ff4..786e241 100644
--- a/src/proguard/classfile/editor/AccessFixer.java
+++ b/src/proguard/classfile/editor/AccessFixer.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -38,7 +38,10 @@ implements   ConstantVisitor,
              ClassVisitor,
              MemberVisitor
 {
+    private MyReferencedClassFinder referencedClassFinder = new MyReferencedClassFinder();
+
     private Clazz referencingClass;
+    private Clazz referencedClass;
 
 
     // Implementations for ConstantVisitor.
@@ -49,6 +52,7 @@ implements   ConstantVisitor,
     public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
     {
         referencingClass = clazz;
+        referencedClass  = stringConstant.referencedClass;
 
         // Make sure the access flags of the referenced class or class member,
         // if any, are acceptable.
@@ -61,7 +65,12 @@ implements   ConstantVisitor,
     {
         referencingClass = clazz;
 
-        // Make sure the access flags of the referenced class member are acceptable.
+        // Remember the specified class, since it might be different from
+        // the referenced class that acutally contains the class member.
+        clazz.constantPoolEntryAccept(refConstant.u2classIndex, referencedClassFinder);
+
+        // Make sure the access flags of the referenced class member are
+        // acceptable.
         refConstant.referencedMemberAccept(this);
     }
 
@@ -88,9 +97,7 @@ implements   ConstantVisitor,
         // Compute the required access level.
         Clazz referencingClass = this.referencingClass;
         int requiredAccessLevel =
-            programClass.equals(this.referencingClass)    ? AccessUtil.PRIVATE         :
             inSamePackage(programClass, referencingClass) ? AccessUtil.PACKAGE_VISIBLE :
-            referencingClass.extends_(programClass)       ? AccessUtil.PROTECTED       :
                                                             AccessUtil.PUBLIC;
 
         // Fix the class access flags if necessary.
@@ -117,7 +124,10 @@ implements   ConstantVisitor,
         int requiredAccessLevel =
             programClass.equals(referencingClass)         ? AccessUtil.PRIVATE         :
             inSamePackage(programClass, referencingClass) ? AccessUtil.PACKAGE_VISIBLE :
+            referencedClass.extends_(referencingClass) &&
+            referencingClass.extends_(programClass)       ? AccessUtil.PROTECTED       :
                                                             AccessUtil.PUBLIC;
+
         // Fix the class member access flags if necessary.
         if (currentAccessLevel < requiredAccessLevel)
         {
@@ -128,6 +138,22 @@ implements   ConstantVisitor,
     }
 
 
+    /**
+     * This ConstantVisitor returns the referenced class of the class constant
+     * that it visits.
+     */
+    private class MyReferencedClassFinder
+    extends       SimplifiedVisitor
+    implements    ConstantVisitor
+    {
+        // Implementations for ConstantVisitor.
+        public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+        {
+            referencedClass = classConstant.referencedClass;
+        }
+    }
+
+
     // Small utility methods.
 
     private boolean inSamePackage(ProgramClass class1, Clazz class2)
diff --git a/src/proguard/classfile/editor/AnnotationAdder.java b/src/proguard/classfile/editor/AnnotationAdder.java
new file mode 100644
index 0000000..92ae382
--- /dev/null
+++ b/src/proguard/classfile/editor/AnnotationAdder.java
@@ -0,0 +1,116 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with 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 or target 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 ConstantAdder              constantAdder;
+    private final AnnotationsAttributeEditor annotationsAttributeEditor;
+
+
+    /**
+     * 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;
+
+        constantAdder              = new ConstantAdder(targetClass);
+        annotationsAttributeEditor = null;
+    }
+
+
+    /**
+     * Creates a new AnnotationAdder that will copy annotations into the given
+     * target annotation.
+     */
+    public AnnotationAdder(ProgramClass         targetClass,
+                           AnnotationsAttribute targetAnnotationsAttribute)
+    {
+        this.targetClass                  = targetClass;
+        this.targetAnnotationElementValue = null;
+
+        constantAdder              = new ConstantAdder(targetClass);
+        annotationsAttributeEditor = new AnnotationsAttributeEditor(targetAnnotationsAttribute);
+    }
+
+
+    // 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)
+    {
+        // TODO: Handle parameter annotations.
+    }
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/AnnotationsAttributeEditor.java b/src/proguard/classfile/editor/AnnotationsAttributeEditor.java
new file mode 100644
index 0000000..a579ff7
--- /dev/null
+++ b/src/proguard/classfile/editor/AnnotationsAttributeEditor.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with 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/src/proguard/classfile/editor/AttributeAdder.java b/src/proguard/classfile/editor/AttributeAdder.java
index 805e710..004019f 100644
--- a/src/proguard/classfile/editor/AttributeAdder.java
+++ b/src/proguard/classfile/editor/AttributeAdder.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -25,6 +25,7 @@ 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;
 
 /**
  * This AttributeVisitor adds all attributes that it visits to the given
@@ -33,26 +34,32 @@ import proguard.classfile.attribute.visitor.AttributeVisitor;
  * @author Eric Lafortune
  */
 public class AttributeAdder
+extends      SimplifiedVisitor
 implements   AttributeVisitor
 {
-    private static final int[] EMPTY_INTS = new int[0];
+    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 final ProgramClass  targetClass;
     private final ProgramMember targetMember;
-    private final Attribute     targetAttribute;
+    private final CodeAttribute targetCodeAttribute;
+    private final boolean       replaceAttributes;
 
-    private final ConstantAdder    constantAdder    = new ConstantAdder();
-    private final AttributesEditor attributesEditor = new AttributesEditor();
+    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)
+    public AttributeAdder(ProgramClass targetClass,
+                          boolean      replaceAttributes)
     {
-        this(targetClass, null, null);
+        this(targetClass, null, null, replaceAttributes);
     }
 
 
@@ -61,9 +68,10 @@ implements   AttributeVisitor
      * target class member.
      */
     public AttributeAdder(ProgramClass  targetClass,
-                          ProgramMember targetMember)
+                          ProgramMember targetMember,
+                          boolean       replaceAttributes)
     {
-        this(targetClass, targetMember, null);
+        this(targetClass, targetMember, null, replaceAttributes);
     }
 
 
@@ -73,138 +81,211 @@ implements   AttributeVisitor
      */
     public AttributeAdder(ProgramClass  targetClass,
                           ProgramMember targetMember,
-                          Attribute     targetAttribute)
+                          CodeAttribute targetCodeAttribute,
+                          boolean       replaceAttributes)
     {
-        this.targetClass     = targetClass;
-        this.targetMember    = targetMember;
-        this.targetAttribute = targetAttribute;
+        this.targetClass         = targetClass;
+        this.targetMember        = targetMember;
+        this.targetCodeAttribute = targetCodeAttribute;
+        this.replaceAttributes   = replaceAttributes;
 
-        constantAdder.setTargetClass(targetClass);
+        constantAdder    = new ConstantAdder(targetClass);
+        attributesEditor = new AttributesEditor(targetClass,
+                                                targetMember,
+                                                targetCodeAttribute,
+                                                replaceAttributes);
     }
 
 
-    // Implementations for AttibuteVisitor.
+    // Implementations for AttributeVisitor.
 
     public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
     {
-        // TODO: Implement method.
+        // 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)
     {
-        // TODO: Implement method.
+        // 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)
     {
-        // TODO: Implement method.
+        // 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)
     {
         // TODO: Implement method.
+        // Note that the attribute may already be present.
+//        // Create a copy of the attribute.
+//        InnerClassesAttribute newInnerClassesAttribute =
+//            new InnerClassesAttribute(constantAdder.addConstant(clazz, innerClassesAttribute.u2attributeNameIndex),
+//                                      0,
+//                                      null);
+//
+//        // Add it to the target class.
+//        attributesEditor.addClassAttribute(newInnerClassesAttribute);
     }
 
 
     public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
     {
-        // TODO: Implement method.
-    }
+        // 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;
 
-    public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
-    {
-        // TODO: Implement method.
+        // Add it to the target class.
+        attributesEditor.addAttribute(newEnclosingMethodAttribute);
     }
 
 
-    public void visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute)
+    public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
     {
-        // TODO: Implement method.
-    }
-
+        // Create a copy of the attribute.
+        DeprecatedAttribute newDeprecatedAttribute =
+            new DeprecatedAttribute(constantAdder.addConstant(clazz, deprecatedAttribute.u2attributeNameIndex));
 
-    public void visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute)
-    {
-        // TODO: Implement method.
+        // Add it to the target.
+        attributesEditor.addAttribute(newDeprecatedAttribute);
     }
 
 
     public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
     {
-        // TODO: Implement method.
-    }
-
+        // Create a copy of the attribute.
+        SyntheticAttribute newSyntheticAttribute =
+            new SyntheticAttribute(constantAdder.addConstant(clazz, syntheticAttribute.u2attributeNameIndex));
 
-    public void visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute)
-    {
-        // TODO: Implement method.
-    }
-
-
-    public void visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute)
-    {
-        // TODO: Implement method.
+        // Add it to the target.
+        attributesEditor.addAttribute(newSyntheticAttribute);
     }
 
 
     public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
     {
-        // TODO: Implement method.
-    }
+        // Create a copy of the attribute.
+        SignatureAttribute newSignatureAttribute =
+            new SignatureAttribute(constantAdder.addConstant(clazz, signatureAttribute.u2attributeNameIndex),
+                                   constantAdder.addConstant(clazz, signatureAttribute.u2signatureIndex));
 
+        newSignatureAttribute.referencedClasses = signatureAttribute.referencedClasses;
 
-    public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute signatureAttribute)
-    {
-        // TODO: Implement method.
-    }
-
-
-    public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute)
-    {
-        // TODO: Implement method.
+        // Add it to the target.
+        attributesEditor.addAttribute(newSignatureAttribute);
     }
 
 
     public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
     {
-        // TODO: Implement method.
+        // 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 visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
     {
         // Create a new exceptions attribute.
-        ExceptionsAttribute newExceptionsAttribute = new ExceptionsAttribute();
-
-        // Make sure the name is set in the constant pool.
-        clazz.constantPoolEntryAccept(exceptionsAttribute.u2attributeNameIndex,
-                                      constantAdder);
-
-        newExceptionsAttribute.u2attributeNameIndex = constantAdder.getConstantIndex();
-
-        // Start with an empty exception index table.
-        newExceptionsAttribute.u2exceptionIndexTableLength = 0;
-        newExceptionsAttribute.u2exceptionIndexTable       = EMPTY_INTS;
+        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 the completed exceptions attribute.
-        attributesEditor.addAttribute(targetClass,
-                                      (ProgramMethod)targetMember,
-                                      newExceptionsAttribute);
+        // Add it to the target method.
+        attributesEditor.addAttribute(newExceptionsAttribute);
     }
 
 
     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
     {
-        // TODO: Implement method.
+        // 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));
+        // Add the exceptions.
+        codeAttribute.exceptionsAccept(clazz,
+                                       method,
+                                       new ExceptionInfoAdder(targetClass,
+                                                              codeAttributeComposer));
+
+        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);
     }
 
 
@@ -240,37 +321,37 @@ implements   AttributeVisitor
 
     public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
     {
-        // TODO: Implement method.
-    }
-
-
-    public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
-    {
-        // TODO: Implement method.
-    }
+        // 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));
 
-    public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
-    {
-        // TODO: Implement method.
+        // Add it to the target.
+        attributesEditor.addAttribute(newAnnotationsAttribute);
     }
 
 
     public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
     {
-        // TODO: Implement method.
-    }
+        // 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));
 
-    public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
-    {
-        // TODO: Implement method.
-    }
-
-
-    public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
-    {
-        // TODO: Implement method.
+        // Add it to the target.
+        attributesEditor.addAttribute(newAnnotationsAttribute);
     }
 
 
@@ -288,6 +369,18 @@ implements   AttributeVisitor
 
     public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
     {
-        // TODO: Implement method.
+        // 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/src/proguard/classfile/editor/AttributeSorter.java b/src/proguard/classfile/editor/AttributeSorter.java
index 0e24a75..4e24d5a 100644
--- a/src/proguard/classfile/editor/AttributeSorter.java
+++ b/src/proguard/classfile/editor/AttributeSorter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/editor/AttributesEditor.java b/src/proguard/classfile/editor/AttributesEditor.java
index 3eb789c..efd681e 100644
--- a/src/proguard/classfile/editor/AttributesEditor.java
+++ b/src/proguard/classfile/editor/AttributesEditor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -33,202 +33,182 @@ import proguard.classfile.attribute.*;
  */
 public class AttributesEditor
 {
-    /**
-     * Adds the given attribute to the given class.
-     */
-    public void addAttribute(ProgramClass programClass,
-                             Attribute    attribute)
-    {
-        // Try to replace an existing attribute.
-        if (!replaceAttribute(programClass,
-                              programClass.u2attributesCount,
-                              programClass.attributes,
-                              attribute))
-        {
-            // Otherwise append the attribute.
-            programClass.attributes =
-                appendAttribute(programClass.u2attributesCount,
-                                programClass.attributes,
-                                attribute);
-
-            programClass.u2attributesCount++;
-        }
-    }
+    private final ProgramClass  targetClass;
+    private final ProgramMember targetMember;
+    private final CodeAttribute targetAttribute;
+    private final boolean       replaceAttributes;
 
 
     /**
-     * Adds the given attribute to the given field.
+     * Creates a new AttributeAdder that will edit attributes in the given
+     * target class.
      */
-    public void addAttribute(ProgramClass programClass,
-                             ProgramField programField,
-                             Attribute    attribute)
+    public AttributesEditor(ProgramClass targetClass,
+                            boolean      replaceAttributes)
     {
-        // Try to replace an existing attribute.
-        if (!replaceAttribute(programClass,
-                              programField.u2attributesCount,
-                              programField.attributes,
-                              attribute))
-        {
-            // Otherwise append the attribute.
-            programField.attributes =
-                appendAttribute(programField.u2attributesCount,
-                                programField.attributes,
-                                attribute);
-
-            programField.u2attributesCount++;
-        }
+        this(targetClass, null, null, replaceAttributes);
     }
 
 
     /**
-     * Adds the given attribute to the given method.
+     * Creates a new AttributeAdder that will edit attributes in the given
+     * target class member.
      */
-    public void addAttribute(ProgramClass  programClass,
-                             ProgramMethod programMethod,
-                             Attribute     attribute)
+    public AttributesEditor(ProgramClass  targetClass,
+                            ProgramMember targetMember,
+                            boolean       replaceAttributes)
     {
-        // Try to replace an existing attribute.
-        if (!replaceAttribute(programClass,
-                              programMethod.u2attributesCount,
-                              programMethod.attributes,
-                              attribute))
-        {
-            // Otherwise append the attribute.
-            programMethod.attributes =
-                appendAttribute(programMethod.u2attributesCount,
-                                programMethod.attributes,
-                                attribute);
-
-            programMethod.u2attributesCount++;
-        }
+        this(targetClass, targetMember, null, replaceAttributes);
     }
 
 
     /**
-     * Adds the given attribute to the given code attribute.
+     * Creates a new AttributeAdder that will edit attributes in the given
+     * target code attribute.
      */
-    public void addAttribute(ProgramClass  programClass,
-                             ProgramMethod programMethod,
-                             CodeAttribute codeAttribute,
-                             Attribute     attribute)
+    public AttributesEditor(ProgramClass  targetClass,
+                            ProgramMember targetMember,
+                            CodeAttribute targetAttribute,
+                            boolean       replaceAttributes)
     {
-        // Try to replace an existing attribute.
-        if (!replaceAttribute(programClass,
-                              codeAttribute.u2attributesCount,
-                              codeAttribute.attributes,
-                              attribute))
-        {
-            // Otherwise append the attribute.
-            codeAttribute.attributes =
-                appendAttribute(codeAttribute.u2attributesCount,
-                                codeAttribute.attributes,
-                                attribute);
-
-            codeAttribute.u2attributesCount++;
-        }
+        this.targetClass       = targetClass;
+        this.targetMember      = targetMember;
+        this.targetAttribute   = targetAttribute;
+        this.replaceAttributes = replaceAttributes;
     }
 
 
     /**
-     * Deletes the given attribute from the given class.
+     * Adds the given attribute to the target.
      */
-    public void deleteAttribute(ProgramClass programClass,
-                                String       attributeName)
+    public void addAttribute(Attribute attribute)
     {
-        programClass.u2attributesCount =
-            deleteAttribute(programClass,
-                            programClass.u2attributesCount,
-                            programClass.attributes,
-                            attributeName);
-    }
-
+        // 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);
 
-    /**
-     * Deletes the given attribute from the given field.
-     */
-    public void deleteAttribute(ProgramClass programClass,
-                                ProgramField programField,
-                                String       attributeName)
-    {
-        programField.u2attributesCount =
-            deleteAttribute(programClass,
-                            programField.u2attributesCount,
-                            programField.attributes,
-                            attributeName);
-    }
+                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);
 
-    /**
-     * Deletes the given attribute from the given method.
-     */
-    public void deleteAttribute(ProgramClass  programClass,
-                                ProgramMethod programMethod,
-                                String        attributeName)
-    {
-        programMethod.u2attributesCount =
-            deleteAttribute(programClass,
-                            programMethod.u2attributesCount,
-                            programMethod.attributes,
-                            attributeName);
+                targetClass.u2attributesCount++;
+            }
+        }
     }
 
 
     /**
-     * Deletes the given attribute from the given code attribute.
+     * Deletes the specified attribute from the target.
      */
-    public void deleteAttribute(ProgramClass  programClass,
-                                ProgramMethod programMethod,
-                                CodeAttribute codeAttribute,
-                                String        attributeName)
+    public void deleteAttribute(String attributeName)
     {
-        codeAttribute.u2attributesCount =
-            deleteAttribute(programClass,
-                            codeAttribute.u2attributesCount,
-                            codeAttribute.attributes,
-                            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 put the given attribute in place of an existing attribute of
-     * the same type.
+     * Tries put the given attribute in place of an existing attribute of the
+     * same name, returning whether it was present.
      */
-    private boolean replaceAttribute(Clazz       clazz,
-                                     int         attributesCount,
+    private boolean replaceAttribute(int         attributesCount,
                                      Attribute[] attributes,
                                      Attribute   attribute)
     {
-        String attributeName = attribute.getAttributeName(clazz);
-
-        for (int index = 0; index < attributesCount; index++)
+        // Find the attribute with the same name.
+        int index = findAttribute(attributesCount,
+                                  attributes,
+                                  attribute.getAttributeName(targetClass));
+        if (index < 0)
         {
-            if (attributes[index].getAttributeName(clazz).equals(attributeName))
-            {
-                attributes[index] = attribute;
-                return true;
-            }
+            return false;
         }
 
-        return false;
+        attributes[index] = attribute;
+
+        return true;
     }
 
 
     /**
-     * Appends the given attribute to the given array of attributes, creating
-     * a new array if necessary.
+     * Appends the given attribute to the given array of attributes, creating a
+     * new array if necessary.
      */
-    private Attribute[] appendAttribute(int         attributesCount,
-                                        Attribute[] attributes,
-                                        Attribute   attribute)
+    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);
+            System.arraycopy(attributes, 0,
+                             newAttributes, 0,
+                             attributesCount);
             attributes = newAttributes;
         }
 
@@ -240,31 +220,50 @@ public class AttributesEditor
 
 
     /**
-     * Deletes attributes with the given name, and returns the new number of
-     * attributes.
+     * Deletes the attributes with the given name from the given array of
+     * attributes, returning the new number of attributes.
      */
-    private int deleteAttribute(Clazz       clazz,
-                                int         attributesCount,
+    private int deleteAttribute(int         attributesCount,
                                 Attribute[] attributes,
                                 String      attributeName)
     {
-        int newIndex = 0;
+        // Find the attribute.
+        int index = findAttribute(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 findAttribute(int         attributesCount,
+                              Attribute[] attributes,
+                              String      attributeName)
+    {
         for (int index = 0; index < attributesCount; index++)
         {
-            if (!attributes[index].getAttributeName(clazz).equals(attributeName))
+            if (attributes[index].getAttributeName(targetClass).equals(attributeName))
             {
-                attributes[newIndex++] = attributes[index];
+                return index;
             }
         }
 
-        // Clear the remaining entries in the array.
-        for (int index = newIndex; index < attributesCount; index++)
-        {
-            attributes[index] = null;
-        }
-
-        return newIndex;
+        return -1;
     }
 }
diff --git a/src/proguard/classfile/editor/ClassEditor.java b/src/proguard/classfile/editor/ClassEditor.java
new file mode 100644
index 0000000..9887600
--- /dev/null
+++ b/src/proguard/classfile/editor/ClassEditor.java
@@ -0,0 +1,255 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with 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/src/proguard/classfile/editor/ClassElementSorter.java b/src/proguard/classfile/editor/ClassElementSorter.java
index dccf241..df250f7 100644
--- a/src/proguard/classfile/editor/ClassElementSorter.java
+++ b/src/proguard/classfile/editor/ClassElementSorter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/editor/ClassMemberSorter.java b/src/proguard/classfile/editor/ClassMemberSorter.java
index 483f184..66de832 100644
--- a/src/proguard/classfile/editor/ClassMemberSorter.java
+++ b/src/proguard/classfile/editor/ClassMemberSorter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/editor/ClassReferenceFixer.java b/src/proguard/classfile/editor/ClassReferenceFixer.java
index f32b991..34624f6 100644
--- a/src/proguard/classfile/editor/ClassReferenceFixer.java
+++ b/src/proguard/classfile/editor/ClassReferenceFixer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -53,9 +53,6 @@ implements   ClassVisitor,
     private final boolean ensureUniqueMemberNames;
 
 
-    private final ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor();
-
-
     /**
      * Creates a new ClassReferenceFixer.
      * @param ensureUniqueMemberNames specifies whether class members whose
@@ -104,9 +101,12 @@ implements   ClassVisitor,
 
         if (!descriptor.equals(newDescriptor))
         {
+            ConstantPoolEditor constantPoolEditor =
+                new ConstantPoolEditor(programClass);
+
             // Update the descriptor.
             programField.u2descriptorIndex =
-                constantPoolEditor.addUtf8Constant(programClass, newDescriptor);
+                constantPoolEditor.addUtf8Constant(newDescriptor);
 
             // Update the name, if requested.
             if (ensureUniqueMemberNames)
@@ -114,7 +114,7 @@ implements   ClassVisitor,
                 String name    = programField.getName(programClass);
                 String newName = newUniqueMemberName(name, descriptor);
                 programField.u2nameIndex =
-                    constantPoolEditor.addUtf8Constant(programClass, newName);
+                    constantPoolEditor.addUtf8Constant(newName);
             }
         }
 
@@ -132,9 +132,12 @@ implements   ClassVisitor,
 
         if (!descriptor.equals(newDescriptor))
         {
+            ConstantPoolEditor constantPoolEditor =
+                new ConstantPoolEditor(programClass);
+
             // Update the descriptor.
             programMethod.u2descriptorIndex =
-                constantPoolEditor.addUtf8Constant(programClass, newDescriptor);
+                constantPoolEditor.addUtf8Constant(newDescriptor);
 
             // Update the name, if requested.
             if (ensureUniqueMemberNames)
@@ -142,7 +145,7 @@ implements   ClassVisitor,
                 String name    = programMethod.getName(programClass);
                 String newName = newUniqueMemberName(name, descriptor);
                 programMethod.u2nameIndex =
-                    constantPoolEditor.addUtf8Constant(programClass, newName);
+                    constantPoolEditor.addUtf8Constant(newName);
             }
         }
 
@@ -201,8 +204,7 @@ implements   ClassVisitor,
 
                 // Refer to a new Utf8 entry.
                 stringConstant.u2stringIndex =
-                    constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                       newExternalClassName);
+                    new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newExternalClassName);
             }
         }
     }
@@ -221,13 +223,11 @@ implements   ClassVisitor,
             {
                 // Refer to a new Utf8 entry.
                 classConstant.u2nameIndex =
-                    constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                       newClassName);
+                    new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newClassName);
             }
         }
     }
 
-
     // Implementations for AttributeVisitor.
 
     public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
@@ -271,8 +271,7 @@ implements   ClassVisitor,
         if (!signature.equals(newSignature))
         {
             signatureAttribute.u2signatureIndex =
-                constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                   newSignature);
+                new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature);
         }
     }
 
@@ -313,8 +312,7 @@ implements   ClassVisitor,
             if (index >= 0)
             {
                 innerClassesInfo.u2innerNameIndex =
-                    constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                       newInnerName.substring(index + 1));
+                    new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newInnerName.substring(index + 1));
             }
         }
     }
@@ -333,12 +331,10 @@ implements   ClassVisitor,
         {
             // Refer to a new Utf8 entry.
             localVariableInfo.u2descriptorIndex =
-                constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                   newDescriptor);
+                new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newDescriptor);
         }
     }
 
-
     // Implementations for LocalVariableTypeInfoVisitor.
 
     public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
@@ -351,12 +347,10 @@ implements   ClassVisitor,
         if (!signature.equals(newSignature))
         {
             localVariableTypeInfo.u2signatureIndex =
-                constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                   newSignature);
+                new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature);
         }
     }
 
-
     // Implementations for AnnotationVisitor.
 
     public void visitAnnotation(Clazz clazz, Annotation annotation)
@@ -370,8 +364,7 @@ implements   ClassVisitor,
         {
             // Refer to a new Utf8 entry.
             annotation.u2typeIndex =
-                constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                   newTypeName);
+                new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newTypeName);
         }
 
         // Fix the element values.
@@ -397,8 +390,7 @@ implements   ClassVisitor,
         {
             // Refer to a new Utf8 entry.
             enumConstantElementValue.u2typeNameIndex =
-                constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                   newTypeName);
+                new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newTypeName);
         }
     }
 
@@ -414,8 +406,7 @@ implements   ClassVisitor,
         {
             // Refer to a new Utf8 entry.
             classElementValue.u2classInfoIndex =
-                constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                   newClassName);
+                new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newClassName);
         }
     }
 
@@ -517,7 +508,6 @@ implements   ClassVisitor,
      */
     private String newUniqueMemberName(String name, String descriptor)
     {
-        // TODO: Avoid duplicate constructors.
         return name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ?
             ClassConstants.INTERNAL_METHOD_NAME_INIT :
             name + ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode()));
diff --git a/src/proguard/classfile/editor/CodeAttributeComposer.java b/src/proguard/classfile/editor/CodeAttributeComposer.java
index 7a2cb37..d810403 100644
--- a/src/proguard/classfile/editor/CodeAttributeComposer.java
+++ b/src/proguard/classfile/editor/CodeAttributeComposer.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -67,9 +67,9 @@ implements   AttributeVisitor,
     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];
+    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];
 
     private ExceptionInfo[] exceptionTable   =  new ExceptionInfo[ClassConstants.TYPICAL_EXCEPTION_TABLE_LENGTH];
 
@@ -77,6 +77,7 @@ implements   AttributeVisitor,
 
     private final StackSizeUpdater    stackSizeUpdater    = new StackSizeUpdater();
     private final VariableSizeUpdater variableSizeUpdater = new VariableSizeUpdater();
+//    private final InstructionWriter   instructionWriter   = new InstructionWriter();
 
 
     /**
@@ -126,6 +127,13 @@ implements   AttributeVisitor,
             throw new IllegalArgumentException("Maximum number of code fragment levels exceeded ["+level+"]");
         }
 
+//        // TODO: Figure out some length.
+//        if (level == 0)
+//        {
+//            // Prepare for possible widening of instructions.
+//            instructionWriter.reset(2 * maximumCodeFragmentLength);
+//        }
+
         // Make sure there is sufficient space for adding the code fragment.
         maximumCodeLength += maximumCodeFragmentLength;
         if (code.length < maximumCodeLength)
@@ -176,6 +184,11 @@ implements   AttributeVisitor,
         oldInstructionOffsets[codeLength] = oldInstructionOffset;
 
         // Write the instruction.
+//        instruction.accept(null,
+//                           null,
+//                           new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
+//                           codeLength,
+//                           instructionWriter);
         instruction.write(code, codeLength);
 
         // Fill out the new offset of the appended instruction.
@@ -272,6 +285,11 @@ implements   AttributeVisitor,
                 instruction.accept(null, null, null, instructionOffset, this);
 
                 // Write the instruction back.
+//                instruction.accept(null,
+//                                   null,
+//                                   new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
+//                                   instructionOffset,
+//                                   instructionWriter);
                 instruction.write(code, instructionOffset);
 
                 // Don't remap this instruction again.
@@ -374,6 +392,9 @@ implements   AttributeVisitor,
         //    removeEmptyExceptions(codeAttribute.exceptionTable,
         //                          codeAttribute.u2exceptionTableLength);
 
+//        // Make sure instructions are widened if necessary.
+//        instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);
+
         level--;
     }
 
diff --git a/src/proguard/classfile/editor/CodeAttributeEditor.java b/src/proguard/classfile/editor/CodeAttributeEditor.java
index cda12a6..dc7915c 100644
--- a/src/proguard/classfile/editor/CodeAttributeEditor.java
+++ b/src/proguard/classfile/editor/CodeAttributeEditor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -441,8 +441,8 @@ implements   AttributeVisitor,
      * @param codeAttribute the code to be changed.
      * @return the new code length.
      */
-    private int updateInstructions(Clazz    clazz,
-                                   Method   method,
+    private int updateInstructions(Clazz         clazz,
+                                   Method        method,
                                    CodeAttribute codeAttribute)
     {
         byte[] oldCode   = codeAttribute.code;
diff --git a/src/proguard/classfile/editor/CodeAttributeEditorResetter.java b/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
index bbe8f01..53b0a73 100644
--- a/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
+++ b/src/proguard/classfile/editor/CodeAttributeEditorResetter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ComparableConstant.java b/src/proguard/classfile/editor/ComparableConstant.java
index 5d7cbbe..21a8f0b 100644
--- a/src/proguard/classfile/editor/ComparableConstant.java
+++ b/src/proguard/classfile/editor/ComparableConstant.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -35,20 +35,20 @@ import proguard.classfile.util.SimplifiedVisitor;
  *
  * @author Eric Lafortune
  */
-final class      ComparableConstant
+class      ComparableConstant
 extends    SimplifiedVisitor
 implements Comparable, ConstantVisitor
 {
     private static final int[] PRIORITIES = new int[13];
     static
     {
-        PRIORITIES[ClassConstants.CONSTANT_Integer]            = 0;
+        PRIORITIES[ClassConstants.CONSTANT_Integer]            = 0; // Possibly byte index (ldc).
         PRIORITIES[ClassConstants.CONSTANT_Float]              = 1;
-        PRIORITIES[ClassConstants.CONSTANT_Long]               = 2;
-        PRIORITIES[ClassConstants.CONSTANT_Double]             = 3;
-        PRIORITIES[ClassConstants.CONSTANT_String]             = 4;
-        PRIORITIES[ClassConstants.CONSTANT_Class]              = 5;
-        PRIORITIES[ClassConstants.CONSTANT_Fieldref]           = 6;
+        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;
+        PRIORITIES[ClassConstants.CONSTANT_Fieldref]           = 6; // Always wide index.
         PRIORITIES[ClassConstants.CONSTANT_Methodref]          = 7;
         PRIORITIES[ClassConstants.CONSTANT_InterfaceMethodref] = 8;
         PRIORITIES[ClassConstants.CONSTANT_NameAndType]        = 9;
@@ -58,6 +58,7 @@ implements Comparable, ConstantVisitor
     private final Clazz    clazz;
     private final int      thisIndex;
     private final Constant thisConstant;
+
     private Constant otherConstant;
     private int      result;
 
@@ -98,7 +99,7 @@ implements Comparable, ConstantVisitor
 
             return thisIndex <  otherIndex ? -1 :
                    thisIndex == otherIndex ?  0 :
-                   1;
+                                              1;
         }
 
         // Compare based on the tags, if they are different.
@@ -179,4 +180,21 @@ implements Comparable, ConstantVisitor
                  (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();
+    }
 }
diff --git a/src/proguard/classfile/editor/ConstantAdder.java b/src/proguard/classfile/editor/ConstantAdder.java
index 8895fee..e2b620d 100644
--- a/src/proguard/classfile/editor/ConstantAdder.java
+++ b/src/proguard/classfile/editor/ConstantAdder.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
@@ -33,27 +33,42 @@ import proguard.classfile.constant.visitor.ConstantVisitor;
 public class ConstantAdder
 implements   ConstantVisitor
 {
-    private ProgramClass targetClass;
-    private int          constantIndex;
+    private final ConstantPoolEditor constantPoolEditor;
 
-    private final ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor();
+    private int constantIndex;
 
 
     /**
-     * Sets the class to which visited constants will be copied.
+     * Creates a new ConstantAdder that will copy constants into the given
+     * target class.
      */
-    public void setTargetClass(ProgramClass targetClass)
+    public ConstantAdder(ProgramClass targetClass)
     {
-        this.targetClass = targetClass;
+        constantPoolEditor = new ConstantPoolEditor(targetClass);
     }
 
 
     /**
-     * Returns the class to which visited constants will be copied.
+     * 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 ProgramClass getTargetClass()
+    public int addConstant(Clazz clazz, int constantIndex)
     {
-        return targetClass;
+        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;
     }
 
 
@@ -72,40 +87,35 @@ implements   ConstantVisitor
     public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
     {
         constantIndex =
-            constantPoolEditor.addIntegerConstant(targetClass,
-                                                  integerConstant.getValue());
+            constantPoolEditor.addIntegerConstant(integerConstant.getValue());
     }
 
 
     public void visitLongConstant(Clazz clazz, LongConstant longConstant)
     {
         constantIndex =
-            constantPoolEditor.addLongConstant(targetClass,
-                                               longConstant.getValue());
+            constantPoolEditor.addLongConstant(longConstant.getValue());
     }
 
 
     public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
     {
         constantIndex =
-            constantPoolEditor.addFloatConstant(targetClass,
-                                                floatConstant.getValue());
+            constantPoolEditor.addFloatConstant(floatConstant.getValue());
     }
 
 
     public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
     {
         constantIndex =
-            constantPoolEditor.addDoubleConstant(targetClass,
-                                                 doubleConstant.getValue());
+            constantPoolEditor.addDoubleConstant(doubleConstant.getValue());
     }
 
 
     public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
     {
         constantIndex =
-            constantPoolEditor.addStringConstant(targetClass,
-                                                 stringConstant.getString(clazz),
+            constantPoolEditor.addStringConstant(stringConstant.getString(clazz),
                                                  stringConstant.referencedClass,
                                                  stringConstant.referencedMember);
     }
@@ -114,8 +124,7 @@ implements   ConstantVisitor
     public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
     {
         constantIndex =
-            constantPoolEditor.addUtf8Constant(targetClass,
-                                               utf8Constant.getString());
+            constantPoolEditor.addUtf8Constant(utf8Constant.getString());
     }
 
 
@@ -127,8 +136,7 @@ implements   ConstantVisitor
         // Then add the actual field reference constant, with its referenced
         // class and class member.
         constantIndex =
-            constantPoolEditor.addFieldrefConstant(targetClass,
-                                                   constantIndex,
+            constantPoolEditor.addFieldrefConstant(constantIndex,
                                                    fieldrefConstant.getName(clazz),
                                                    fieldrefConstant.getType(clazz),
                                                    fieldrefConstant.referencedClass,
@@ -144,8 +152,7 @@ implements   ConstantVisitor
         // Then add the actual interface method reference constant, with its
         // referenced class and class member.
         constantIndex =
-            constantPoolEditor.addInterfaceMethodrefConstant(targetClass,
-                                                             constantIndex,
+            constantPoolEditor.addInterfaceMethodrefConstant(constantIndex,
                                                              interfaceMethodrefConstant.getName(clazz),
                                                              interfaceMethodrefConstant.getType(clazz),
                                                              interfaceMethodrefConstant.referencedClass,
@@ -161,8 +168,7 @@ implements   ConstantVisitor
         // Then add the actual method reference constant, with its referenced
         // class and class member.
         constantIndex =
-            constantPoolEditor.addMethodrefConstant(targetClass,
-                                                    constantIndex,
+            constantPoolEditor.addMethodrefConstant(constantIndex,
                                                     methodrefConstant.getName(clazz),
                                                     methodrefConstant.getType(clazz),
                                                     methodrefConstant.referencedClass,
@@ -174,8 +180,7 @@ implements   ConstantVisitor
     {
         // Add the class constant, with its referenced class..
         constantIndex =
-            constantPoolEditor.addClassConstant(targetClass,
-                                                classConstant.getName(clazz),
+            constantPoolEditor.addClassConstant(classConstant.getName(clazz),
                                                 classConstant.referencedClass);
     }
 
@@ -183,8 +188,7 @@ implements   ConstantVisitor
     public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
     {
         constantIndex =
-            constantPoolEditor.addNameAndTypeConstant(targetClass,
-                                                      nameAndTypeConstant.getName(clazz),
+            constantPoolEditor.addNameAndTypeConstant(nameAndTypeConstant.getName(clazz),
                                                       nameAndTypeConstant.getType(clazz));
     }
 }
diff --git a/src/proguard/classfile/editor/ConstantPoolEditor.java b/src/proguard/classfile/editor/ConstantPoolEditor.java
index 7fb0224..509963e 100644
--- a/src/proguard/classfile/editor/ConstantPoolEditor.java
+++ b/src/proguard/classfile/editor/ConstantPoolEditor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -24,7 +24,7 @@ import proguard.classfile.*;
 import proguard.classfile.constant.*;
 
 /**
- * This class can add constant pool entries to given classes.
+ * This class can add constant pool entries to a given class.
  *
  * @author Eric Lafortune
  */
@@ -32,17 +32,28 @@ 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,
-     * in the given class.
-     * @return the constant pool index of the   Utf8Constant.
+     * Finds or creates a IntegerConstant constant pool entry with the given
+     * value.
+     * @return the constant pool index of the Utf8Constant.
      */
-    public int addIntegerConstant(ProgramClass programClass,
-                                  int          value)
+    public int addIntegerConstant(int value)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Check if the entry already exists.
         for (int index = 1; index < constantPoolCount; index++)
@@ -60,20 +71,18 @@ public class ConstantPoolEditor
             }
         }
 
-        return addConstant(programClass, new IntegerConstant(value));
+        return addConstant(new IntegerConstant(value));
     }
 
 
     /**
-     * Finds or creates a LongConstant constant pool entry with the given value,
-     * in the given class.
-     * @return the constant pool index of the   Utf8Constant.
+     * Finds or creates a LongConstant constant pool entry with the given value.
+     * @return the constant pool index of the LongConstant.
      */
-    public int addLongConstant(ProgramClass programClass,
-                               long         value)
+    public int addLongConstant(long value)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Check if the entry already exists.
         for (int index = 1; index < constantPoolCount; index++)
@@ -91,20 +100,19 @@ public class ConstantPoolEditor
             }
         }
 
-        return addConstant(programClass, new LongConstant(value));
+        return addConstant(new LongConstant(value));
     }
 
 
     /**
-     * Finds or creates a FloatConstant constant pool entry with the given value,
-     * in the given class.
-     * @return the constant pool index of the   Utf8Constant.
+     * Finds or creates a FloatConstant constant pool entry with the given
+     * value.
+     * @return the constant pool index of the FloatConstant.
      */
-    public int addFloatConstant(ProgramClass programClass,
-                                float        value)
+    public int addFloatConstant(float value)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Check if the entry already exists.
         for (int index = 1; index < constantPoolCount; index++)
@@ -122,20 +130,19 @@ public class ConstantPoolEditor
             }
         }
 
-        return addConstant(programClass, new FloatConstant(value));
+        return addConstant(new FloatConstant(value));
     }
 
 
     /**
-     * Finds or creates a DoubleConstant constant pool entry with the given value,
-     * in the given class.
-     * @return the constant pool index of the   Utf8Constant.
+     * Finds or creates a DoubleConstant constant pool entry with the given
+     * value.
+     * @return the constant pool index of the DoubleConstant.
      */
-    public int addDoubleConstant(ProgramClass programClass,
-                                  double      value)
+    public int addDoubleConstant(double value)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Check if the entry already exists.
         for (int index = 1; index < constantPoolCount; index++)
@@ -153,22 +160,21 @@ public class ConstantPoolEditor
             }
         }
 
-        return addConstant(programClass, new DoubleConstant(value));
+        return addConstant(new DoubleConstant(value));
     }
 
 
     /**
-     * Finds or creates a StringConstant constant pool entry with the given value,
-     * in the given class.
-     * @return the constant pool index of the ClassConstant.
+     * Finds or creates a StringConstant constant pool entry with the given
+     * value.
+     * @return the constant pool index of the StringConstant.
      */
-    public int addStringConstant(ProgramClass programClass,
-                                 String       string,
-                                 Clazz        referencedClass,
-                                 Member       referencedMember)
+    public int addStringConstant(String string,
+                                 Clazz  referencedClass,
+                                 Member referencedMember)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Check if the entry already exists.
         for (int index = 1; index < constantPoolCount; index++)
@@ -178,18 +184,15 @@ public class ConstantPoolEditor
             if (constant != null &&
                 constant.getTag() == ClassConstants.CONSTANT_String)
             {
-                StringConstant classConstant = (StringConstant)constant;
-                if (classConstant.getString(programClass).equals(string))
+                StringConstant stringConstant = (StringConstant)constant;
+                if (stringConstant.getString(targetClass).equals(string))
                 {
                     return index;
                 }
             }
         }
 
-        int nameIndex = addUtf8Constant(programClass, string);
-
-        return addConstant(programClass,
-                           new StringConstant(nameIndex,
+        return addConstant(new StringConstant(addUtf8Constant(string),
                                               referencedClass,
                                               referencedMember));
     }
@@ -197,15 +200,13 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a FieldrefConstant constant pool entry for the given
-     * class and field, in the given class.
+     * class and field.
      * @return the constant pool index of the FieldrefConstant.
      */
-    public int addFieldrefConstant(ProgramClass programClass,
-                                   Clazz        referencedClass,
-                                   Member       referencedMember)
+    public int addFieldrefConstant(Clazz  referencedClass,
+                                   Member referencedMember)
     {
-        return addFieldrefConstant(programClass,
-                                   referencedClass.getName(),
+        return addFieldrefConstant(referencedClass.getName(),
                                    referencedMember.getName(referencedClass),
                                    referencedMember.getDescriptor(referencedClass),
                                    referencedClass,
@@ -215,21 +216,17 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a FieldrefConstant constant pool entry with the given
-     * class name, field name, and descriptor, in the given class.
+     * class name, field name, and descriptor.
      * @return the constant pool index of the FieldrefConstant.
      */
-    public int addFieldrefConstant(ProgramClass programClass,
-                                   String       className,
-                                   String       name,
-                                   String       descriptor,
-                                   Clazz        referencedClass,
-                                   Member       referencedMember)
+    public int addFieldrefConstant(String className,
+                                   String name,
+                                   String descriptor,
+                                   Clazz  referencedClass,
+                                   Member referencedMember)
     {
-        return addFieldrefConstant(programClass,
-                                   className,
-                                   addNameAndTypeConstant(programClass,
-                                                          name,
-                                                          descriptor),
+        return addFieldrefConstant(className,
+                                   addNameAndTypeConstant(name, descriptor),
                                    referencedClass,
                                    referencedMember);
     }
@@ -237,19 +234,15 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a FieldrefConstant constant pool entry with the given
-     * class name, field name, and descriptor, in the given class.
+     * class name, field name, and descriptor.
      * @return the constant pool index of the FieldrefConstant.
      */
-    public int addFieldrefConstant(ProgramClass programClass,
-                                   String       className,
-                                   int          nameAndTypeIndex,
-                                   Clazz        referencedClass,
-                                   Member       referencedMember)
+    public int addFieldrefConstant(String className,
+                                   int    nameAndTypeIndex,
+                                   Clazz  referencedClass,
+                                   Member referencedMember)
     {
-        return addFieldrefConstant(programClass,
-                                   addClassConstant(programClass,
-                                                    className,
-                                                    referencedClass),
+        return addFieldrefConstant(addClassConstant(className, referencedClass),
                                    nameAndTypeIndex,
                                    referencedClass,
                                    referencedMember);
@@ -258,22 +251,17 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a FieldrefConstant constant pool entry with the given
-     * class constant pool entry index, field name, and descriptor, in the
-     * given class.
-     * @return the constant pool index of the   FieldrefConstant.
+     * class constant pool entry index, field name, and descriptor.
+     * @return the constant pool index of the FieldrefConstant.
      */
-    public int addFieldrefConstant(ProgramClass programClass,
-                                   int          classIndex,
-                                   String       name,
-                                   String       descriptor,
-                                   Clazz        referencedClass,
-                                   Member       referencedMember)
+    public int addFieldrefConstant(int    classIndex,
+                                   String name,
+                                   String descriptor,
+                                   Clazz  referencedClass,
+                                   Member referencedMember)
     {
-        return addFieldrefConstant(programClass,
-                                   classIndex,
-                                   addNameAndTypeConstant(programClass,
-                                                          name,
-                                                          descriptor),
+        return addFieldrefConstant(classIndex,
+                                   addNameAndTypeConstant(name, descriptor),
                                    referencedClass,
                                    referencedMember);
     }
@@ -281,18 +269,17 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a FieldrefConstant constant pool entry with the given
-     * class constant pool entry index and name and type constant pool entry index
-     * the given class.
+     * class constant pool entry index and name and type constant pool entry
+     * index.
      * @return the constant pool index of the FieldrefConstant.
      */
-    public int addFieldrefConstant(ProgramClass programClass,
-                                   int          classIndex,
-                                   int          nameAndTypeIndex,
-                                   Clazz        referencedClass,
-                                   Member       referencedMember)
+    public int addFieldrefConstant(int    classIndex,
+                                   int    nameAndTypeIndex,
+                                   Clazz  referencedClass,
+                                   Member referencedMember)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Check if the entry already exists.
         for (int index = 1; index < constantPoolCount; index++)
@@ -311,8 +298,7 @@ public class ConstantPoolEditor
             }
         }
 
-        return addConstant(programClass,
-                           new FieldrefConstant(classIndex,
+        return addConstant(new FieldrefConstant(classIndex,
                                                 nameAndTypeIndex,
                                                 referencedClass,
                                                 referencedMember));
@@ -321,58 +307,48 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
-     * given class name, method name, and descriptor, in the given class.
+     * given class name, method name, and descriptor.
      * @return the constant pool index of the InterfaceMethodrefConstant.
      */
-    public int addInterfaceMethodrefConstant(ProgramClass programClass,
-                                             String       className,
-                                             String       name,
-                                             String       descriptor,
-                                             Clazz        referencedClass,
-                                             Member       referencedMember)
+    public int addInterfaceMethodrefConstant(String className,
+                                             String name,
+                                             String descriptor,
+                                             Clazz  referencedClass,
+                                             Member referencedMember)
     {
-        return addInterfaceMethodrefConstant(programClass,
-                                             className,
-                                             addNameAndTypeConstant(programClass,
-                                                                    name,
-                                                                    descriptor),
-                                                                    referencedClass,
-                                                                    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, in the given class.
+     * given class name, method name, and descriptor.
      * @return the constant pool index of the InterfaceMethodrefConstant.
      */
-    public int addInterfaceMethodrefConstant(ProgramClass programClass,
-                                             String       className,
-                                             int          nameAndTypeIndex,
-                                             Clazz        referencedClass,
-                                             Member       referencedMember)
+    public int addInterfaceMethodrefConstant(String className,
+                                             int    nameAndTypeIndex,
+                                             Clazz  referencedClass,
+                                             Member referencedMember)
     {
-        return addInterfaceMethodrefConstant(programClass,
-                                             addClassConstant(programClass,
-                                                              className,
-                                                              referencedClass),
-                                                              nameAndTypeIndex,
-                                                              referencedClass,
-                                                              referencedMember);
+        return addInterfaceMethodrefConstant(addClassConstant(className, referencedClass),
+                                             nameAndTypeIndex,
+                                             referencedClass,
+                                             referencedMember);
     }
 
 
     /**
      * Finds or creates a InterfaceMethodrefConstant constant pool entry for the
-     * given class and method, in the given class.
+     * given class and method.
      * @return the constant pool index of the InterfaceMethodrefConstant.
      */
-    public int addInterfaceMethodrefConstant(ProgramClass programClass,
-                                             Clazz        referencedClass,
-                                             Member       referencedMember)
+    public int addInterfaceMethodrefConstant(Clazz  referencedClass,
+                                             Member referencedMember)
     {
-        return addInterfaceMethodrefConstant(programClass,
-                                             referencedClass.getName(),
+        return addInterfaceMethodrefConstant(referencedClass.getName(),
                                              referencedMember.getName(referencedClass),
                                              referencedMember.getDescriptor(referencedClass),
                                              referencedClass,
@@ -382,22 +358,17 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
-     * given class constant pool entry index, method name, and descriptor, in
-     * the given class.
+     * given class constant pool entry index, method name, and descriptor.
      * @return the constant pool index of the InterfaceMethodrefConstant.
      */
-    public int addInterfaceMethodrefConstant(ProgramClass programClass,
-                                             int          classIndex,
-                                             String       name,
-                                             String       descriptor,
-                                             Clazz        referencedClass,
-                                             Member       referencedMember)
+    public int addInterfaceMethodrefConstant(int    classIndex,
+                                             String name,
+                                             String descriptor,
+                                             Clazz  referencedClass,
+                                             Member referencedMember)
     {
-        return addInterfaceMethodrefConstant(programClass,
-                                             classIndex,
-                                             addNameAndTypeConstant(programClass,
-                                                                    name,
-                                                                    descriptor),
+        return addInterfaceMethodrefConstant(classIndex,
+                                             addNameAndTypeConstant(name, descriptor),
                                              referencedClass,
                                              referencedMember);
     }
@@ -406,17 +377,16 @@ public class ConstantPoolEditor
     /**
      * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
      * given class constant pool entry index and name and type constant pool
-     * entry index the given class.
+     * entry index.
      * @return the constant pool index of the InterfaceMethodrefConstant.
      */
-    public int addInterfaceMethodrefConstant(ProgramClass programClass,
-                                             int          classIndex,
-                                             int          nameAndTypeIndex,
-                                             Clazz        referencedClass,
-                                             Member       referencedMember)
+    public int addInterfaceMethodrefConstant(int    classIndex,
+                                             int    nameAndTypeIndex,
+                                             Clazz  referencedClass,
+                                             Member referencedMember)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Check if the entry already exists.
         for (int index = 1; index < constantPoolCount; index++)
@@ -428,15 +398,14 @@ public class ConstantPoolEditor
             {
                 InterfaceMethodrefConstant methodrefConstant = (InterfaceMethodrefConstant)constant;
                 if (methodrefConstant.u2classIndex       == classIndex &&
-                                methodrefConstant.u2nameAndTypeIndex ==   nameAndTypeIndex)
+                    methodrefConstant.u2nameAndTypeIndex == nameAndTypeIndex)
                 {
                     return index;
                 }
             }
         }
 
-        return addConstant(programClass,
-                           new InterfaceMethodrefConstant(classIndex,
+        return addConstant(new InterfaceMethodrefConstant(classIndex,
                                                           nameAndTypeIndex,
                                                           referencedClass,
                                                           referencedMember));
@@ -445,15 +414,13 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a MethodrefConstant constant pool entry for the given
-     * class and method, in the given class.
-     * @return the constant pool index of   the MethodrefConstant.
+     * class and method.
+     * @return the constant pool index of the MethodrefConstant.
      */
-    public int addMethodrefConstant(ProgramClass programClass,
-                                    Clazz        referencedClass,
-                                    Member       referencedMember)
+    public int addMethodrefConstant(Clazz  referencedClass,
+                                    Member referencedMember)
     {
-        return addMethodrefConstant(programClass,
-                                    referencedClass.getName(),
+        return addMethodrefConstant(referencedClass.getName(),
                                     referencedMember.getName(referencedClass),
                                     referencedMember.getDescriptor(referencedClass),
                                     referencedClass,
@@ -463,21 +430,17 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a MethodrefConstant constant pool entry with the given
-     * class name, method name, and descriptor, in the given class.
-     * @return the constant pool index of   the MethodrefConstant.
+     * class name, method name, and descriptor.
+     * @return the constant pool index of the MethodrefConstant.
      */
-    public int addMethodrefConstant(ProgramClass programClass,
-                                    String       className,
-                                    String       name,
-                                    String       descriptor,
-                                    Clazz        referencedClass,
-                                    Member       referencedMember)
+    public int addMethodrefConstant(String className,
+                                    String name,
+                                    String descriptor,
+                                    Clazz  referencedClass,
+                                    Member referencedMember)
     {
-        return addMethodrefConstant(programClass,
-                                    className,
-                                    addNameAndTypeConstant(programClass,
-                                                           name,
-                                                           descriptor),
+        return addMethodrefConstant(className,
+                                    addNameAndTypeConstant(name, descriptor),
                                     referencedClass,
                                     referencedMember);
     }
@@ -485,19 +448,15 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a MethodrefConstant constant pool entry with the given
-     * class name, method name, and descriptor, in the given class.
-     * @return the constant pool index of   the MethodrefConstant.
+     * class name, method name, and descriptor.
+     * @return the constant pool index of the MethodrefConstant.
      */
-    public int addMethodrefConstant(ProgramClass programClass,
-                                    String       className,
-                                    int          nameAndTypeIndex,
-                                    Clazz        referencedClass,
-                                    Member       referencedMember)
+    public int addMethodrefConstant(String className,
+                                    int    nameAndTypeIndex,
+                                    Clazz  referencedClass,
+                                    Member referencedMember)
     {
-        return addMethodrefConstant(programClass,
-                                    addClassConstant(programClass,
-                                                     className,
-                                                     referencedClass),
+        return addMethodrefConstant(addClassConstant(className, referencedClass),
                                     nameAndTypeIndex,
                                     referencedClass,
                                     referencedMember);
@@ -506,22 +465,17 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a MethodrefConstant constant pool entry with the given
-     * class constant pool entry index, method name, and descriptor, in the
-     * given class.
-     * @return the constant pool index of   the MethodrefConstant.
+     * class constant pool entry index, method name, and descriptor.
+     * @return the constant pool index of the MethodrefConstant.
      */
-    public int addMethodrefConstant(ProgramClass programClass,
-                                    int          classIndex,
-                                    String       name,
-                                    String       descriptor,
-                                    Clazz        referencedClass,
-                                    Member       referencedMember)
+    public int addMethodrefConstant(int    classIndex,
+                                    String name,
+                                    String descriptor,
+                                    Clazz  referencedClass,
+                                    Member referencedMember)
     {
-        return addMethodrefConstant(programClass,
-                                    classIndex,
-                                    addNameAndTypeConstant(programClass,
-                                                           name,
-                                                           descriptor),
+        return addMethodrefConstant(classIndex,
+                                    addNameAndTypeConstant(name, descriptor),
                                     referencedClass,
                                     referencedMember);
     }
@@ -529,18 +483,17 @@ public class ConstantPoolEditor
 
     /**
      * Finds or creates a MethodrefConstant constant pool entry with the given
-     * class constant pool entry index and name and type constant pool entry index
-     * the given class.
+     * class constant pool entry index and name and type constant pool entry
+     * index.
      * @return the constant pool index of the MethodrefConstant.
      */
-    public int addMethodrefConstant(ProgramClass programClass,
-                                    int          classIndex,
-                                    int          nameAndTypeIndex,
-                                    Clazz        referencedClass,
-                                    Member       referencedMember)
+    public int addMethodrefConstant(int    classIndex,
+                                    int    nameAndTypeIndex,
+                                    Clazz  referencedClass,
+                                    Member referencedMember)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Check if the entry already exists.
         for (int index = 1; index < constantPoolCount; index++)
@@ -551,16 +504,15 @@ public class ConstantPoolEditor
                 constant.getTag() == ClassConstants.CONSTANT_Methodref)
             {
                 MethodrefConstant methodrefConstant = (MethodrefConstant)constant;
-                if (methodrefConstant.u2classIndex         == classIndex &&
-                    methodrefConstant.u2nameAndTypeIndex   == nameAndTypeIndex)
+                if (methodrefConstant.u2classIndex       == classIndex &&
+                    methodrefConstant.u2nameAndTypeIndex == nameAndTypeIndex)
                 {
                     return index;
                 }
             }
         }
 
-        return addConstant(programClass,
-                           new MethodrefConstant(classIndex,
+        return addConstant(new MethodrefConstant(classIndex,
                                                  nameAndTypeIndex,
                                                  referencedClass,
                                                  referencedMember));
@@ -568,30 +520,25 @@ public class ConstantPoolEditor
 
 
     /**
-     * Finds or creates a ClassConstant constant pool entry for the given class,
-     * in the given class.
+     * Finds or creates a ClassConstant constant pool entry for the given class.
      * @return the constant pool index of the ClassConstant.
      */
-    public int addClassConstant(ProgramClass programClass,
-                                Clazz        referencedClass)
+    public int addClassConstant(Clazz referencedClass)
     {
-        return addClassConstant(programClass,
-                                referencedClass.getName(),
+        return addClassConstant(referencedClass.getName(),
                                 referencedClass);
     }
 
 
     /**
-     * Finds or creates a ClassConstant constant pool entry with the given name,
-     * in the given class.
+     * Finds or creates a ClassConstant constant pool entry with the given name.
      * @return the constant pool index of the ClassConstant.
      */
-    public int addClassConstant(ProgramClass programClass,
-                                String       name,
-                                Clazz        referencedClass)
+    public int addClassConstant(String name,
+                                Clazz  referencedClass)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Check if the entry already exists.
         for (int index = 1; index < constantPoolCount; index++)
@@ -602,32 +549,29 @@ public class ConstantPoolEditor
                 constant.getTag() == ClassConstants.CONSTANT_Class)
             {
                 ClassConstant classConstant = (ClassConstant)constant;
-                if (classConstant.getName(programClass).equals(name))
+                if (classConstant.getName(targetClass).equals(name))
                 {
                     return index;
                 }
             }
         }
 
-        int nameIndex = addUtf8Constant(programClass, name);
+        int nameIndex = addUtf8Constant(name);
 
-        return addConstant(programClass,
-                           new ClassConstant(nameIndex,
-                                             referencedClass));
+        return addConstant(new ClassConstant(nameIndex, referencedClass));
     }
 
 
     /**
      * Finds or creates a NameAndTypeConstant constant pool entry with the given
-     * name and type, in the given class.
+     * name and type.
      * @return the constant pool index of the NameAndTypeConstant.
      */
-    public int addNameAndTypeConstant(ProgramClass programClass,
-                                      String       name,
-                                      String       type)
+    public int addNameAndTypeConstant(String name,
+                                      String type)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Check if the entry already exists.
         for (int index = 1; index < constantPoolCount; index++)
@@ -638,33 +582,27 @@ public class ConstantPoolEditor
                 constant.getTag() == ClassConstants.CONSTANT_NameAndType)
             {
                 NameAndTypeConstant nameAndTypeConstant = (NameAndTypeConstant)constant;
-                if (nameAndTypeConstant.getName(programClass).equals(name) &&
-                    nameAndTypeConstant.getType(programClass).equals(type))
+                if (nameAndTypeConstant.getName(targetClass).equals(name) &&
+                    nameAndTypeConstant.getType(targetClass).equals(type))
                 {
                     return index;
                 }
             }
         }
 
-        int nameIndex       = addUtf8Constant(programClass, name);
-        int descriptorIndex = addUtf8Constant(programClass, type);
-
-        return addConstant(programClass,
-                           new NameAndTypeConstant(nameIndex,
-                                                   descriptorIndex));
+        return addConstant(new NameAndTypeConstant(addUtf8Constant(name),
+                                                   addUtf8Constant(type)));
     }
 
 
     /**
-     * Finds or creates a Utf8Constant constant pool entry for the given string,
-     * in the given class.
-     * @return the constant pool index of the   Utf8Constant.
+     * Finds or creates a Utf8Constant constant pool entry for the given string.
+     * @return the constant pool index of the Utf8Constant.
      */
-    public int addUtf8Constant(ProgramClass programClass,
-                               String       string)
+    public int addUtf8Constant(String string)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Check if the entry already exists.
         for (int index = 1; index < constantPoolCount; index++)
@@ -682,38 +620,36 @@ public class ConstantPoolEditor
             }
         }
 
-        return addConstant(programClass, new Utf8Constant(string));
+        return addConstant(new Utf8Constant(string));
     }
 
 
     /**
-     * Adds a given constant pool entry to the end of the constant pool
-     * in the given class.
+     * 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(ProgramClass programClass,
-                           Constant     constant)
+    public int addConstant(Constant constant)
     {
-        int        constantPoolCount = programClass.u2constantPoolCount;
-        Constant[] constantPool      = programClass.constantPool;
+        int        constantPoolCount = targetClass.u2constantPoolCount;
+        Constant[] constantPool      = targetClass.constantPool;
 
         // Make sure there is enough space for another constant pool entry.
         if (constantPool.length < constantPoolCount+2)
         {
-            programClass.constantPool = new Constant[constantPoolCount+2];
+            targetClass.constantPool = new Constant[constantPoolCount+2];
             System.arraycopy(constantPool, 0,
-                             programClass.constantPool, 0,
+                             targetClass.constantPool, 0,
                              constantPoolCount);
-            constantPool = programClass.constantPool;
+            constantPool = targetClass.constantPool;
         }
 
         if (DEBUG)
         {
-            System.out.println(programClass.getName()+": adding ["+constant.getClass().getName()+"] at index "+programClass.u2constantPoolCount);
+            System.out.println(targetClass.getName()+": adding ["+constant.getClass().getName()+"] at index "+targetClass.u2constantPoolCount);
         }
 
         // Create a new Utf8Constant for the given string.
-        constantPool[programClass.u2constantPoolCount++] = constant;
+        constantPool[targetClass.u2constantPoolCount++] = constant;
 
         // Long constants and double constants take up two entries in the
         // constant pool.
@@ -721,7 +657,7 @@ public class ConstantPoolEditor
         if (tag == ClassConstants.CONSTANT_Long ||
             tag == ClassConstants.CONSTANT_Double)
         {
-            constantPool[programClass.u2constantPoolCount++] = null;
+            constantPool[targetClass.u2constantPoolCount++] = null;
         }
 
         return constantPoolCount;
diff --git a/src/proguard/classfile/editor/ConstantPoolRemapper.java b/src/proguard/classfile/editor/ConstantPoolRemapper.java
index 8005ee9..33c4d9f 100644
--- a/src/proguard/classfile/editor/ConstantPoolRemapper.java
+++ b/src/proguard/classfile/editor/ConstantPoolRemapper.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/ConstantPoolSorter.java b/src/proguard/classfile/editor/ConstantPoolSorter.java
index 4ce4cb0..2828e7f 100644
--- a/src/proguard/classfile/editor/ConstantPoolSorter.java
+++ b/src/proguard/classfile/editor/ConstantPoolSorter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -22,21 +22,25 @@ 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 classes that
- * it visits. The sorting order is based on the types of the constant pool
+ * 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 implements ClassVisitor
+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();
 
@@ -45,72 +49,78 @@ public class ConstantPoolSorter implements ClassVisitor
 
     public void visitProgramClass(ProgramClass programClass)
     {
-        // Sort the constant pool and set up an index map.
-        sortConstantPool(programClass,
-                         programClass.constantPool,
-                         programClass.u2constantPoolCount);
-
-        // Remap all constant pool references.
-        constantPoolRemapper.setConstantIndexMap(constantIndexMap);
-        constantPoolRemapper.visitProgramClass(programClass);
-    }
+        int constantPoolCount = programClass.u2constantPoolCount;
 
-
-    public void visitLibraryClass(LibraryClass libraryClass)
-    {
-    }
-
-
-    // Small utility methods.
-
-    /**
-     * Sorts the given constant pool.
-     */
-    private void sortConstantPool(Clazz clazz, Constant[] constantPool, int length)
-    {
-        if (constantIndexMap.length < length)
+        // Sort the constant pool and set up an index map.
+        if (constantIndexMap.length < constantPoolCount)
         {
-            constantIndexMap       = new int[length];
-            comparableConstantPool = new ComparableConstant[length];
+            constantIndexMap       = new int[constantPoolCount];
+            comparableConstantPool = new ComparableConstant[constantPoolCount];
+            newConstantPool        = new Constant[constantPoolCount];
         }
 
         // Initialize an array whose elements can be compared.
-        for (int oldIndex = 1; oldIndex < length; oldIndex++)
+        int sortLength = 0;
+        for (int oldIndex = 1; oldIndex < constantPoolCount; oldIndex++)
         {
-            Constant constant = constantPool[oldIndex];
-
-            // Long entries take up two entries, the second of which is null.
-            if (constant == null)
+            Constant constant = programClass.constantPool[oldIndex];
+            if (constant != null)
             {
-                constant = constantPool[oldIndex-1];
+                comparableConstantPool[sortLength++] =
+                    new ComparableConstant(programClass, oldIndex, constant);
             }
-
-            comparableConstantPool[oldIndex] = new ComparableConstant(clazz,
-                                                                      oldIndex,
-                                                                      constant);
         }
 
         // Sort the array.
-        Arrays.sort(comparableConstantPool, 1, length);
+        Arrays.sort(comparableConstantPool, 0, sortLength);
 
         // Save the sorted elements.
-        Constant previousConstant = null;
-        for (int newIndex = 1; newIndex < length; newIndex++)
+        int newLength = 1;
+        int newIndex  = 1;
+        ComparableConstant previousComparableConstant = null;
+        for (int sortIndex = 0; sortIndex < sortLength; sortIndex++)
         {
-            ComparableConstant comparableConstant = comparableConstantPool[newIndex];
+            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.
-            int oldIndex = comparableConstant.getIndex();
-            constantIndexMap[oldIndex] = newIndex;
+            constantIndexMap[comparableConstant.getIndex()] = newIndex;
+        }
 
-            // Copy the sorted constant pool entry over to the constant pool.
-            // Long entries take up two entries, the second of which is null.
-            Constant constant = comparableConstant.getConstant();
-            constantPool[newIndex] = constant != previousConstant ?
-                constant :
-                null;
+        // Copy the new constant pool over.
+        System.arraycopy(newConstantPool, 0, programClass.constantPool, 0, newLength);
 
-            previousConstant = constant;
+        // Clear any remaining entries.
+        for (int index = newLength; index < constantPoolCount; index++)
+        {
+            programClass.constantPool[index] = null;
         }
+
+        programClass.u2constantPoolCount = newLength;
+
+        // Remap all constant pool references.
+        constantPoolRemapper.setConstantIndexMap(constantIndexMap);
+        constantPoolRemapper.visitProgramClass(programClass);
     }
 }
diff --git a/src/proguard/classfile/editor/ElementValueAdder.java b/src/proguard/classfile/editor/ElementValueAdder.java
new file mode 100644
index 0000000..dbf5aa2
--- /dev/null
+++ b/src/proguard/classfile/editor/ElementValueAdder.java
@@ -0,0 +1,218 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with 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)
+    {
+System.out.println("ElementValueAdder.ElementValueAdder "+targetClass.getName());
+        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/src/proguard/classfile/editor/ElementValuesEditor.java b/src/proguard/classfile/editor/ElementValuesEditor.java
new file mode 100644
index 0000000..5e06768
--- /dev/null
+++ b/src/proguard/classfile/editor/ElementValuesEditor.java
@@ -0,0 +1,238 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with 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.*;
+
+/**
+ * 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/src/proguard/classfile/editor/ExceptionAdder.java b/src/proguard/classfile/editor/ExceptionAdder.java
index 91e9a22..48decfe 100644
--- a/src/proguard/classfile/editor/ExceptionAdder.java
+++ b/src/proguard/classfile/editor/ExceptionAdder.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -36,22 +36,19 @@ public class ExceptionAdder
 extends      SimplifiedVisitor
 implements   ConstantVisitor
 {
-    private final ExceptionsAttribute targetExceptionsAttribute;
-
-    private final ConstantAdder    constantAdder    = new ConstantAdder();
-    private final ExceptionsEditor exceptionsEditor = new ExceptionsEditor();
+    private final ConstantAdder             constantAdder;
+    private final ExceptionsAttributeEditor exceptionsAttributeEditor;
 
 
     /**
-     * Creates a new MemberAdder that will copy methods into the given target
-     * class.
+     * Creates a new ExceptionAdder that will copy classes into the given
+     * target exceptions attribute.
      */
-  public ExceptionAdder(ProgramClass        targetClass,
-                        ExceptionsAttribute targetExceptionsAttribute)
+    public ExceptionAdder(ProgramClass        targetClass,
+                          ExceptionsAttribute targetExceptionsAttribute)
     {
-        this.targetExceptionsAttribute = targetExceptionsAttribute;
-
-        constantAdder.setTargetClass(targetClass);
+        constantAdder             = new ConstantAdder(targetClass);
+        exceptionsAttributeEditor = new ExceptionsAttributeEditor(targetExceptionsAttribute);
     }
 
 
@@ -59,9 +56,10 @@ implements   ConstantVisitor
 
     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
     {
+        // Add a class constant to the constant pool.
         constantAdder.visitClassConstant(clazz, classConstant);
 
-        exceptionsEditor.addException(targetExceptionsAttribute,
-                                      constantAdder.getConstantIndex());
+        // Add the index of the class constant to the list of exceptions.
+        exceptionsAttributeEditor.addException(constantAdder.getConstantIndex());
     }
 }
diff --git a/src/proguard/classfile/editor/ExceptionInfoAdder.java b/src/proguard/classfile/editor/ExceptionInfoAdder.java
new file mode 100644
index 0000000..b1c55ae
--- /dev/null
+++ b/src/proguard/classfile/editor/ExceptionInfoAdder.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with 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/src/proguard/classfile/editor/ExceptionsEditor.java b/src/proguard/classfile/editor/ExceptionsAttributeEditor.java
similarity index 50%
rename from src/proguard/classfile/editor/ExceptionsEditor.java
rename to src/proguard/classfile/editor/ExceptionsAttributeEditor.java
index f84020d..08daa0b 100644
--- a/src/proguard/classfile/editor/ExceptionsEditor.java
+++ b/src/proguard/classfile/editor/ExceptionsAttributeEditor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -23,33 +23,46 @@ package proguard.classfile.editor;
 import proguard.classfile.attribute.ExceptionsAttribute;
 
 /**
- * This class can add exceptions to exceptions attributes. Exceptions to be
- * added must have been added to the constant pool filled out beforehand.
+ * 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 ExceptionsEditor
+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 given exceptions attribute.
+     * Adds a given exception to the exceptions attribute.
      */
-  public void addException(ExceptionsAttribute exceptionsAttribute,
-                           int                 exceptionIndex)
+    public void addException(int exceptionIndex)
     {
-        int   exceptionIndexTableLength = exceptionsAttribute.u2exceptionIndexTableLength;
-        int[] exceptionIndexTable       = exceptionsAttribute.u2exceptionIndexTable;
+        int   exceptionIndexTableLength = targetExceptionsAttribute.u2exceptionIndexTableLength;
+        int[] exceptionIndexTable       = targetExceptionsAttribute.u2exceptionIndexTable;
 
         // Make sure there is enough space for the new exception.
         if (exceptionIndexTable.length <= exceptionIndexTableLength)
         {
-            exceptionsAttribute.u2exceptionIndexTable = new int[exceptionIndexTableLength+1];
+            targetExceptionsAttribute.u2exceptionIndexTable = new int[exceptionIndexTableLength+1];
             System.arraycopy(exceptionIndexTable, 0,
-                             exceptionsAttribute.u2exceptionIndexTable, 0,
+                             targetExceptionsAttribute.u2exceptionIndexTable, 0,
                              exceptionIndexTableLength);
-            exceptionIndexTable = exceptionsAttribute.u2exceptionIndexTable;
+            exceptionIndexTable = targetExceptionsAttribute.u2exceptionIndexTable;
         }
 
         // Add the exception.
-        exceptionIndexTable[exceptionsAttribute.u2exceptionIndexTableLength++] = exceptionIndex;
+        exceptionIndexTable[targetExceptionsAttribute.u2exceptionIndexTableLength++] = exceptionIndex;
     }
 }
diff --git a/src/proguard/classfile/editor/InstructionAdder.java b/src/proguard/classfile/editor/InstructionAdder.java
new file mode 100644
index 0000000..ffd3d81
--- /dev/null
+++ b/src/proguard/classfile/editor/InstructionAdder.java
@@ -0,0 +1,76 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with 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.instruction.visitor.InstructionVisitor;
+import proguard.classfile.instruction.*;
+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).shrink();
+
+        // Add the instruction.
+        codeAttributeComposer.appendInstruction(offset, newConstantInstruction);
+    }
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/InstructionWriter.java b/src/proguard/classfile/editor/InstructionWriter.java
index c82fa76..c7e3010 100644
--- a/src/proguard/classfile/editor/InstructionWriter.java
+++ b/src/proguard/classfile/editor/InstructionWriter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/editor/ExceptionAdder.java b/src/proguard/classfile/editor/InterfaceAdder.java
similarity index 56%
copy from src/proguard/classfile/editor/ExceptionAdder.java
copy to src/proguard/classfile/editor/InterfaceAdder.java
index 91e9a22..881b034 100644
--- a/src/proguard/classfile/editor/ExceptionAdder.java
+++ b/src/proguard/classfile/editor/InterfaceAdder.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,37 +21,35 @@
 package proguard.classfile.editor;
 
 import proguard.classfile.*;
-import proguard.classfile.attribute.ExceptionsAttribute;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.annotation.*;
+import proguard.classfile.attribute.preverification.*;
 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.
+ * This ConstantVisitor adds all interfaces that it visits to the given
+ * target class.
  *
  * @author Eric Lafortune
  */
-public class ExceptionAdder
+public class InterfaceAdder
 extends      SimplifiedVisitor
 implements   ConstantVisitor
 {
-    private final ExceptionsAttribute targetExceptionsAttribute;
-
-    private final ConstantAdder    constantAdder    = new ConstantAdder();
-    private final ExceptionsEditor exceptionsEditor = new ExceptionsEditor();
+    private final ConstantAdder    constantAdder;
+    private final InterfacesEditor interfacesEditor;
 
 
     /**
-     * Creates a new MemberAdder that will copy methods into the given target
-     * class.
+     * Creates a new InterfaceAdder that will add interfaces to the given
+     * target class.
      */
-  public ExceptionAdder(ProgramClass        targetClass,
-                        ExceptionsAttribute targetExceptionsAttribute)
+    public InterfaceAdder(ProgramClass targetClass)
     {
-        this.targetExceptionsAttribute = targetExceptionsAttribute;
-
-        constantAdder.setTargetClass(targetClass);
+        constantAdder    = new ConstantAdder(targetClass);
+        interfacesEditor = new InterfacesEditor(targetClass);
     }
 
 
@@ -59,9 +57,6 @@ implements   ConstantVisitor
 
     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
     {
-        constantAdder.visitClassConstant(clazz, classConstant);
-
-        exceptionsEditor.addException(targetExceptionsAttribute,
-                                      constantAdder.getConstantIndex());
+        interfacesEditor.addInterface(constantAdder.addConstant(clazz, classConstant));
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/InterfaceSorter.java b/src/proguard/classfile/editor/InterfaceSorter.java
index 80af353..30a86da 100644
--- a/src/proguard/classfile/editor/InterfaceSorter.java
+++ b/src/proguard/classfile/editor/InterfaceSorter.java
@@ -2,46 +2,66 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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.util.SimplifiedVisitor;
 import proguard.classfile.visitor.ClassVisitor;
 
 import java.util.Arrays;
 
 /**
- * This ClassVisitor sorts the interfaces of the classes that it visits.
+ * This ClassVisitor sorts the interfaces of the program classes that it visits.
  *
  * @author Eric Lafortune
  */
-public class InterfaceSorter implements ClassVisitor
+public class InterfaceSorter
+extends      SimplifiedVisitor
+implements   ClassVisitor
 {
     // Implementations for ClassVisitor.
 
     public void visitProgramClass(ProgramClass programClass)
     {
+        int[] interfaces      = programClass.u2interfaces;
+        int   interfacesCount = programClass.u2interfacesCount;
+
         // Sort the interfaces.
-        Arrays.sort(programClass.u2interfaces, 0, programClass.u2interfacesCount);
-    }
+        Arrays.sort(interfaces, 0, interfacesCount);
 
+        // Remove any duplicate entries.
+        int newInterfacesCount     = 0;
+        int previousInterfaceIndex = 0;
+        for (int index = 0; index < interfacesCount; index++)
+        {
+            int interfaceIndex = interfaces[index];
 
-    public void visitLibraryClass(LibraryClass libraryClass)
-    {
+            // Isn't this a duplicate of the previous interface?
+            if (interfaceIndex != previousInterfaceIndex)
+            {
+                interfaces[newInterfacesCount++] = interfaceIndex;
+
+                // Remember the interface.
+                previousInterfaceIndex = interfaceIndex;
+            }
+        }
+
+        programClass.u2interfacesCount = newInterfacesCount;
     }
 }
diff --git a/src/proguard/classfile/editor/InterfacesEditor.java b/src/proguard/classfile/editor/InterfacesEditor.java
new file mode 100644
index 0000000..fb35ec9
--- /dev/null
+++ b/src/proguard/classfile/editor/InterfacesEditor.java
@@ -0,0 +1,122 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with 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 java.util.Arrays;
+
+/**
+ * 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)
+        {
+            int   interfacesCount = targetClass.u2interfacesCount++;
+            int[] interfaces      = targetClass.u2interfaces;
+
+            // Is the array too small to contain the additional interface?
+            if (interfaces.length <= interfacesCount)
+            {
+                // Create a new array and copy the interfaces into it.
+                int[] newinterfaces = new int[interfacesCount + 1];
+                System.arraycopy(interfaces, 0, newinterfaces, 0, interfacesCount);
+                interfaces = newinterfaces;
+
+                targetClass.u2interfaces = interfaces;
+            }
+
+            // Append the interface.
+            interfaces[interfacesCount] = 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/src/proguard/classfile/editor/MemberAdder.java b/src/proguard/classfile/editor/MemberAdder.java
index 5150059..c2083af 100644
--- a/src/proguard/classfile/editor/MemberAdder.java
+++ b/src/proguard/classfile/editor/MemberAdder.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -35,26 +35,41 @@ 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      copyAttributes;
+//    private final boolean      addFields;
 
-    private final ConstantAdder constantAdder = new ConstantAdder();
-    private final MembersEditor membersEditor = new MembersEditor();
+    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, boolean copyAttributes)
+//     * @param addFields   specifies whether fields should be added, or fused
+//     *                    with the present fields.
+    public MemberAdder(ProgramClass targetClass)//),
+//                       boolean      addFields)
     {
-        this.targetClass    = targetClass;
-        this.copyAttributes = copyAttributes;
+        this.targetClass = targetClass;
+//        this.addFields   = addFields;
 
-        constantAdder.setTargetClass(targetClass);
+        constantAdder      = new ConstantAdder(targetClass);
+        classEditor        = new ClassEditor(targetClass);
+        constantPoolEditor = new ConstantPoolEditor(targetClass);
     }
 
 
@@ -62,80 +77,179 @@ implements   MemberVisitor
 
     public void visitProgramField(ProgramClass programClass, ProgramField programField)
     {
-        String name       = programField.getName(programClass);
-        String descriptor = programField.getDescriptor(programClass);
+        String name        = programField.getName(programClass);
+        String descriptor  = programField.getDescriptor(programClass);
+        int    accessFlags = programField.getAccessFlags();
 
-        if (targetClass.findMethod(name, descriptor) == null)
+        // Does the target class already have such a field?
+        ProgramField targetField = (ProgramField)targetClass.findField(name, descriptor);
+        if (targetField != null)
         {
-            ProgramField newProgramField = new ProgramField();
-
-            // Copy the access flags.
-            newProgramField.u2accessFlags = programField.u2accessFlags;
-
-            // Make sure the name is set in the constant pool.
-            programClass.constantPoolEntryAccept(programField.u2nameIndex,
-                                                 constantAdder);
-
-            newProgramField.u2nameIndex = constantAdder.getConstantIndex();
-
-            // Make sure the descriptor is set in the constant pool.
-            programClass.constantPoolEntryAccept(programField.u2descriptorIndex,
-                                                 constantAdder);
-
-            newProgramField.u2descriptorIndex = constantAdder.getConstantIndex();
-
-            // Copy the attributes if requested.
-            if (copyAttributes)
+            // Is the field private or static?
+            int targetAccessFlags = targetField.getAccessFlags();
+            if ((targetAccessFlags &
+                 (ClassConstants.INTERNAL_ACC_PRIVATE |
+                  ClassConstants.INTERNAL_ACC_STATIC)) != 0)
             {
-                programField.attributesAccept(programClass,
-                                              new AttributeAdder(targetClass,
-                                                                 newProgramField));
+                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;
+//            }
+        }
 
-            // Actually add the completed field.
-            membersEditor.addField(targetClass, newProgramField);
+        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);
+
+        newProgramField.setVisitorInfo(programField);
+
+        // Copy its attributes.
+        programField.attributesAccept(programClass,
+                                      new AttributeAdder(targetClass,
+                                                         newProgramField,
+                                                         false));
+
+        // Add the completed field.
+        classEditor.addField(newProgramField);
     }
 
 
     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
     {
-        String name       = programMethod.getName(programClass);
-        String descriptor = programMethod.getDescriptor(programClass);
+        String name        = programMethod.getName(programClass);
+        String descriptor  = programMethod.getDescriptor(programClass);
+        int    accessFlags = programMethod.getAccessFlags();
 
-        if (targetClass.findMethod(name, descriptor) == null)
+        // Does the target class already have such a method?
+        ProgramMethod targetMethod = (ProgramMethod)targetClass.findMethod(name, descriptor);
+        if (targetMethod != null)
         {
-            ProgramMethod newProgramMethod = new ProgramMethod();
+            // is this source method abstract?
+            if ((accessFlags & ClassConstants.INTERNAL_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.INTERNAL_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.INTERNAL_ACC_FINAL;
+
+                // Add and replace the attributes.
+                programMethod.attributesAccept(programClass,
+                                               new AttributeAdder(targetClass,
+                                                                  targetMethod,
+                                                                  true));
 
-            // Copy the access flags.
-            newProgramMethod.u2accessFlags = programMethod.u2accessFlags;
+                // Don't add a new method.
+                return;
+            }
 
-            // Make sure the name is set in the constant pool.
-            programClass.constantPoolEntryAccept(programMethod.u2nameIndex,
-                                                 constantAdder);
+            if (DEBUG)
+            {
+                System.out.println("MemberAdder: renaming method ["+targetClass.getName()+"."+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]");
+            }
 
-            newProgramMethod.u2nameIndex = constantAdder.getConstantIndex();
+            // Rename the private (non-abstract) or static method.
+            targetMethod.u2nameIndex =
+                constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, descriptor));
+        }
 
-            // Make sure the descriptor is set in the constant pool.
-            programClass.constantPoolEntryAccept(programMethod.u2descriptorIndex,
-                                                 constantAdder);
+        if (DEBUG)
+        {
+            System.out.println("MemberAdder: copying method ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
+        }
 
-            newProgramMethod.u2descriptorIndex = constantAdder.getConstantIndex();
+        // Create a copy of the method.
+        ProgramMethod newProgramMethod =
+            new ProgramMethod(accessFlags & ~ClassConstants.INTERNAL_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);
+
+        newProgramMethod.setVisitorInfo(programMethod);
+
+        // Copy its attributes.
+        programMethod.attributesAccept(programClass,
+                                       new AttributeAdder(targetClass,
+                                                          newProgramMethod,
+                                                          false));
+
+        // Add the completed method.
+        classEditor.addMethod(newProgramMethod);
+    }
 
-            // Start with an empty list of attributes.
-            newProgramMethod.u2attributesCount = 0;
-            newProgramMethod.attributes        = EMPTY_ATTRIBUTES;
 
-            // Copy the attributes if requested.
-            if (copyAttributes)
-            {
-                programMethod.attributesAccept(programClass,
-                                               new AttributeAdder(targetClass,
-                                                                  newProgramMethod));
-            }
+    // Small utility methods.
 
-            // Actually add the completed method.
-            membersEditor.addMethod(targetClass, newProgramMethod);
-        }
+    /**
+     * Returns a unique class member name, based on the given name and descriptor.
+     */
+    private String newUniqueMemberName(String name, String descriptor)
+    {
+        return name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ?
+            ClassConstants.INTERNAL_METHOD_NAME_INIT :
+            name + ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode()));
     }
 }
diff --git a/src/proguard/classfile/editor/MemberReferenceFixer.java b/src/proguard/classfile/editor/MemberReferenceFixer.java
index cee33af..d78a08c 100644
--- a/src/proguard/classfile/editor/MemberReferenceFixer.java
+++ b/src/proguard/classfile/editor/MemberReferenceFixer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -48,8 +48,7 @@ implements   ClassVisitor,
     private static final boolean DEBUG = false;
 
 
-    private final ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor();
-    private final StackSizeUpdater   stackSizeUpdater   = new StackSizeUpdater();
+    private final StackSizeUpdater stackSizeUpdater = new StackSizeUpdater();
 
     // Parameter for the visitor methods.
     private int constantIndex;
@@ -78,7 +77,7 @@ implements   ClassVisitor,
             }
         }
 
-        // Fix class members.
+        // Fix the class members.
         programClass.fieldsAccept(this);
         programClass.methodsAccept(this);
 
@@ -113,8 +112,7 @@ implements   ClassVisitor,
 
                 // Update the name.
                 stringConstant.u2stringIndex =
-                    constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                       newName);
+                    new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newName);
             }
         }
     }
@@ -142,9 +140,7 @@ implements   ClassVisitor,
 
                 // Update the name and type index.
                 fieldrefConstant.u2nameAndTypeIndex =
-                    constantPoolEditor.addNameAndTypeConstant((ProgramClass)clazz,
-                                                              newName,
-                                                              newType);
+                    new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(newName, newType);
             }
         }
     }
@@ -172,9 +168,7 @@ implements   ClassVisitor,
 
                 // Update the name and type index.
                 interfaceMethodrefConstant.u2nameAndTypeIndex =
-                    constantPoolEditor.addNameAndTypeConstant((ProgramClass)clazz,
-                                                              newName,
-                                                              newType);
+                    new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(newName, newType);
 
                 // Remember that the stack sizes of the methods in this class
                 // may have changed.
@@ -230,9 +224,7 @@ implements   ClassVisitor,
 
                 // Update the name and type index.
                 methodrefConstant.u2nameAndTypeIndex =
-                    constantPoolEditor.addNameAndTypeConstant((ProgramClass)clazz,
-                                                              newName,
-                                                              newType);
+                    new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(newName, newType);
 
                 // Remember that the stack sizes of the methods in this class
                 // may have changed.
@@ -311,8 +303,7 @@ implements   ClassVisitor,
             {
                 // Update the class index.
                 enclosingMethodAttribute.u2classIndex =
-                    constantPoolEditor.addClassConstant((ProgramClass)clazz,
-                                                        referencedClass);
+                    new ConstantPoolEditor((ProgramClass)clazz).addClassConstant(referencedClass);
             }
 
             // Does it have a new name or type?
@@ -321,9 +312,8 @@ implements   ClassVisitor,
             {
                 // Update the name and type index.
                 enclosingMethodAttribute.u2nameAndTypeIndex =
-                    constantPoolEditor.addNameAndTypeConstant((ProgramClass)clazz,
-                                                              referencedMember.getName(referencedClass),
-                                                              referencedMember.getDescriptor(referencedClass));
+                    new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(referencedMember.getName(referencedClass),
+                                                                                       referencedMember.getDescriptor(referencedClass));
             }
         }
     }
@@ -334,7 +324,7 @@ implements   ClassVisitor,
         // Recompute the maximum stack size if necessary.
         if (stackSizesMayHaveChanged)
         {
-            stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
+                stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
         }
 
         // Fix the nested attributes.
@@ -431,8 +421,7 @@ implements   ClassVisitor,
             {
                 // Update the element name index.
                 elementValue.u2elementNameIndex =
-                    constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                       newMethodName);
+                    new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newMethodName);
             }
         }
     }
diff --git a/src/proguard/classfile/editor/MembersEditor.java b/src/proguard/classfile/editor/MembersEditor.java
deleted file mode 100644
index fb47b93..0000000
--- a/src/proguard/classfile/editor/MembersEditor.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- *             of Java bytecode.
- *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with 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 class members to classes. Class members to be added must
- * be filled out beforehand, including their references to the constant pool.
- *
- * @author Eric Lafortune
- */
-public class MembersEditor
-{
-    private static final boolean DEBUG = false;
-
-
-    /**
-     * Adds a given field to the given class.
-     */
-    public void addField(ProgramClass programClass,
-                         Field        field)
-    {
-        int     fieldsCount = programClass.u2fieldsCount;
-        Field[] fields      = programClass.fields;
-
-        // Make sure there is enough space for the new field.
-        if (fields.length <= fieldsCount)
-        {
-            programClass.fields = new ProgramField[fieldsCount+1];
-            System.arraycopy(fields, 0,
-                             programClass.fields, 0,
-                             fieldsCount);
-            fields = programClass.fields;
-        }
-
-        if (DEBUG)
-        {
-            System.out.println(programClass.getName()+": adding ["+field.getName(programClass)+field.getDescriptor(programClass)+"]");
-        }
-
-        // Add the field.
-        fields[programClass.u2fieldsCount++] = field;
-    }
-
-
-    /**
-     * Adds a given method to the given class.
-     */
-    public void addMethod(ProgramClass programClass,
-                          Method       method)
-    {
-        int      methodsCount = programClass.u2methodsCount;
-        Method[] methods      = programClass.methods;
-
-        // Make sure there is enough space for the new method.
-        if (methods.length <= methodsCount)
-        {
-            programClass.methods = new ProgramMethod[methodsCount+1];
-            System.arraycopy(methods, 0,
-                             programClass.methods, 0,
-                             methodsCount);
-            methods = programClass.methods;
-        }
-
-        if (DEBUG)
-        {
-            System.out.println(programClass.getName()+": adding ["+method.getName(programClass)+method.getDescriptor(programClass)+"]");
-        }
-
-        // Add the method.
-        methods[programClass.u2methodsCount++] = method;
-    }
-}
diff --git a/src/proguard/classfile/editor/MethodInvocationFixer.java b/src/proguard/classfile/editor/MethodInvocationFixer.java
index 21e3c1f..d60bb36 100644
--- a/src/proguard/classfile/editor/MethodInvocationFixer.java
+++ b/src/proguard/classfile/editor/MethodInvocationFixer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/constant/visitor/AllConstantVisitor.java b/src/proguard/classfile/editor/NamedAttributeDeleter.java
similarity index 66%
copy from src/proguard/classfile/constant/visitor/AllConstantVisitor.java
copy to src/proguard/classfile/editor/NamedAttributeDeleter.java
index 01c5487..a8019f2 100644
--- a/src/proguard/classfile/constant/visitor/AllConstantVisitor.java
+++ b/src/proguard/classfile/editor/NamedAttributeDeleter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,36 +18,37 @@
  * with 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;
+package proguard.classfile.editor;
 
 import proguard.classfile.*;
-import proguard.classfile.visitor.ClassVisitor;
+import proguard.classfile.visitor.*;
+import proguard.util.StringMatcher;
 
 
 /**
- * This ClassVisitor lets a given ConstantVisitor visit all constant pool
- * entries of the program classes it visits.
+ * This ClassVisitor deletes attributes with a given name in the program
+ * classes that it visits.
  *
  * @author Eric Lafortune
  */
-public class AllConstantVisitor implements ClassVisitor
+public class NamedAttributeDeleter implements ClassVisitor
 {
-    private final ConstantVisitor constantVisitor;
+    private final String attributeName;
 
 
-    public AllConstantVisitor(ConstantVisitor constantVisitor)
+    public NamedAttributeDeleter(String attributeName)
     {
-        this.constantVisitor = constantVisitor;
+        this.attributeName = attributeName;
     }
 
 
     // Implementations for ClassVisitor.
 
+    public void visitLibraryClass(LibraryClass libraryClass) {}
+
+
     public void visitProgramClass(ProgramClass programClass)
     {
-        programClass.constantPoolEntriesAccept(constantVisitor);
+        new AttributesEditor(programClass, false).deleteAttribute(attributeName);
     }
-
-
-    public void visitLibraryClass(LibraryClass libraryClass) {}
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/StackSizeUpdater.java b/src/proguard/classfile/editor/StackSizeUpdater.java
index 5ab4dd7..358e720 100644
--- a/src/proguard/classfile/editor/StackSizeUpdater.java
+++ b/src/proguard/classfile/editor/StackSizeUpdater.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameFactoryResetter.java b/src/proguard/classfile/editor/SubclassAdder.java
similarity index 68%
copy from src/proguard/obfuscate/NameFactoryResetter.java
copy to src/proguard/classfile/editor/SubclassAdder.java
index cda368c..9e204ff 100644
--- a/src/proguard/obfuscate/NameFactoryResetter.java
+++ b/src/proguard/classfile/editor/SubclassAdder.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,29 +18,29 @@
  * 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;
+package proguard.classfile.editor;
 
 import proguard.classfile.*;
 import proguard.classfile.visitor.ClassVisitor;
 
 /**
- * This ClassVisitor resets a given name factory whenever it visits a class
- * file.
+ * This ClassVisitor adds the given class to the list of subclasses of the
+ * classes that it visits.
  *
  * @author Eric Lafortune
  */
-public class NameFactoryResetter implements ClassVisitor
+public class SubclassAdder
+implements   ClassVisitor
 {
-    private final NameFactory nameFactory;
+    private final Clazz subclass;
 
 
     /**
-     * Creates a new NameFactoryResetter.
-     * @param nameFactory the name factory to be reset.
+     * Creates a new SubclassAdder that will add the given subclass.
      */
-    public NameFactoryResetter(NameFactory nameFactory)
+    public SubclassAdder(Clazz subclass)
     {
-        this.nameFactory = nameFactory;
+        this.subclass = subclass;
     }
 
 
@@ -48,12 +48,12 @@ public class NameFactoryResetter implements ClassVisitor
 
     public void visitProgramClass(ProgramClass programClass)
     {
-        nameFactory.reset();
+        programClass.addSubClass(subclass);
     }
 
 
     public void visitLibraryClass(LibraryClass libraryClass)
     {
-        nameFactory.reset();
+        libraryClass.addSubClass(subclass);
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/obfuscate/NameFactoryResetter.java b/src/proguard/classfile/editor/SubclassToAdder.java
similarity index 67%
copy from src/proguard/obfuscate/NameFactoryResetter.java
copy to src/proguard/classfile/editor/SubclassToAdder.java
index cda368c..97d96b3 100644
--- a/src/proguard/obfuscate/NameFactoryResetter.java
+++ b/src/proguard/classfile/editor/SubclassToAdder.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,29 +18,30 @@
  * 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;
+package proguard.classfile.editor;
 
 import proguard.classfile.*;
 import proguard.classfile.visitor.ClassVisitor;
 
 /**
- * This ClassVisitor resets a given name factory whenever it visits a class
- * file.
+ * This ClassVisitor adds all classes that it visits to the list of subclasses
+ * of the given target class.
  *
  * @author Eric Lafortune
  */
-public class NameFactoryResetter implements ClassVisitor
+public class SubclassToAdder
+implements   ClassVisitor
 {
-    private final NameFactory nameFactory;
+    private final Clazz targetClass;
 
 
     /**
-     * Creates a new NameFactoryResetter.
-     * @param nameFactory the name factory to be reset.
+     * Creates a new SubclassAdder that will add subclasses to the given
+     * target class.
      */
-    public NameFactoryResetter(NameFactory nameFactory)
+    public SubclassToAdder(Clazz targetClass)
     {
-        this.nameFactory = nameFactory;
+        this.targetClass = targetClass;
     }
 
 
@@ -48,12 +49,12 @@ public class NameFactoryResetter implements ClassVisitor
 
     public void visitProgramClass(ProgramClass programClass)
     {
-        nameFactory.reset();
+        targetClass.addSubClass(programClass);
     }
 
 
     public void visitLibraryClass(LibraryClass libraryClass)
     {
-        nameFactory.reset();
+        targetClass.addSubClass(libraryClass);
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/editor/VariableEditor.java b/src/proguard/classfile/editor/VariableEditor.java
index e2ee933..76556ed 100644
--- a/src/proguard/classfile/editor/VariableEditor.java
+++ b/src/proguard/classfile/editor/VariableEditor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/VariableRemapper.java b/src/proguard/classfile/editor/VariableRemapper.java
index 4877979..4728525 100644
--- a/src/proguard/classfile/editor/VariableRemapper.java
+++ b/src/proguard/classfile/editor/VariableRemapper.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/editor/VariableSizeUpdater.java b/src/proguard/classfile/editor/VariableSizeUpdater.java
index 7568a42..fe0c62a 100644
--- a/src/proguard/classfile/editor/VariableSizeUpdater.java
+++ b/src/proguard/classfile/editor/VariableSizeUpdater.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/instruction/BranchInstruction.java b/src/proguard/classfile/instruction/BranchInstruction.java
index a803840..afac36e 100644
--- a/src/proguard/classfile/instruction/BranchInstruction.java
+++ b/src/proguard/classfile/instruction/BranchInstruction.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/ConstantInstruction.java b/src/proguard/classfile/instruction/ConstantInstruction.java
index 69942de..1950b02 100644
--- a/src/proguard/classfile/instruction/ConstantInstruction.java
+++ b/src/proguard/classfile/instruction/ConstantInstruction.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/Instruction.java b/src/proguard/classfile/instruction/Instruction.java
index 630ea8b..bdd5c7f 100644
--- a/src/proguard/classfile/instruction/Instruction.java
+++ b/src/proguard/classfile/instruction/Instruction.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -707,7 +707,7 @@ public abstract class Instruction
 
 
     /**
-     * Returns whether the instruction is wide, index.e. preceded by a wide opcode.
+     * 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()
diff --git a/src/proguard/classfile/instruction/InstructionConstants.java b/src/proguard/classfile/instruction/InstructionConstants.java
index 4ee0c38..2f8e20d 100644
--- a/src/proguard/classfile/instruction/InstructionConstants.java
+++ b/src/proguard/classfile/instruction/InstructionConstants.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/InstructionFactory.java b/src/proguard/classfile/instruction/InstructionFactory.java
index 6b3b71a..bf6f8f9 100644
--- a/src/proguard/classfile/instruction/InstructionFactory.java
+++ b/src/proguard/classfile/instruction/InstructionFactory.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/InstructionUtil.java b/src/proguard/classfile/instruction/InstructionUtil.java
index 74ed3e3..f5e8d2b 100644
--- a/src/proguard/classfile/instruction/InstructionUtil.java
+++ b/src/proguard/classfile/instruction/InstructionUtil.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/LookUpSwitchInstruction.java b/src/proguard/classfile/instruction/LookUpSwitchInstruction.java
index adca0f1..a188e0b 100644
--- a/src/proguard/classfile/instruction/LookUpSwitchInstruction.java
+++ b/src/proguard/classfile/instruction/LookUpSwitchInstruction.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/SimpleInstruction.java b/src/proguard/classfile/instruction/SimpleInstruction.java
index d9ada3e..c351baa 100644
--- a/src/proguard/classfile/instruction/SimpleInstruction.java
+++ b/src/proguard/classfile/instruction/SimpleInstruction.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/SwitchInstruction.java b/src/proguard/classfile/instruction/SwitchInstruction.java
index 96411c6..96fab5f 100644
--- a/src/proguard/classfile/instruction/SwitchInstruction.java
+++ b/src/proguard/classfile/instruction/SwitchInstruction.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/TableSwitchInstruction.java b/src/proguard/classfile/instruction/TableSwitchInstruction.java
index 42e448c..ec94dde 100644
--- a/src/proguard/classfile/instruction/TableSwitchInstruction.java
+++ b/src/proguard/classfile/instruction/TableSwitchInstruction.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/VariableInstruction.java b/src/proguard/classfile/instruction/VariableInstruction.java
index eb025b7..220dc47 100644
--- a/src/proguard/classfile/instruction/VariableInstruction.java
+++ b/src/proguard/classfile/instruction/VariableInstruction.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java b/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
index 3ba60ea..32c507e 100644
--- a/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
+++ b/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/visitor/InstructionCounter.java b/src/proguard/classfile/instruction/visitor/InstructionCounter.java
index b472f67..5658953 100644
--- a/src/proguard/classfile/instruction/visitor/InstructionCounter.java
+++ b/src/proguard/classfile/instruction/visitor/InstructionCounter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/visitor/InstructionVisitor.java b/src/proguard/classfile/instruction/visitor/InstructionVisitor.java
index 0565802..1a6b586 100644
--- a/src/proguard/classfile/instruction/visitor/InstructionVisitor.java
+++ b/src/proguard/classfile/instruction/visitor/InstructionVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java b/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java
index 3e144da..2c373fb 100644
--- a/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java
+++ b/src/proguard/classfile/instruction/visitor/MultiInstructionVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/io/LibraryClassReader.java b/src/proguard/classfile/io/LibraryClassReader.java
index b059812..8f17031 100644
--- a/src/proguard/classfile/io/LibraryClassReader.java
+++ b/src/proguard/classfile/io/LibraryClassReader.java
@@ -2,20 +2,20 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  * more details.
  *
  * You should have received a copy of the GNU General Public License along
- * with this library; if not, write to the Free Software Foundation, Inc.,
+ * with 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;
diff --git a/src/proguard/classfile/io/ProgramClassReader.java b/src/proguard/classfile/io/ProgramClassReader.java
index 36bdced..b536e9a 100644
--- a/src/proguard/classfile/io/ProgramClassReader.java
+++ b/src/proguard/classfile/io/ProgramClassReader.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -483,10 +483,22 @@ implements   ClassVisitor,
     {
         // Read the parameter annotations.
         parameterAnnotationsAttribute.u2parametersCount           = 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.INTERNAL_METHOD_NAME_INIT))
+        {
+            int realParametersCount = ClassUtil.internalMethodParameterCount(method.getDescriptor(clazz));
+            parameterStart = realParametersCount - parameterAnnotationsAttribute.u2parametersCount;
+            parameterAnnotationsAttribute.u2parametersCount = realParametersCount;
+        }
+
         parameterAnnotationsAttribute.u2parameterAnnotationsCount = new int[parameterAnnotationsAttribute.u2parametersCount];
         parameterAnnotationsAttribute.parameterAnnotations        = new Annotation[parameterAnnotationsAttribute.u2parametersCount][];
 
-        for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++)
+        for (int parameterIndex = parameterStart; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++)
         {
             // Read the parameter annotations of the given parameter.
             int u2annotationsCount = dataInput.readUnsignedShort();
diff --git a/src/proguard/classfile/io/ProgramClassWriter.java b/src/proguard/classfile/io/ProgramClassWriter.java
index ac776c5..041de2f 100644
--- a/src/proguard/classfile/io/ProgramClassWriter.java
+++ b/src/proguard/classfile/io/ProgramClassWriter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/io/RuntimeDataInput.java b/src/proguard/classfile/io/RuntimeDataInput.java
index 94d11a3..b123b9f 100644
--- a/src/proguard/classfile/io/RuntimeDataInput.java
+++ b/src/proguard/classfile/io/RuntimeDataInput.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/io/RuntimeDataOutput.java b/src/proguard/classfile/io/RuntimeDataOutput.java
index 51684b7..89dc71d 100644
--- a/src/proguard/classfile/io/RuntimeDataOutput.java
+++ b/src/proguard/classfile/io/RuntimeDataOutput.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/AccessUtil.java b/src/proguard/classfile/util/AccessUtil.java
index 621ecc2..0f2ab64 100644
--- a/src/proguard/classfile/util/AccessUtil.java
+++ b/src/proguard/classfile/util/AccessUtil.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/ClassReferenceInitializer.java b/src/proguard/classfile/util/ClassReferenceInitializer.java
index 8e324bd..ff88b76 100644
--- a/src/proguard/classfile/util/ClassReferenceInitializer.java
+++ b/src/proguard/classfile/util/ClassReferenceInitializer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -63,7 +63,8 @@ implements   ClassVisitor,
 {
     private final ClassPool      programClassPool;
     private final ClassPool      libraryClassPool;
-    private final WarningPrinter warningPrinter;
+    private final WarningPrinter missingWarningPrinter;
+    private final WarningPrinter dependencyWarningPrinter;
 
     private final MemberFinder memberFinder = new MemberFinder();
 
@@ -71,15 +72,17 @@ implements   ClassVisitor,
     /**
      * Creates a new ClassReferenceInitializer that initializes the references
      * of all visited class files, optionally printing warnings if some classes
-     * can't be found.
+     * can't be found or if they are in the program class pool.
      */
     public ClassReferenceInitializer(ClassPool      programClassPool,
                                      ClassPool      libraryClassPool,
-                                     WarningPrinter warningPrinter)
+                                     WarningPrinter missingWarningPrinter,
+                                     WarningPrinter dependencyWarningPrinter)
     {
-        this.programClassPool = programClassPool;
-        this.libraryClassPool = libraryClassPool;
-        this.warningPrinter   = warningPrinter;
+        this.programClassPool         = programClassPool;
+        this.libraryClassPool         = libraryClassPool;
+        this.missingWarningPrinter    = missingWarningPrinter;
+        this.dependencyWarningPrinter = dependencyWarningPrinter;
     }
 
 
@@ -112,7 +115,8 @@ implements   ClassVisitor,
     public void visitProgramField(ProgramClass programClass, ProgramField programField)
     {
         programField.referencedClass =
-            findReferencedClass(programField.getDescriptor(programClass));
+            findReferencedClass(programClass.getName(),
+                                programField.getDescriptor(programClass));
 
         // Initialize the attributes.
         programField.attributesAccept(programClass, this);
@@ -122,7 +126,8 @@ implements   ClassVisitor,
     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
     {
         programMethod.referencedClasses =
-            findReferencedClasses(programMethod.getDescriptor(programClass));
+            findReferencedClasses(programClass.getName(),
+                                  programMethod.getDescriptor(programClass));
 
         // Initialize the attributes.
         programMethod.attributesAccept(programClass, this);
@@ -132,14 +137,16 @@ implements   ClassVisitor,
     public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
     {
         libraryField.referencedClass =
-            findReferencedClass(libraryField.getDescriptor(libraryClass));
+            findReferencedClass(libraryClass.getName(),
+                                libraryField.getDescriptor(libraryClass));
     }
 
 
     public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
     {
         libraryMethod.referencedClasses =
-            findReferencedClasses(libraryMethod.getDescriptor(libraryClass));
+            findReferencedClasses(libraryClass.getName(),
+                                  libraryMethod.getDescriptor(libraryClass));
     }
 
 
@@ -152,7 +159,7 @@ implements   ClassVisitor,
     {
         // Fill out the String class.
         stringConstant.javaLangStringClass =
-            findClass(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING);
+            findClass(clazz.getName(), ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING);
     }
 
 
@@ -163,7 +170,7 @@ implements   ClassVisitor,
         // 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(className);
+        Clazz referencedClass = findClass(clazz.getName(), className);
 
         if (referencedClass != null &&
             !ClassUtil.isInternalArrayType(className))
@@ -183,10 +190,10 @@ implements   ClassVisitor,
             refConstant.referencedClass  = memberFinder.correspondingClass();
 
             if (refConstant.referencedMember == null &&
-                warningPrinter != null)
+                missingWarningPrinter != null)
             {
                 // We've haven't found the class member anywhere in the hierarchy.
-                warningPrinter.print("Warning: " +
+                missingWarningPrinter.print("Warning: " +
                                      ClassUtil.externalClassName(clazz.getName()) +
                                      ": can't find referenced " +
                                      (isFieldRef ?
@@ -201,13 +208,15 @@ implements   ClassVisitor,
 
     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
     {
+        String className = clazz.getName();
+
         // Fill out the referenced class.
         classConstant.referencedClass =
-            findClass(classConstant.getName(clazz));
+            findClass(className, classConstant.getName(clazz));
 
         // Fill out the Class class.
         classConstant.javaLangClassClass =
-            findClass(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS);
+            findClass(className, ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS);
     }
 
 
@@ -218,20 +227,21 @@ implements   ClassVisitor,
 
     public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
     {
-        String className = enclosingMethodAttribute.getClassName(clazz);
+        String className          = clazz.getName();
+        String enclosingClassName = enclosingMethodAttribute.getClassName(clazz);
 
         // See if we can find the referenced class.
-        Clazz referencedClass = findClass(className);
+        Clazz referencedClass = findClass(className, enclosingClassName);
 
         if (referencedClass == null)
         {
             // We couldn't find the enclosing class.
-            if (warningPrinter != null)
+            if (missingWarningPrinter != null)
             {
-                warningPrinter.print("Warning: " +
-                                     ClassUtil.externalClassName(clazz.getName()) +
+                missingWarningPrinter.print("Warning: " +
+                                     ClassUtil.externalClassName(className) +
                                      ": can't find enclosing class " +
-                                     ClassUtil.externalClassName(className));
+                                     ClassUtil.externalClassName(enclosingClassName));
             }
 
             return;
@@ -252,14 +262,14 @@ implements   ClassVisitor,
         if (referencedMethod == null)
         {
             // We couldn't find the enclosing method.
-            if (warningPrinter != null)
+            if (missingWarningPrinter != null)
             {
-                warningPrinter.print("Warning: " +
-                                     ClassUtil.externalClassName(clazz.getName()) +
+                missingWarningPrinter.print("Warning: " +
+                                     ClassUtil.externalClassName(className) +
                                      ": can't find enclosing method '" +
-                                     ClassUtil.externalFullMethodDescription(className, 0, name, type) +
+                                     ClassUtil.externalFullMethodDescription(enclosingClassName, 0, name, type) +
                                      "' in class " +
-                                     ClassUtil.externalClassName(className));
+                                     ClassUtil.externalClassName(enclosingClassName));
             }
 
             return;
@@ -295,7 +305,8 @@ implements   ClassVisitor,
     public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
     {
         signatureAttribute.referencedClasses =
-            findReferencedClasses(clazz.getString(signatureAttribute.u2signatureIndex));
+            findReferencedClasses(clazz.getName(),
+                                  clazz.getString(signatureAttribute.u2signatureIndex));
     }
 
 
@@ -325,7 +336,8 @@ implements   ClassVisitor,
     public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
     {
         localVariableInfo.referencedClass =
-            findReferencedClass(clazz.getString(localVariableInfo.u2descriptorIndex));
+            findReferencedClass(clazz.getName(),
+                                clazz.getString(localVariableInfo.u2descriptorIndex));
     }
 
 
@@ -334,7 +346,8 @@ implements   ClassVisitor,
     public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
     {
         localVariableTypeInfo.referencedClasses =
-            findReferencedClasses(clazz.getString(localVariableTypeInfo.u2signatureIndex));
+            findReferencedClasses(clazz.getName(),
+                                  clazz.getString(localVariableTypeInfo.u2signatureIndex));
     }
 
 
@@ -343,7 +356,8 @@ implements   ClassVisitor,
     public void visitAnnotation(Clazz clazz, Annotation annotation)
     {
         annotation.referencedClasses =
-            findReferencedClasses(clazz.getString(annotation.u2typeIndex));
+            findReferencedClasses(clazz.getName(),
+                                  clazz.getString(annotation.u2typeIndex));
 
         // Initialize the element values.
         annotation.elementValuesAccept(clazz, this);
@@ -363,7 +377,8 @@ implements   ClassVisitor,
         initializeElementValue(clazz, annotation, enumConstantElementValue);
 
         enumConstantElementValue.referencedClasses =
-            findReferencedClasses(clazz.getString(enumConstantElementValue.u2typeNameIndex));
+            findReferencedClasses(clazz.getName(),
+                                  clazz.getString(enumConstantElementValue.u2typeNameIndex));
     }
 
 
@@ -372,7 +387,8 @@ implements   ClassVisitor,
         initializeElementValue(clazz, annotation, classElementValue);
 
         classElementValue.referencedClasses =
-            findReferencedClasses(clazz.getString(classElementValue.u2classInfoIndex));
+            findReferencedClasses(clazz.getName(),
+                                  clazz.getString(classElementValue.u2classInfoIndex));
     }
 
 
@@ -421,7 +437,8 @@ implements   ClassVisitor,
      * Returns the single class referenced by the given descriptor, or
      * <code>null</code> if there isn't any useful reference.
      */
-    private Clazz findReferencedClass(String descriptor)
+    private Clazz findReferencedClass(String referencingClassName,
+                                      String descriptor)
     {
         DescriptorClassEnumeration enumeration =
             new DescriptorClassEnumeration(descriptor);
@@ -430,7 +447,7 @@ implements   ClassVisitor,
 
         if (enumeration.hasMoreClassNames())
         {
-            return findClass(enumeration.nextClassName());
+            return findClass(referencingClassName, enumeration.nextClassName());
         }
 
         return null;
@@ -441,7 +458,8 @@ implements   ClassVisitor,
      * Returns an array of classes referenced by the given descriptor, or
      * <code>null</code> if there aren't any useful references.
      */
-    private Clazz[] findReferencedClasses(String descriptor)
+    private Clazz[] findReferencedClasses(String referencingClassName,
+                                          String descriptor)
     {
         DescriptorClassEnumeration enumeration =
             new DescriptorClassEnumeration(descriptor);
@@ -458,7 +476,7 @@ implements   ClassVisitor,
                 String fluff = enumeration.nextFluff();
                 String name  = enumeration.nextClassName();
 
-                Clazz referencedClass = findClass(name);
+                Clazz referencedClass = findClass(referencingClassName, name);
 
                 if (referencedClass != null)
                 {
@@ -481,8 +499,15 @@ implements   ClassVisitor,
      * 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)
+    private Clazz findClass(String referencingClassName, String name)
     {
+        // Ignore any primitive array types.
+        if (ClassUtil.isInternalArrayType(name) &&
+            !ClassUtil.isInternalClassType(name))
+        {
+            return null;
+        }
+
         // First look for the class in the program class pool.
         Clazz clazz = programClassPool.getClass(name);
 
@@ -490,6 +515,25 @@ implements   ClassVisitor,
         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("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.
+            dependencyWarningPrinter.print("Warning: library class " +
+                                           ClassUtil.externalClassName(referencingClassName) +
+                                           " depends on program class " +
+                                           ClassUtil.externalClassName(name));
         }
 
         return clazz;
diff --git a/src/proguard/classfile/util/ClassSubHierarchyInitializer.java b/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
index b2f7514..c65b512 100644
--- a/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
+++ b/src/proguard/classfile/util/ClassSubHierarchyInitializer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java b/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java
index aa12165..2896a63 100644
--- a/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java
+++ b/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -34,7 +34,8 @@ import proguard.classfile.visitor.ClassVisitor;
  * references are equivalent to the names, but they are more efficient to work
  * with.
  * <p>
- * This visitor optionally prints warnings if some items can't be found.
+ * This visitor optionally prints warnings if some superclasses can't be found
+ * or if they are in the program class pool.
  *
  * @author Eric Lafortune
  */
@@ -45,21 +46,24 @@ implements   ClassVisitor,
 {
     private final ClassPool      programClassPool;
     private final ClassPool      libraryClassPool;
-    private final WarningPrinter warningPrinter;
+    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.
+     * some classes can't be found or if they are in the program class pool.
      */
     public ClassSuperHierarchyInitializer(ClassPool      programClassPool,
                                           ClassPool      libraryClassPool,
-                                          WarningPrinter warningPrinter)
+                                          WarningPrinter missingWarningPrinter,
+                                          WarningPrinter dependencyWarningPrinter)
     {
-        this.programClassPool = programClassPool;
-        this.libraryClassPool = libraryClassPool;
-        this.warningPrinter   = warningPrinter;
+        this.programClassPool         = programClassPool;
+        this.libraryClassPool         = libraryClassPool;
+        this.missingWarningPrinter    = missingWarningPrinter;
+        this.dependencyWarningPrinter = dependencyWarningPrinter;
     }
 
 
@@ -68,18 +72,10 @@ implements   ClassVisitor,
     public void visitProgramClass(ProgramClass programClass)
     {
         // Link to the super class.
-        if (programClass.u2superClass != 0)
-        {
-            programClass.constantPoolEntryAccept(programClass.u2superClass,
-                                                 this);
-        }
+        programClass.superClassConstantAccept(this);
 
         // Link to the interfaces.
-        for (int index = 0; index < programClass.u2interfacesCount; index++)
-        {
-            programClass.constantPoolEntryAccept(programClass.u2interfaces[index],
-                                                 this);
-        }
+        programClass.interfaceConstantsAccept(this);
     }
 
 
@@ -133,7 +129,7 @@ implements   ClassVisitor,
      * 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 subClassName, String name)
+    private Clazz findClass(String referencingClassName, String name)
     {
         // First look for the class in the program class pool.
         Clazz clazz = programClassPool.getClass(name);
@@ -142,16 +138,25 @@ implements   ClassVisitor,
         if (clazz == null)
         {
             clazz = libraryClassPool.getClass(name);
-        }
 
-        if (clazz == null &&
-            warningPrinter != null)
+            if (clazz == null &&
+                missingWarningPrinter != null)
+            {
+                // We didn't find the superclass or interface. Print a warning.
+                missingWarningPrinter.print("Warning: " +
+                                            ClassUtil.externalClassName(referencingClassName) +
+                                            ": can't find superclass or interface " +
+                                            ClassUtil.externalClassName(name));
+            }
+        }
+        else if (dependencyWarningPrinter != null)
         {
-            // We didn't find the superclass or interface. Print a warning.
-            warningPrinter.print("Warning: " +
-                                 ClassUtil.externalClassName(subClassName) +
-                                 ": can't find superclass or interface " +
-                                 ClassUtil.externalClassName(name));
+            // The superclass or interface was found in the program class pool.
+            // Print a warning.
+            dependencyWarningPrinter.print("Warning: library class " +
+                                           ClassUtil.externalClassName(referencingClassName) +
+                                           " extends or implements program class " +
+                                           ClassUtil.externalClassName(name));
         }
 
         return clazz;
diff --git a/src/proguard/classfile/util/ClassUtil.java b/src/proguard/classfile/util/ClassUtil.java
index 02486c5..dc46ef3 100644
--- a/src/proguard/classfile/util/ClassUtil.java
+++ b/src/proguard/classfile/util/ClassUtil.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -873,10 +873,18 @@ public class ClassUtil
         {
             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_FINAL).append(' ');
         }
+        if ((accessFlags & ClassConstants.INTERNAL_ACC_ANNOTATTION) != 0)
+        {
+            string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ANNOTATION);
+        }
         if ((accessFlags & ClassConstants.INTERNAL_ACC_INTERFACE) != 0)
         {
             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_INTERFACE).append(' ');
         }
+        else if ((accessFlags & ClassConstants.INTERNAL_ACC_ENUM) != 0)
+        {
+            string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ENUM).append(' ');
+        }
         else if ((accessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0)
         {
             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ABSTRACT).append(' ');
diff --git a/src/proguard/classfile/util/DescriptorClassEnumeration.java b/src/proguard/classfile/util/DescriptorClassEnumeration.java
index f64065d..4523722 100644
--- a/src/proguard/classfile/util/DescriptorClassEnumeration.java
+++ b/src/proguard/classfile/util/DescriptorClassEnumeration.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -100,7 +100,7 @@ public class DescriptorClassEnumeration
                 case ClassConstants.INTERNAL_TYPE_GENERIC_END:
                 {
                     nestingLevel--;
-                    break;
+                    continue loop;
                 }
                 case ClassConstants.INTERNAL_TYPE_GENERIC_BOUND:
                 {
@@ -159,6 +159,7 @@ public class DescriptorClassEnumeration
             {
                 case ClassConstants.INTERNAL_TYPE_GENERIC_START:
                 case ClassConstants.INTERNAL_TYPE_CLASS_END:
+                case ClassConstants.EXTERNAL_INNER_CLASS_SEPARATOR:
                 {
                     break loop;
                 }
@@ -195,14 +196,18 @@ public class DescriptorClassEnumeration
     {
         try
         {
-            System.out.println("Descriptor ["+args[0]+"]");
-            DescriptorClassEnumeration enumeration = new DescriptorClassEnumeration(args[0]);
-            System.out.println("Class count = "+enumeration.classCount());
-            System.out.println("  Fluff: ["+enumeration.nextFluff()+"]");
-            while (enumeration.hasMoreClassNames())
+            for (int index = 0; index < args.length; index++)
             {
-                System.out.println("  Name:  ["+enumeration.nextClassName()+"]");
+                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)
diff --git a/src/proguard/classfile/util/DynamicClassReferenceInitializer.java b/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
index 43f4f2f..d849121 100644
--- a/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
+++ b/src/proguard/classfile/util/DynamicClassReferenceInitializer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -176,6 +176,8 @@ implements   InstructionVisitor,
 
     private final ClassPool      programClassPool;
     private final ClassPool      libraryClassPool;
+    private final WarningPrinter missingNotePrinter;
+    private final WarningPrinter dependencyWarningPrinter;
     private final WarningPrinter notePrinter;
     private final StringMatcher  noteExceptionMatcher;
 
@@ -215,17 +217,22 @@ implements   InstructionVisitor,
 
     /**
      * Creates a new DynamicClassReferenceInitializer that optionally prints
-     * notes, with optional class specifications for which never to print notes.
+     * 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.notePrinter          = notePrinter;
-        this.noteExceptionMatcher = noteExceptionMatcher;
+        this.programClassPool         = programClassPool;
+        this.libraryClassPool         = libraryClassPool;
+        this.missingNotePrinter       = missingNotePrinter;
+        this.dependencyWarningPrinter = dependencyWarningPrinter;
+        this.notePrinter              = notePrinter;
+        this.noteExceptionMatcher     = noteExceptionMatcher;
     }
 
 
@@ -296,7 +303,7 @@ implements   InstructionVisitor,
         String externalClassName = stringConstant.getString(clazz);
         String internalClassName = ClassUtil.internalClassName(externalClassName);
 
-        stringConstant.referencedClass = findClass(internalClassName);
+        stringConstant.referencedClass = findClass(clazz.getName(), internalClassName);
     }
 
 
@@ -424,8 +431,15 @@ implements   InstructionVisitor,
      * 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)
+    private Clazz findClass(String referencingClassName, String name)
     {
+        // Ignore any primitive array types.
+        if (ClassUtil.isInternalArrayType(name) &&
+            !ClassUtil.isInternalClassType(name))
+        {
+            return null;
+        }
+
         // First look for the class in the program class pool.
         Clazz clazz = programClassPool.getClass(name);
 
@@ -433,6 +447,25 @@ implements   InstructionVisitor,
         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("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("Warning: library class " +
+                                           ClassUtil.externalClassName(referencingClassName) +
+                                           " depends dynamically on program class " +
+                                           ClassUtil.externalClassName(name));
         }
 
         return clazz;
diff --git a/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java b/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
index ff2ed07..b6cc51d 100644
--- a/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
+++ b/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/ExternalTypeEnumeration.java b/src/proguard/classfile/util/ExternalTypeEnumeration.java
index 271004f..bf43501 100644
--- a/src/proguard/classfile/util/ExternalTypeEnumeration.java
+++ b/src/proguard/classfile/util/ExternalTypeEnumeration.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/InstructionSequenceMatcher.java b/src/proguard/classfile/util/InstructionSequenceMatcher.java
index 00e137d..22b88c0 100644
--- a/src/proguard/classfile/util/InstructionSequenceMatcher.java
+++ b/src/proguard/classfile/util/InstructionSequenceMatcher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/InternalTypeEnumeration.java b/src/proguard/classfile/util/InternalTypeEnumeration.java
index f4f9b26..80bb608 100644
--- a/src/proguard/classfile/util/InternalTypeEnumeration.java
+++ b/src/proguard/classfile/util/InternalTypeEnumeration.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -34,6 +34,8 @@ import proguard.classfile.ClassConstants;
 public class InternalTypeEnumeration
 {
     private String descriptor;
+    private int    firstIndex;
+    private int    lastIndex;
     private int    index;
 
 
@@ -43,7 +45,24 @@ public class InternalTypeEnumeration
     public InternalTypeEnumeration(String descriptor)
     {
         this.descriptor = descriptor;
-        this.index      = descriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN) + 1;
+        this.firstIndex = descriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN);
+        this.lastIndex  = descriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE);
+        this.index      = firstIndex + 1;
+
+        if (lastIndex < 0)
+        {
+            lastIndex = descriptor.length();
+        }
+    }
+
+
+    /**
+     * Returns the formal type parameters from the descriptor, assuming it's a
+     * method descriptor.
+     */
+    public String formalTypeParameters()
+    {
+        return descriptor.substring(0, firstIndex);
     }
 
 
@@ -53,8 +72,7 @@ public class InternalTypeEnumeration
      */
     public boolean hasMoreTypes()
     {
-        return index < descriptor.length() &&
-               descriptor.charAt(index) != ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE;
+        return index < lastIndex;
     }
 
 
@@ -65,75 +83,23 @@ public class InternalTypeEnumeration
     {
         int startIndex = index;
 
-        int     nestingLevel   = 0;
-        boolean parsingRawType = true;
-        boolean parsingArrayPrefix;
-        do
-        {
-            parsingArrayPrefix = false;
+        skipArray();
 
-            char c = descriptor.charAt(index++);
-
-            if (parsingRawType)
+        char c = descriptor.charAt(index++);
+        switch (c)
+        {
+            case ClassConstants.INTERNAL_TYPE_CLASS_START:
+            case ClassConstants.INTERNAL_TYPE_GENERIC_VARIABLE_START:
             {
-                // Parse an array character, primitive type, or a token
-                // marking the beginning of an identifier (for a class or
-                // a variable type).
-                switch (c)
-                {
-                    case ClassConstants.INTERNAL_TYPE_GENERIC_START:
-                    {
-                        parsingRawType = false;
-                        nestingLevel++;
-                        break;
-                    }
-                    case ClassConstants.INTERNAL_TYPE_GENERIC_END:
-                    {
-                        parsingRawType = false;
-                        nestingLevel--;
-                        break;
-                    }
-                    case ClassConstants.INTERNAL_TYPE_ARRAY:
-                    {
-                        parsingArrayPrefix = true;
-                        break;
-                    }
-                    case ClassConstants.INTERNAL_TYPE_CLASS_START:
-                    case ClassConstants.INTERNAL_TYPE_GENERIC_VARIABLE_START:
-                    {
-                        parsingRawType = false;
-                        nestingLevel += 2;
-                        break;
-                    }
-                }
+                skipClass();
+                break;
             }
-            else
+            case ClassConstants.INTERNAL_TYPE_GENERIC_START:
             {
-                // Parse the identifier, or a token marking its end.
-                switch (c)
-                {
-                    case ClassConstants.INTERNAL_TYPE_CLASS_END:
-                        parsingRawType = true;
-                        nestingLevel -= 2;
-
-                        // Are we at the start of a type parameter?
-                        if (nestingLevel == 1 &&
-                            descriptor.charAt(index) != ClassConstants.INTERNAL_TYPE_GENERIC_END)
-                        {
-                            parsingRawType = false;
-                        }
-                        break;
-                    case ClassConstants.INTERNAL_TYPE_GENERIC_START:
-                        parsingRawType = true;
-                        nestingLevel++;
-                        break;
-                    case ClassConstants.INTERNAL_TYPE_GENERIC_BOUND:
-                        parsingRawType = true;
-                        break;
-                }
+                skipGeneric();
+                break;
             }
         }
-        while (nestingLevel > 0 || parsingArrayPrefix);
 
         return descriptor.substring(startIndex, index);
     }
@@ -145,7 +111,58 @@ public class InternalTypeEnumeration
      */
     public String returnType()
     {
-        return descriptor.substring(descriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE) + 1);
+        return descriptor.substring(lastIndex + 1);
+    }
+
+
+    // Small utility methods.
+
+    private void skipArray()
+    {
+        while (descriptor.charAt(index) == ClassConstants.INTERNAL_TYPE_ARRAY)
+        {
+            index++;
+        }
+    }
+
+
+    private void skipClass()
+    {
+        while (true)
+        {
+            char c = descriptor.charAt(index++);
+            switch (c)
+            {
+                case ClassConstants.INTERNAL_TYPE_GENERIC_START:
+                    skipGeneric();
+                    break;
+
+                case ClassConstants.INTERNAL_TYPE_CLASS_END:
+                    return;
+            }
+        }
+    }
+
+
+    private void skipGeneric()
+    {
+        int nestingLevel = 1;
+
+        do
+        {
+            char c = descriptor.charAt(index++);
+            switch (c)
+            {
+                case ClassConstants.INTERNAL_TYPE_GENERIC_START:
+                    nestingLevel++;
+                    break;
+
+                case ClassConstants.INTERNAL_TYPE_GENERIC_END:
+                    nestingLevel--;
+                    break;
+            }
+        }
+        while (nestingLevel > 0);
     }
 
 
@@ -156,15 +173,28 @@ public class InternalTypeEnumeration
     {
         try
         {
-            System.out.println("Descriptor ["+args[0]+"]");
-            InternalTypeEnumeration enumeration = new InternalTypeEnumeration(args[0]);
-
-            while (enumeration.hasMoreTypes())
+            for (int index = 0; index < args.length; index++)
             {
-                System.out.println("  Type ["+enumeration.nextType()+"]");
-            }
+                String descriptor = args[index];
+
+                System.out.println("Descriptor ["+descriptor+"]");
+                InternalTypeEnumeration enumeration = new InternalTypeEnumeration(descriptor);
+
+                if (enumeration.firstIndex >= 0)
+                {
+                    System.out.println("  Formal type parameters ["+enumeration.formalTypeParameters()+"]");
+                }
+
+                while (enumeration.hasMoreTypes())
+                {
+                    System.out.println("  Type ["+enumeration.nextType()+"]");
+                }
 
-            System.out.println("  Return type ["+enumeration.returnType()+"]");
+                if (enumeration.lastIndex < descriptor.length())
+                {
+                    System.out.println("  Return type ["+enumeration.returnType()+"]");
+                }
+            }
         }
         catch (Exception ex)
         {
diff --git a/src/proguard/classfile/util/MemberFinder.java b/src/proguard/classfile/util/MemberFinder.java
index d5c9baa..c066e10 100644
--- a/src/proguard/classfile/util/MemberFinder.java
+++ b/src/proguard/classfile/util/MemberFinder.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/MethodLinker.java b/src/proguard/classfile/util/MethodLinker.java
index 2afd59b..7857cc3 100644
--- a/src/proguard/classfile/util/MethodLinker.java
+++ b/src/proguard/classfile/util/MethodLinker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -80,9 +80,6 @@ implements   ClassVisitor,
             return;
         }
 
-        // Get the last method in the chain.
-        Member thisLastMember = lastMember(member);
-
         // See if we've already come across a method with the same name and
         // descriptor.
         String key = name + ' ' + descriptor;
@@ -90,33 +87,47 @@ implements   ClassVisitor,
 
         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
         {
-            // Get the last method in the other chain.
-            Member otherLastMember = lastMember(otherMember);
+            // 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 (!thisLastMember.equals(otherLastMember))
+        // 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)
             {
-                // Merge the two chains, with the library members last.
-                if (otherLastMember instanceof LibraryMember)
-                {
-                    thisLastMember.setVisitorInfo(otherLastMember);
-                }
-                else
-                {
-                    otherLastMember.setVisitorInfo(thisLastMember);
-                }
+                lastMember1.setVisitorInfo(lastMember2);
+            }
+            else
+            {
+                lastMember2.setVisitorInfo(lastMember1);
             }
         }
     }
 
 
-    // Small utility methods.
-
     /**
      * Finds the last class member in the linked list of related class members.
      * @param member the given class member.
diff --git a/src/proguard/classfile/util/SimplifiedVisitor.java b/src/proguard/classfile/util/SimplifiedVisitor.java
index b9fa59f..126562f 100644
--- a/src/proguard/classfile/util/SimplifiedVisitor.java
+++ b/src/proguard/classfile/util/SimplifiedVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/StringSharer.java b/src/proguard/classfile/util/StringSharer.java
index d808c78..3d9005b 100644
--- a/src/proguard/classfile/util/StringSharer.java
+++ b/src/proguard/classfile/util/StringSharer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/util/WarningPrinter.java b/src/proguard/classfile/util/WarningPrinter.java
index fd7c18c..88de32f 100644
--- a/src/proguard/classfile/util/WarningPrinter.java
+++ b/src/proguard/classfile/util/WarningPrinter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllClassVisitor.java b/src/proguard/classfile/visitor/AllClassVisitor.java
index 3e7c863..e8c67db 100644
--- a/src/proguard/classfile/visitor/AllClassVisitor.java
+++ b/src/proguard/classfile/visitor/AllClassVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllFieldVisitor.java b/src/proguard/classfile/visitor/AllFieldVisitor.java
index f9d0d56..eb0047c 100644
--- a/src/proguard/classfile/visitor/AllFieldVisitor.java
+++ b/src/proguard/classfile/visitor/AllFieldVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllMemberVisitor.java b/src/proguard/classfile/visitor/AllMemberVisitor.java
index 843aecb..d22dfd2 100644
--- a/src/proguard/classfile/visitor/AllMemberVisitor.java
+++ b/src/proguard/classfile/visitor/AllMemberVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/AllMethodVisitor.java b/src/proguard/classfile/visitor/AllMethodVisitor.java
index ace33ed..70cbf51 100644
--- a/src/proguard/classfile/visitor/AllMethodVisitor.java
+++ b/src/proguard/classfile/visitor/AllMethodVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/BottomClassFilter.java b/src/proguard/classfile/visitor/BottomClassFilter.java
index 3236554..7aaaabc 100644
--- a/src/proguard/classfile/visitor/BottomClassFilter.java
+++ b/src/proguard/classfile/visitor/BottomClassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassAccessFilter.java b/src/proguard/classfile/visitor/ClassAccessFilter.java
index a6761fa..90aee34 100644
--- a/src/proguard/classfile/visitor/ClassAccessFilter.java
+++ b/src/proguard/classfile/visitor/ClassAccessFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassCleaner.java b/src/proguard/classfile/visitor/ClassCleaner.java
index 91e6cee..5bab937 100644
--- a/src/proguard/classfile/visitor/ClassCleaner.java
+++ b/src/proguard/classfile/visitor/ClassCleaner.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -198,7 +198,7 @@ implements   ClassVisitor,
     public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
     {
         clean(sameOneFrame);
-        
+
         sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
     }
 
@@ -212,7 +212,7 @@ implements   ClassVisitor,
     public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
     {
         clean(moreZeroFrame);
-        
+
         moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
     }
 
@@ -220,7 +220,7 @@ implements   ClassVisitor,
     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);
     }
diff --git a/src/proguard/classfile/visitor/ClassCollector.java b/src/proguard/classfile/visitor/ClassCollector.java
index 252000f..24b6ed9 100644
--- a/src/proguard/classfile/visitor/ClassCollector.java
+++ b/src/proguard/classfile/visitor/ClassCollector.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/visitor/ClassCounter.java b/src/proguard/classfile/visitor/ClassCounter.java
index 63ec942..9aadce6 100644
--- a/src/proguard/classfile/visitor/ClassCounter.java
+++ b/src/proguard/classfile/visitor/ClassCounter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassForNameClassVisitor.java b/src/proguard/classfile/visitor/ClassForNameClassVisitor.java
index b4d163a..7c93e78 100644
--- a/src/proguard/classfile/visitor/ClassForNameClassVisitor.java
+++ b/src/proguard/classfile/visitor/ClassForNameClassVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassHierarchyTraveler.java b/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
index c248d3c..b0d9da2 100644
--- a/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
+++ b/src/proguard/classfile/visitor/ClassHierarchyTraveler.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassMemberVisitor.java b/src/proguard/classfile/visitor/ClassMemberVisitor.java
deleted file mode 100644
index 6735773..0000000
--- a/src/proguard/classfile/visitor/ClassMemberVisitor.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- *             of Java bytecode.
- *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with 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 ClassMemberVisitor implements MemberVisitor
-{
-    private final ClassVisitor classVisitor;
-
-    private Clazz lastVisitedClass;
-
-
-    public ClassMemberVisitor(ClassVisitor classVisitor)
-    {
-        this.classVisitor = classVisitor;
-    }
-
-
-    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/src/proguard/classfile/visitor/ClassNameFilter.java b/src/proguard/classfile/visitor/ClassNameFilter.java
index 0d3f578..f924efb 100644
--- a/src/proguard/classfile/visitor/ClassNameFilter.java
+++ b/src/proguard/classfile/visitor/ClassNameFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -46,7 +46,22 @@ public class ClassNameFilter implements ClassVisitor
     public ClassNameFilter(String       regularExpression,
                            ClassVisitor classVisitor)
     {
-        this.regularExpressionMatcher = new ListParser(new ClassNameParser()).parse(regularExpression);
+        this(new ListParser(new ClassNameParser()).parse(regularExpression),
+             classVisitor);
+    }
+
+
+    /**
+     * Creates a new ClassNameFilter.
+     * @param regularExpressionMatcher the regular expression 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;
     }
 
diff --git a/src/proguard/classfile/visitor/ClassPoolFiller.java b/src/proguard/classfile/visitor/ClassPoolFiller.java
index 2c5e813..3fd7a72 100644
--- a/src/proguard/classfile/visitor/ClassPoolFiller.java
+++ b/src/proguard/classfile/visitor/ClassPoolFiller.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassPoolVisitor.java b/src/proguard/classfile/visitor/ClassPoolVisitor.java
index b81ab89..9b15722 100644
--- a/src/proguard/classfile/visitor/ClassPoolVisitor.java
+++ b/src/proguard/classfile/visitor/ClassPoolVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassPresenceFilter.java b/src/proguard/classfile/visitor/ClassPresenceFilter.java
index 0f8250d..3b6294f 100644
--- a/src/proguard/classfile/visitor/ClassPresenceFilter.java
+++ b/src/proguard/classfile/visitor/ClassPresenceFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassPrinter.java b/src/proguard/classfile/visitor/ClassPrinter.java
index 84677c3..4d09c13 100644
--- a/src/proguard/classfile/visitor/ClassPrinter.java
+++ b/src/proguard/classfile/visitor/ClassPrinter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -97,8 +97,11 @@ implements   ClassVisitor,
         println("Minor version: 0x" + Integer.toHexString(ClassUtil.internalMinorClassVersion(programClass.u4version)));
         println("Access flags:  0x" + Integer.toHexString(programClass.u2accessFlags));
         println("  = " +
+                ((programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ANNOTATTION) != 0 ? "@ " : "") +
                 ClassUtil.externalClassAccessFlags(programClass.u2accessFlags) +
-                ((programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_INTERFACE) == 0 ? "class " : "") +
+                ((programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ENUM)      != 0 ? "enum " :
+                 (programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_INTERFACE) == 0 ? "class " :
+                                                                                             "") +
                 ClassUtil.externalClassName(programClass.getName()) +
                 (programClass.u2superClass == 0 ? "" : " extends " +
                 ClassUtil.externalClassName(programClass.getSuperName())));
@@ -107,10 +110,7 @@ implements   ClassVisitor,
 
         println("Interfaces (count = " + programClass.u2interfacesCount + "):");
         indent();
-        for (int index = 0; index < programClass.u2interfacesCount; index++)
-        {
-            println("+ " + programClass.getClassName(programClass.u2interfaces[index]));
-        }
+        programClass.interfaceConstantsAccept(this);
         outdent();
         println();
 
@@ -149,10 +149,14 @@ implements   ClassVisitor,
         println("Superclass:    " + libraryClass.getSuperName());
         println("Access flags:  0x" + Integer.toHexString(libraryClass.u2accessFlags));
         println("  = " +
+                ((libraryClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ANNOTATTION) != 0 ? "@ " : "") +
                 ClassUtil.externalClassAccessFlags(libraryClass.u2accessFlags) +
-                ((libraryClass.u2accessFlags & ClassConstants.INTERNAL_ACC_INTERFACE) == 0 ? "class " : "") +
-                ClassUtil.externalClassName(libraryClass.getName()) + " extends "  +
-                ClassUtil.externalClassName(libraryClass.getSuperName()));
+                ((libraryClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ENUM)      != 0 ? "enum " :
+                 (libraryClass.u2accessFlags & ClassConstants.INTERNAL_ACC_INTERFACE) == 0 ? "class " :
+                                                                                             "") +
+                ClassUtil.externalClassName(libraryClass.getName()) +
+                (libraryClass.getSuperName() == null ? "" : " extends "  +
+                ClassUtil.externalClassName(libraryClass.getSuperName())));
         outdent();
         println();
 
@@ -594,20 +598,9 @@ implements   ClassVisitor,
                 " InnerClassesInfo:");
 
         indent();
-        if (innerClassesInfo.u2innerClassIndex != 0)
-        {
-            clazz.constantPoolEntryAccept(innerClassesInfo.u2innerClassIndex, this);
-        }
-
-        if (innerClassesInfo.u2outerClassIndex != 0)
-        {
-            clazz.constantPoolEntryAccept(innerClassesInfo.u2outerClassIndex, this);
-        }
-
-        if (innerClassesInfo.u2innerNameIndex != 0)
-        {
-            clazz.constantPoolEntryAccept(innerClassesInfo.u2innerNameIndex, this);
-        }
+        innerClassesInfo.innerClassConstantAccept(clazz, this);
+        innerClassesInfo.outerClassConstantAccept(clazz, this);
+        innerClassesInfo.innerNameConstantAccept(clazz, this);
         outdent();
     }
 
diff --git a/src/proguard/classfile/visitor/ClassVersionFilter.java b/src/proguard/classfile/visitor/ClassVersionFilter.java
index ae0fe43..1465ded 100644
--- a/src/proguard/classfile/visitor/ClassVersionFilter.java
+++ b/src/proguard/classfile/visitor/ClassVersionFilter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/visitor/ClassVersionSetter.java b/src/proguard/classfile/visitor/ClassVersionSetter.java
index d441333..2f99af9 100644
--- a/src/proguard/classfile/visitor/ClassVersionSetter.java
+++ b/src/proguard/classfile/visitor/ClassVersionSetter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/visitor/ClassVisitor.java b/src/proguard/classfile/visitor/ClassVisitor.java
index 3e215b1..3219e7e 100644
--- a/src/proguard/classfile/visitor/ClassVisitor.java
+++ b/src/proguard/classfile/visitor/ClassVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java b/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java
index 09376ef..de8f2b1 100644
--- a/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java
+++ b/src/proguard/classfile/visitor/ConcreteClassDownTraveler.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/DotClassClassVisitor.java b/src/proguard/classfile/visitor/DotClassClassVisitor.java
index cd1cbf9..aa4b672 100644
--- a/src/proguard/classfile/visitor/DotClassClassVisitor.java
+++ b/src/proguard/classfile/visitor/DotClassClassVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/BottomClassFilter.java b/src/proguard/classfile/visitor/ExceptClassFilter.java
similarity index 68%
copy from src/proguard/classfile/visitor/BottomClassFilter.java
copy to src/proguard/classfile/visitor/ExceptClassFilter.java
index 3236554..c13cc94 100644
--- a/src/proguard/classfile/visitor/BottomClassFilter.java
+++ b/src/proguard/classfile/visitor/ExceptClassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -22,26 +22,28 @@ 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.
+ * <code>ClassVisitor</code>, except for one given class.
  *
  * @author Eric Lafortune
  */
-public class BottomClassFilter implements ClassVisitor
+public class ExceptClassFilter implements ClassVisitor
 {
+    private final Clazz        exceptClass;
     private final ClassVisitor classVisitor;
 
 
     /**
-     * Creates a new ProgramClassFilter.
-     * @param classVisitor     the <code>ClassVisitor</code> to which visits
-     *                         will be delegated.
+     * 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 BottomClassFilter(ClassVisitor classVisitor)
+    public ExceptClassFilter(Clazz        exceptClass,
+                             ClassVisitor classVisitor)
     {
+        this.exceptClass  = exceptClass;
         this.classVisitor = classVisitor;
     }
 
@@ -50,8 +52,7 @@ public class BottomClassFilter implements ClassVisitor
 
     public void visitProgramClass(ProgramClass programClass)
     {
-        // Is this a bottom class in the class hierarchy?
-        if (programClass.subClasses == null)
+        if (!programClass.equals(exceptClass))
         {
             classVisitor.visitProgramClass(programClass);
         }
@@ -60,10 +61,9 @@ public class BottomClassFilter implements ClassVisitor
 
     public void visitLibraryClass(LibraryClass libraryClass)
     {
-        // Is this a bottom class in the class hierarchy?
-        if (libraryClass.subClasses == null)
+        if (!libraryClass.equals(exceptClass))
         {
             classVisitor.visitLibraryClass(libraryClass);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/visitor/BottomClassFilter.java b/src/proguard/classfile/visitor/ExceptClassesFilter.java
similarity index 56%
copy from src/proguard/classfile/visitor/BottomClassFilter.java
copy to src/proguard/classfile/visitor/ExceptClassesFilter.java
index 3236554..11a1348 100644
--- a/src/proguard/classfile/visitor/BottomClassFilter.java
+++ b/src/proguard/classfile/visitor/ExceptClassesFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -22,27 +22,29 @@ 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.
+ * <code>ClassVisitor</code>, except for classes are in a given list.
  *
  * @author Eric Lafortune
  */
-public class BottomClassFilter implements ClassVisitor
+public class ExceptClassesFilter implements ClassVisitor
 {
+    private final Clazz[]      exceptClasses;
     private final ClassVisitor classVisitor;
 
 
     /**
-     * Creates a new ProgramClassFilter.
-     * @param classVisitor     the <code>ClassVisitor</code> to which visits
-     *                         will be delegated.
+     * 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 BottomClassFilter(ClassVisitor classVisitor)
+    public ExceptClassesFilter(Clazz[]      exceptClasses,
+                               ClassVisitor classVisitor)
     {
-        this.classVisitor = classVisitor;
+        this.exceptClasses = exceptClasses;
+        this.classVisitor  = classVisitor;
     }
 
 
@@ -50,8 +52,7 @@ public class BottomClassFilter implements ClassVisitor
 
     public void visitProgramClass(ProgramClass programClass)
     {
-        // Is this a bottom class in the class hierarchy?
-        if (programClass.subClasses == null)
+        if (!present(programClass))
         {
             classVisitor.visitProgramClass(programClass);
         }
@@ -60,10 +61,30 @@ public class BottomClassFilter implements ClassVisitor
 
     public void visitLibraryClass(LibraryClass libraryClass)
     {
-        // Is this a bottom class in the class hierarchy?
-        if (libraryClass.subClasses == null)
+        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/src/proguard/classfile/visitor/ExceptionCounter.java b/src/proguard/classfile/visitor/ExceptionCounter.java
index 578287d..6c37579 100644
--- a/src/proguard/classfile/visitor/ExceptionCounter.java
+++ b/src/proguard/classfile/visitor/ExceptionCounter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java b/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java
index 2f3e461..0989002 100644
--- a/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionExcludedOffsetFilter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/visitor/ExceptionOffsetFilter.java b/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
index 461e3d7..3114dbb 100644
--- a/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionOffsetFilter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/visitor/ExceptionRangeFilter.java b/src/proguard/classfile/visitor/ExceptionRangeFilter.java
index e6ccddc..a2e0f93 100644
--- a/src/proguard/classfile/visitor/ExceptionRangeFilter.java
+++ b/src/proguard/classfile/visitor/ExceptionRangeFilter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with 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;
 
diff --git a/src/proguard/classfile/editor/ExceptionAdder.java b/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java
similarity index 50%
copy from src/proguard/classfile/editor/ExceptionAdder.java
copy to src/proguard/classfile/visitor/ImplementedClassConstantFilter.java
index 91e9a22..9c59944 100644
--- a/src/proguard/classfile/editor/ExceptionAdder.java
+++ b/src/proguard/classfile/visitor/ImplementedClassConstantFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,40 +18,40 @@
  * with 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;
+package proguard.classfile.visitor;
 
 import proguard.classfile.*;
-import proguard.classfile.attribute.ExceptionsAttribute;
-import proguard.classfile.constant.ClassConstant;
 import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.constant.ClassConstant;
 import proguard.classfile.util.SimplifiedVisitor;
 
 /**
- * This ConstantVisitor adds all class constants that it visits to the given
- * target exceptions attribute.
+ * 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 ExceptionAdder
+public class ImplementedClassConstantFilter
 extends      SimplifiedVisitor
 implements   ConstantVisitor
 {
-    private final ExceptionsAttribute targetExceptionsAttribute;
-
-    private final ConstantAdder    constantAdder    = new ConstantAdder();
-    private final ExceptionsEditor exceptionsEditor = new ExceptionsEditor();
+    private final Clazz           implementedClass;
+    private final ConstantVisitor constantVisitor;
 
 
     /**
-     * Creates a new MemberAdder that will copy methods into the given target
-     * class.
+     * 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 ExceptionAdder(ProgramClass        targetClass,
-                        ExceptionsAttribute targetExceptionsAttribute)
+    public ImplementedClassConstantFilter(Clazz           implementedClass,
+                                          ConstantVisitor constantVisitor)
     {
-        this.targetExceptionsAttribute = targetExceptionsAttribute;
-
-        constantAdder.setTargetClass(targetClass);
+        this.implementedClass = implementedClass;
+        this.constantVisitor  = constantVisitor;
     }
 
 
@@ -59,9 +59,11 @@ implements   ConstantVisitor
 
     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
     {
-        constantAdder.visitClassConstant(clazz, classConstant);
-
-        exceptionsEditor.addException(targetExceptionsAttribute,
-                                      constantAdder.getConstantIndex());
+        Clazz referencedClass = classConstant.referencedClass;
+        if (referencedClass == null ||
+            !referencedClass.extendsOrImplements(implementedClass))
+        {
+            constantVisitor.visitClassConstant(clazz, classConstant);
+        }
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/visitor/BottomClassFilter.java b/src/proguard/classfile/visitor/ImplementedClassFilter.java
similarity index 64%
copy from src/proguard/classfile/visitor/BottomClassFilter.java
copy to src/proguard/classfile/visitor/ImplementedClassFilter.java
index 3236554..7e78cd9 100644
--- a/src/proguard/classfile/visitor/BottomClassFilter.java
+++ b/src/proguard/classfile/visitor/ImplementedClassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -22,27 +22,31 @@ 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.
+ * <code>ClassVisitor</code>, except for classes that extend or implement
+ * a given class.
  *
  * @author Eric Lafortune
  */
-public class BottomClassFilter implements ClassVisitor
+public class ImplementedClassFilter implements ClassVisitor
 {
+    private final Clazz        implementedClass;
     private final ClassVisitor classVisitor;
 
 
     /**
-     * Creates a new ProgramClassFilter.
-     * @param classVisitor     the <code>ClassVisitor</code> to which visits
-     *                         will be delegated.
+     * 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 BottomClassFilter(ClassVisitor classVisitor)
+    public ImplementedClassFilter(Clazz        implementedClass,
+                                  ClassVisitor classVisitor)
     {
-        this.classVisitor = classVisitor;
+        this.implementedClass = implementedClass;
+        this.classVisitor     = classVisitor;
     }
 
 
@@ -50,8 +54,7 @@ public class BottomClassFilter implements ClassVisitor
 
     public void visitProgramClass(ProgramClass programClass)
     {
-        // Is this a bottom class in the class hierarchy?
-        if (programClass.subClasses == null)
+        if (!programClass.extendsOrImplements(implementedClass))
         {
             classVisitor.visitProgramClass(programClass);
         }
@@ -60,10 +63,9 @@ public class BottomClassFilter implements ClassVisitor
 
     public void visitLibraryClass(LibraryClass libraryClass)
     {
-        // Is this a bottom class in the class hierarchy?
-        if (libraryClass.subClasses == null)
+        if (!libraryClass.extendsOrImplements(implementedClass))
         {
             classVisitor.visitLibraryClass(libraryClass);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java b/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java
new file mode 100644
index 0000000..a247c64
--- /dev/null
+++ b/src/proguard/classfile/visitor/ImplementingClassConstantFilter.java
@@ -0,0 +1,70 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with 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.constant.visitor.ConstantVisitor;
+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 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/src/proguard/classfile/visitor/LibraryClassFilter.java b/src/proguard/classfile/visitor/LibraryClassFilter.java
index 2c6d3d2..2e23a51 100644
--- a/src/proguard/classfile/visitor/LibraryClassFilter.java
+++ b/src/proguard/classfile/visitor/LibraryClassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/LibraryMemberFilter.java b/src/proguard/classfile/visitor/LibraryMemberFilter.java
index b8adfe4..aea455d 100644
--- a/src/proguard/classfile/visitor/LibraryMemberFilter.java
+++ b/src/proguard/classfile/visitor/LibraryMemberFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberAccessFilter.java b/src/proguard/classfile/visitor/MemberAccessFilter.java
index 0ece68b..485f5df 100644
--- a/src/proguard/classfile/visitor/MemberAccessFilter.java
+++ b/src/proguard/classfile/visitor/MemberAccessFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MemberClassAccessFilter.java b/src/proguard/classfile/visitor/MemberClassAccessFilter.java
index a2bd15a..39296cd 100644
--- a/src/proguard/classfile/visitor/MemberClassAccessFilter.java
+++ b/src/proguard/classfile/visitor/MemberClassAccessFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ClassPoolFiller.java b/src/proguard/classfile/visitor/MemberCollector.java
similarity index 61%
copy from src/proguard/classfile/visitor/ClassPoolFiller.java
copy to src/proguard/classfile/visitor/MemberCollector.java
index 2c5e813..41e3403 100644
--- a/src/proguard/classfile/visitor/ClassPoolFiller.java
+++ b/src/proguard/classfile/visitor/MemberCollector.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -23,33 +23,37 @@ package proguard.classfile.visitor;
 import proguard.classfile.*;
 import proguard.classfile.util.SimplifiedVisitor;
 
+import java.util.Set;
 
 /**
- * This ClassVisitor collects all the classes it visits in a given
- * class pool.
+ * This MemberVisitor collects the concatenated name/descriptor strings of
+ * class members that have been visited.
  *
  * @author Eric Lafortune
  */
-public class ClassPoolFiller
+public class MemberCollector
 extends      SimplifiedVisitor
-implements   ClassVisitor
+implements   MemberVisitor
 {
-    private final ClassPool classPool;
+    private final Set set;
 
 
     /**
-     * Creates a new ClassPoolFiller.
+     * Creates a new MemberCollector.
+     * @param set the <code>Set</code> in which all method names/descriptor
+     *            strings will be collected.
      */
-    public ClassPoolFiller(ClassPool classPool)
+    public MemberCollector(Set set)
     {
-        this.classPool = classPool;
+        this.set = set;
     }
 
 
-    // Implementations for ClassVisitor.
+    // Implementations for MemberVisitor.
 
-    public void visitAnyClass(Clazz clazz)
+
+    public void visitAnyMember(Clazz clazz, Member member)
     {
-        classPool.addClass(clazz);
+        set.add(member.getName(clazz) + member.getDescriptor(clazz));
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/visitor/MemberCounter.java b/src/proguard/classfile/visitor/MemberCounter.java
index 501f249..933c957 100644
--- a/src/proguard/classfile/visitor/MemberCounter.java
+++ b/src/proguard/classfile/visitor/MemberCounter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -23,7 +23,7 @@ package proguard.classfile.visitor;
 import proguard.classfile.*;
 
 /**
- * This MemberVisitor counts the number of class members that has been visited.
+ * This MemberVisitor counts the number of class members that have been visited.
  *
  * @author Eric Lafortune
  */
diff --git a/src/proguard/classfile/visitor/MemberDescriptorFilter.java b/src/proguard/classfile/visitor/MemberDescriptorFilter.java
index acaec2a..4721c77 100644
--- a/src/proguard/classfile/visitor/MemberDescriptorFilter.java
+++ b/src/proguard/classfile/visitor/MemberDescriptorFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -47,7 +47,21 @@ public class MemberDescriptorFilter implements MemberVisitor
     public MemberDescriptorFilter(String        regularExpression,
                                   MemberVisitor memberVisitor)
     {
-        this.regularExpressionMatcher = new ClassNameParser().parse(regularExpression);
+        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;
     }
 
diff --git a/src/proguard/classfile/visitor/MemberNameFilter.java b/src/proguard/classfile/visitor/MemberNameFilter.java
index c3cf35d..935f1ad 100644
--- a/src/proguard/classfile/visitor/MemberNameFilter.java
+++ b/src/proguard/classfile/visitor/MemberNameFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -47,7 +47,21 @@ public class MemberNameFilter implements MemberVisitor
     public MemberNameFilter(String        regularExpression,
                             MemberVisitor memberVisitor)
     {
-        this.regularExpressionMatcher = new NameParser().parse(regularExpression);
+        this(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;
     }
 
diff --git a/src/proguard/classfile/visitor/MemberToClassVisitor.java b/src/proguard/classfile/visitor/MemberToClassVisitor.java
index b332c89..2f75efe 100644
--- a/src/proguard/classfile/visitor/MemberToClassVisitor.java
+++ b/src/proguard/classfile/visitor/MemberToClassVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -25,7 +25,7 @@ import proguard.classfile.*;
 
 /**
  * This MemberVisitor delegates all visits to a given ClassVisitor.
- * The latter visits the class  of each visited class member, although
+ * The latter visits the class of each visited class member, although
  * never twice in a row.
  *
  * @author Eric Lafortune
diff --git a/src/proguard/classfile/visitor/MemberVisitor.java b/src/proguard/classfile/visitor/MemberVisitor.java
index 6ea3209..96caaee 100644
--- a/src/proguard/classfile/visitor/MemberVisitor.java
+++ b/src/proguard/classfile/visitor/MemberVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MethodImplementationFilter.java b/src/proguard/classfile/visitor/MethodImplementationFilter.java
index 7b6bb33..4b97050 100644
--- a/src/proguard/classfile/visitor/MethodImplementationFilter.java
+++ b/src/proguard/classfile/visitor/MethodImplementationFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MethodImplementationTraveler.java b/src/proguard/classfile/visitor/MethodImplementationTraveler.java
index 2393c3b..c9bd99e 100644
--- a/src/proguard/classfile/visitor/MethodImplementationTraveler.java
+++ b/src/proguard/classfile/visitor/MethodImplementationTraveler.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -25,8 +25,8 @@ import proguard.classfile.util.SimplifiedVisitor;
 
 /**
  * This <code>MemberVisitor</code> lets a given <code>MemberVisitor</code>
- * travel to all concrete implementations of the visited methods in their class
- * hierarchies.
+ * travel to all concrete and abstract implementations of the visited methods
+ * in their class hierarchies.
  *
  * @author Eric Lafortune
  */
@@ -35,21 +35,36 @@ 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 memberVisitor     the <code>MemberVisitor</code> to which
-     *                          visits will be delegated.
+     * @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.memberVisitor   = memberVisitor;
+        this.visitThisMethod        = visitThisMethod;
+        this.visitSuperMethods      = visitSuperMethods;
+        this.visitInterfaceMethods  = visitInterfaceMethods;
+        this.visitOverridingMethods = visitOverridingMethods;
+        this.memberVisitor          = memberVisitor;
     }
 
 
@@ -57,16 +72,57 @@ implements   MemberVisitor
 
     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
     {
-        programClass.methodImplementationsAccept(programMethod,
-                                                 visitThisMethod,
-                                                 memberVisitor);
+        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.INTERNAL_ACC_PRIVATE |
+                                                                ClassConstants.INTERNAL_ACC_STATIC,
+                                         memberVisitor)));
+        }
     }
 
 
     public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
     {
-        libraryClass.methodImplementationsAccept(libraryMethod,
-                                                 visitThisMethod,
-                                                 memberVisitor);
+        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.INTERNAL_ACC_PRIVATE |
+                                                                ClassConstants.INTERNAL_ACC_STATIC,
+                                         memberVisitor)));
+        }
+    }
+
+
+    // Small utility methods.
+
+    private boolean isSpecial(Clazz clazz, Method method)
+    {
+        return (method.getAccessFlags() &
+                (ClassConstants.INTERNAL_ACC_PRIVATE |
+                 ClassConstants.INTERNAL_ACC_STATIC)) != 0 ||
+               method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT);
     }
 }
diff --git a/src/proguard/classfile/visitor/MultiClassPoolVisitor.java b/src/proguard/classfile/visitor/MultiClassPoolVisitor.java
index bbe6e60..13d4b3e 100644
--- a/src/proguard/classfile/visitor/MultiClassPoolVisitor.java
+++ b/src/proguard/classfile/visitor/MultiClassPoolVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MultiClassVisitor.java b/src/proguard/classfile/visitor/MultiClassVisitor.java
index a7792c8..0259b73 100644
--- a/src/proguard/classfile/visitor/MultiClassVisitor.java
+++ b/src/proguard/classfile/visitor/MultiClassVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/MultiMemberVisitor.java b/src/proguard/classfile/visitor/MultiMemberVisitor.java
index a23326c..9edfeb7 100644
--- a/src/proguard/classfile/visitor/MultiMemberVisitor.java
+++ b/src/proguard/classfile/visitor/MultiMemberVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/NamedClassVisitor.java b/src/proguard/classfile/visitor/NamedClassVisitor.java
index 0628e41..a7aabc2 100644
--- a/src/proguard/classfile/visitor/NamedClassVisitor.java
+++ b/src/proguard/classfile/visitor/NamedClassVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/NamedFieldVisitor.java b/src/proguard/classfile/visitor/NamedFieldVisitor.java
index 5c654b5..bb47b27 100644
--- a/src/proguard/classfile/visitor/NamedFieldVisitor.java
+++ b/src/proguard/classfile/visitor/NamedFieldVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -46,6 +46,8 @@ public class NamedFieldVisitor implements ClassVisitor
     }
 
 
+    // Implementations for ClassVisitor.
+
     public void visitProgramClass(ProgramClass programClass)
     {
         programClass.fieldAccept(name, descriptor, memberVisitor);
diff --git a/src/proguard/classfile/visitor/NamedMethodVisitor.java b/src/proguard/classfile/visitor/NamedMethodVisitor.java
index bb7671c..5b30fe3 100644
--- a/src/proguard/classfile/visitor/NamedMethodVisitor.java
+++ b/src/proguard/classfile/visitor/NamedMethodVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -46,6 +46,8 @@ public class NamedMethodVisitor implements ClassVisitor
     }
 
 
+    // Implementations for ClassVisitor.
+
     public void visitProgramClass(ProgramClass programClass)
     {
         programClass.methodAccept(name, descriptor, memberVisitor);
diff --git a/src/proguard/classfile/visitor/ProgramClassFilter.java b/src/proguard/classfile/visitor/ProgramClassFilter.java
index 6722800..e4ddd56 100644
--- a/src/proguard/classfile/visitor/ProgramClassFilter.java
+++ b/src/proguard/classfile/visitor/ProgramClassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ProgramMemberFilter.java b/src/proguard/classfile/visitor/ProgramMemberFilter.java
index 7c72abc..5463791 100644
--- a/src/proguard/classfile/visitor/ProgramMemberFilter.java
+++ b/src/proguard/classfile/visitor/ProgramMemberFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/ReferencedClassVisitor.java b/src/proguard/classfile/visitor/ReferencedClassVisitor.java
index a2dede2..aba4b7b 100644
--- a/src/proguard/classfile/visitor/ReferencedClassVisitor.java
+++ b/src/proguard/classfile/visitor/ReferencedClassVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -74,6 +74,10 @@ implements   ClassVisitor,
 
     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);
diff --git a/src/proguard/classfile/visitor/ReferencedMemberVisitor.java b/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
index dcbb4b0..93aba43 100644
--- a/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
+++ b/src/proguard/classfile/visitor/ReferencedMemberVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/SimilarMemberVisitor.java b/src/proguard/classfile/visitor/SimilarMemberVisitor.java
new file mode 100644
index 0000000..c62865c
--- /dev/null
+++ b/src/proguard/classfile/visitor/SimilarMemberVisitor.java
@@ -0,0 +1,125 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with 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/src/proguard/classfile/visitor/SimpleClassPrinter.java b/src/proguard/classfile/visitor/SimpleClassPrinter.java
index 73d41c5..a6e438f 100644
--- a/src/proguard/classfile/visitor/SimpleClassPrinter.java
+++ b/src/proguard/classfile/visitor/SimpleClassPrinter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/BottomClassFilter.java b/src/proguard/classfile/visitor/SubclassFilter.java
similarity index 57%
copy from src/proguard/classfile/visitor/BottomClassFilter.java
copy to src/proguard/classfile/visitor/SubclassFilter.java
index 3236554..ad3aa1f 100644
--- a/src/proguard/classfile/visitor/BottomClassFilter.java
+++ b/src/proguard/classfile/visitor/SubclassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -22,26 +22,29 @@ 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.
+ * <code>ClassVisitor</code>, except for classes that have a given class as
+ * direct subclass.
  *
  * @author Eric Lafortune
  */
-public class BottomClassFilter implements ClassVisitor
+public class SubclassFilter implements ClassVisitor
 {
+    private final Clazz        subclass;
     private final ClassVisitor classVisitor;
 
 
     /**
-     * Creates a new ProgramClassFilter.
-     * @param classVisitor     the <code>ClassVisitor</code> to which visits
-     *                         will be delegated.
+     * 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 BottomClassFilter(ClassVisitor classVisitor)
+    public SubclassFilter(Clazz        subclass,
+                          ClassVisitor classVisitor)
     {
+        this.subclass     = subclass;
         this.classVisitor = classVisitor;
     }
 
@@ -50,8 +53,7 @@ public class BottomClassFilter implements ClassVisitor
 
     public void visitProgramClass(ProgramClass programClass)
     {
-        // Is this a bottom class in the class hierarchy?
-        if (programClass.subClasses == null)
+        if (!present(programClass.subClasses))
         {
             classVisitor.visitProgramClass(programClass);
         }
@@ -60,10 +62,30 @@ public class BottomClassFilter implements ClassVisitor
 
     public void visitLibraryClass(LibraryClass libraryClass)
     {
-        // Is this a bottom class in the class hierarchy?
-        if (libraryClass.subClasses == null)
+        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/src/proguard/classfile/visitor/LibraryClassFilter.java b/src/proguard/classfile/visitor/SubclassTraveler.java
similarity index 67%
copy from src/proguard/classfile/visitor/LibraryClassFilter.java
copy to src/proguard/classfile/visitor/SubclassTraveler.java
index 2c6d3d2..97c263c 100644
--- a/src/proguard/classfile/visitor/LibraryClassFilter.java
+++ b/src/proguard/classfile/visitor/SubclassTraveler.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -24,22 +24,22 @@ import proguard.classfile.*;
 
 
 /**
- * This <code>ClassVisitor</code> delegates its visits to another given
- * <code>ClassVisitor</code>, but only when visiting library classes.
+ * This <code>ClassVisitor</code> lets a given <code>ClassVisitor</code>
+ * travel to direct subclasses of the visited class.
  *
  * @author Eric Lafortune
  */
-public class LibraryClassFilter implements ClassVisitor
+public class SubclassTraveler implements ClassVisitor
 {
     private final ClassVisitor classVisitor;
 
 
     /**
-     * Creates a new LibraryClassFilter.
-     * @param classVisitor     the <code>ClassVisitor</code> to which visits
-     *                         will be delegated.
+     * Creates a new ClassHierarchyTraveler.
+     * @param classVisitor    the <code>ClassVisitor</code> to
+     *                        which visits will be delegated.
      */
-    public LibraryClassFilter(ClassVisitor classVisitor)
+    public SubclassTraveler(ClassVisitor classVisitor)
     {
         this.classVisitor = classVisitor;
     }
@@ -49,12 +49,12 @@ public class LibraryClassFilter implements ClassVisitor
 
     public void visitProgramClass(ProgramClass programClass)
     {
-        // Don't delegate visits to program classes.
+        programClass.subclassesAccept(classVisitor);
     }
 
 
     public void visitLibraryClass(LibraryClass libraryClass)
     {
-        classVisitor.visitLibraryClass(libraryClass);
+        libraryClass.subclassesAccept(classVisitor);
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/visitor/VariableClassVisitor.java b/src/proguard/classfile/visitor/VariableClassVisitor.java
index 52d484e..673b328 100644
--- a/src/proguard/classfile/visitor/VariableClassVisitor.java
+++ b/src/proguard/classfile/visitor/VariableClassVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/classfile/visitor/VariableMemberVisitor.java b/src/proguard/classfile/visitor/VariableMemberVisitor.java
index 042c059..b6b69ee 100644
--- a/src/proguard/classfile/visitor/VariableMemberVisitor.java
+++ b/src/proguard/classfile/visitor/VariableMemberVisitor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/BasicBranchUnit.java b/src/proguard/evaluation/BasicBranchUnit.java
index a0fc96a..1a5fad4 100644
--- a/src/proguard/evaluation/BasicBranchUnit.java
+++ b/src/proguard/evaluation/BasicBranchUnit.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/BasicInvocationUnit.java b/src/proguard/evaluation/BasicInvocationUnit.java
index 3979fe2..c05bd53 100644
--- a/src/proguard/evaluation/BasicInvocationUnit.java
+++ b/src/proguard/evaluation/BasicInvocationUnit.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
@@ -42,7 +42,7 @@ implements   InvocationUnit,
              ConstantVisitor,
              MemberVisitor
 {
-    private final ValueFactory valueFactory = new ValueFactory();
+    protected final ValueFactory valueFactory;
 
     // Fields acting as parameters between the visitor methods.
     private boolean isStatic;
@@ -52,8 +52,16 @@ implements   InvocationUnit,
 
 
     /**
-     * Sets up the given variables for entering the given method.
+     * 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);
@@ -121,19 +129,12 @@ implements   InvocationUnit,
     }
 
 
-    /**
-     * Exits the given method with the given return value.
-     */
     public void exitMethod(Clazz clazz, Method method, Value returnValue)
     {
         setMethodReturnValue(clazz, method, 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)
     {
         int constantIndex = constantInstruction.constantIndex;
@@ -221,7 +222,6 @@ implements   InvocationUnit,
             setMethodParameterValue(clazz, methodrefConstant, parameterIndex, stack.pop());
         }
 
-        // Pop the reference value, if applicable.
         // Push the return value, if applicable.
         String returnType = ClassUtil.internalMethodReturnType(type);
         if (returnType.charAt(0) != ClassConstants.INTERNAL_TYPE_VOID)
@@ -231,6 +231,9 @@ implements   InvocationUnit,
     }
 
 
+    /**
+     * Sets the class thru which the specified field is accessed.
+     */
     protected void setFieldClassValue(Clazz          clazz,
                                       RefConstant    refConstant,
                                       ReferenceValue value)
@@ -239,6 +242,9 @@ implements   InvocationUnit,
     }
 
 
+    /**
+     * Returns the class thru which the specified field is accessed.
+     */
     protected Value getFieldClassValue(Clazz       clazz,
                                        RefConstant refConstant,
                                        String      type)
@@ -253,6 +259,9 @@ implements   InvocationUnit,
     }
 
 
+    /**
+     * Sets the value of the specified field.
+     */
     protected void setFieldValue(Clazz       clazz,
                                  RefConstant refConstant,
                                  Value       value)
@@ -261,6 +270,9 @@ implements   InvocationUnit,
     }
 
 
+    /**
+     * Returns the value of the specified field.
+     */
     protected Value getFieldValue(Clazz       clazz,
                                   RefConstant refConstant,
                                   String      type)
@@ -275,6 +287,9 @@ implements   InvocationUnit,
     }
 
 
+    /**
+     * Sets the value of the specified method parameter.
+     */
     protected void setMethodParameterValue(Clazz       clazz,
                                            RefConstant refConstant,
                                            int         parameterIndex,
@@ -284,6 +299,9 @@ implements   InvocationUnit,
     }
 
 
+    /**
+     * Returns the value of the specified method parameter.
+     */
     protected Value getMethodParameterValue(Clazz  clazz,
                                             Method method,
                                             int    parameterIndex,
@@ -294,6 +312,9 @@ implements   InvocationUnit,
     }
 
 
+    /**
+     * Sets the return value of the specified method.
+     */
     protected void setMethodReturnValue(Clazz  clazz,
                                         Method method,
                                         Value  value)
@@ -302,6 +323,9 @@ implements   InvocationUnit,
     }
 
 
+    /**
+     * Returns the return value of the specified method.
+     */
     protected Value getMethodReturnValue(Clazz       clazz,
                                          RefConstant refConstant,
                                          String      type)
diff --git a/src/proguard/evaluation/BranchUnit.java b/src/proguard/evaluation/BranchUnit.java
index 73c775b..9d8b1cc 100644
--- a/src/proguard/evaluation/BranchUnit.java
+++ b/src/proguard/evaluation/BranchUnit.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/InvocationUnit.java b/src/proguard/evaluation/InvocationUnit.java
index 47a4a97..f18581f 100644
--- a/src/proguard/evaluation/InvocationUnit.java
+++ b/src/proguard/evaluation/InvocationUnit.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/MutableValue.java b/src/proguard/evaluation/MutableValue.java
deleted file mode 100644
index c6e12d6..0000000
--- a/src/proguard/evaluation/MutableValue.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- *             of Java bytecode.
- *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * 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.*;
-
-/**
- * This Value is a mutable wrapper for other Value instances.
- * Its generalization method affects the contained Value as a side-effect.
- */
-class MutableValue extends Category1Value
-{
-    private Value containedValue;
-
-
-    /**
-     * Generalizes the contained value with the given value.
-     * @param otherContainedValue the other value.
-     */
-    public void generalizeContainedValue(Value otherContainedValue)
-    {
-        MutableValue lastMutableValue  = lastMutableValue();
-        Value        lastContainedValue= lastMutableValue.containedValue;
-
-        lastMutableValue.containedValue =
-            lastContainedValue == null ? otherContainedValue :
-                                         otherContainedValue.generalize(lastContainedValue);
-    }
-
-
-    /**
-     * Sets the contained value.
-     */
-    public void setContainedValue(Value containedValue)
-    {
-        lastMutableValue().containedValue = containedValue;
-    }
-
-
-    /**
-     * Returns the contained value.
-     */
-    public Value getContainedValue()
-    {
-        return lastMutableValue().containedValue;
-    }
-
-
-    // Implementations for Value.
-
-    public Value generalize(Value other)
-    {
-        MutableValue otherMutableValue = (MutableValue)other;
-
-        MutableValue thisLastMutableValue  = this.lastMutableValue();
-        MutableValue otherLastMutableValue = otherMutableValue.lastMutableValue();
-
-        Value thisLastContainedValue  = thisLastMutableValue.containedValue;
-        Value otherLastContainedValue = otherLastMutableValue.containedValue;
-
-        if (thisLastMutableValue != otherLastMutableValue)
-        {
-            otherLastMutableValue.containedValue = thisLastMutableValue;
-        }
-
-        thisLastMutableValue.containedValue =
-            thisLastContainedValue  == null ? otherLastContainedValue :
-            otherLastContainedValue == null ? thisLastContainedValue  :
-                                              thisLastContainedValue.generalize(otherLastContainedValue);
-        return thisLastMutableValue;
-    }
-
-
-    public int computationalType()
-    {
-        return 0;
-    }
-
-    public final String internalType()
-    {
-        return null;
-    }
-
-
-    // Implementations for Object.
-
-    public boolean equals(Object object)
-    {
-        if (object == null ||
-            this.getClass() != object.getClass())
-        {
-            return false;
-        }
-
-        MutableValue other = (MutableValue)object;
-        Value thisContainedValue  = this.getContainedValue();
-        Value otherContainedValue = other.getContainedValue();
-        return thisContainedValue == null ?
-            otherContainedValue == null :
-            thisContainedValue.equals(otherContainedValue);
-    }
-
-
-    public int hashCode()
-    {
-        Value containedValue  = getContainedValue();
-        return this.getClass().hashCode() ^
-               (containedValue == null ? 0 : containedValue.hashCode());
-    }
-
-
-    public String toString()
-    {
-        return containedValue == null ? "none" : containedValue.toString();
-    }
-
-
-    // Small utility methods.
-
-    public MutableValue lastMutableValue()
-    {
-        MutableValue mutableValue = this;
-
-        while (mutableValue.containedValue instanceof MutableValue)
-        {
-            mutableValue = (MutableValue)mutableValue.containedValue;
-        }
-
-        return mutableValue;
-    }
-}
diff --git a/src/proguard/evaluation/Processor.java b/src/proguard/evaluation/Processor.java
index 6a27dec..9f30010 100644
--- a/src/proguard/evaluation/Processor.java
+++ b/src/proguard/evaluation/Processor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -406,63 +406,63 @@ implements   InstructionVisitor,
                 break;
 
             case InstructionConstants.OP_I2L:
-                stack.push(stack.ipop().convertToLong(valueFactory));
+                stack.push(stack.ipop().convertToLong());
                 break;
 
             case InstructionConstants.OP_I2F:
-                stack.push(stack.ipop().convertToFloat(valueFactory));
+                stack.push(stack.ipop().convertToFloat());
                 break;
 
             case InstructionConstants.OP_I2D:
-                stack.push(stack.ipop().convertToDouble(valueFactory));
+                stack.push(stack.ipop().convertToDouble());
                 break;
 
             case InstructionConstants.OP_L2I:
-                stack.push(stack.lpop().convertToInteger(valueFactory));
+                stack.push(stack.lpop().convertToInteger());
                 break;
 
             case InstructionConstants.OP_L2F:
-                stack.push(stack.lpop().convertToFloat(valueFactory));
+                stack.push(stack.lpop().convertToFloat());
                 break;
 
             case InstructionConstants.OP_L2D:
-                stack.push(stack.lpop().convertToDouble(valueFactory));
+                stack.push(stack.lpop().convertToDouble());
                 break;
 
             case InstructionConstants.OP_F2I:
-                stack.push(stack.fpop().convertToInteger(valueFactory));
+                stack.push(stack.fpop().convertToInteger());
                 break;
 
             case InstructionConstants.OP_F2L:
-                stack.push(stack.fpop().convertToLong(valueFactory));
+                stack.push(stack.fpop().convertToLong());
                 break;
 
             case InstructionConstants.OP_F2D:
-                stack.push(stack.fpop().convertToDouble(valueFactory));
+                stack.push(stack.fpop().convertToDouble());
                 break;
 
             case InstructionConstants.OP_D2I:
-                stack.push(stack.dpop().convertToInteger(valueFactory));
+                stack.push(stack.dpop().convertToInteger());
                 break;
 
             case InstructionConstants.OP_D2L:
-                stack.push(stack.dpop().convertToLong(valueFactory));
+                stack.push(stack.dpop().convertToLong());
                 break;
 
             case InstructionConstants.OP_D2F:
-                stack.push(stack.dpop().convertToFloat(valueFactory));
+                stack.push(stack.dpop().convertToFloat());
                 break;
 
             case InstructionConstants.OP_I2B:
-                stack.push(stack.ipop().convertToByte(valueFactory));
+                stack.push(stack.ipop().convertToByte());
                 break;
 
             case InstructionConstants.OP_I2C:
-                stack.push(stack.ipop().convertToCharacter(valueFactory));
+                stack.push(stack.ipop().convertToCharacter());
                 break;
 
             case InstructionConstants.OP_I2S:
-                stack.push(stack.ipop().convertToShort(valueFactory));
+                stack.push(stack.ipop().convertToShort());
                 break;
 
             case InstructionConstants.OP_LCMP:
@@ -470,27 +470,27 @@ implements   InstructionVisitor,
 
                 LongValue longValue1 = stack.lpop();
                 LongValue longValue2 = stack.lpop();
-                stack.push(longValue2.compare(longValue1, valueFactory));
+                stack.push(longValue2.compare(longValue1));
                 break;
 
             case InstructionConstants.OP_FCMPL:
                 FloatValue floatValue1 = stack.fpop();
                 FloatValue floatValue2 = stack.fpop();
-                stack.push(floatValue2.compare(floatValue1, valueFactory));
+                stack.push(floatValue2.compare(floatValue1));
                 break;
 
             case InstructionConstants.OP_FCMPG:
-                stack.push(stack.fpop().compareReverse(stack.fpop(), valueFactory));
+                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, valueFactory));
+                stack.push(doubleValue2.compare(doubleValue1));
                 break;
 
             case InstructionConstants.OP_DCMPG:
-                stack.push(stack.dpop().compareReverse(stack.dpop(), valueFactory));
+                stack.push(stack.dpop().compareReverse(stack.dpop()));
                 break;
 
             case InstructionConstants.OP_IRETURN:
@@ -934,7 +934,7 @@ implements   InstructionVisitor,
     public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
     {
         cpValue = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING,
-                                                    stringConstant.javaLangStringClass, 
+                                                    stringConstant.javaLangStringClass,
                                                     false);
     }
 
diff --git a/src/proguard/evaluation/Stack.java b/src/proguard/evaluation/Stack.java
index 048b389..b2cb0ee 100644
--- a/src/proguard/evaluation/Stack.java
+++ b/src/proguard/evaluation/Stack.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/TracedStack.java b/src/proguard/evaluation/TracedStack.java
index 4e1abe6..cf32883 100644
--- a/src/proguard/evaluation/TracedStack.java
+++ b/src/proguard/evaluation/TracedStack.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -318,9 +318,8 @@ public class TracedStack extends Stack
             Value value         = this.values[index];
             Value producerValue = producerStack.getBottom(index);
             buffer = buffer.append('[')
-                           .append(producerValue == null ? "empty" : producerValue.toString())
-                           .append('>')
-                           .append(value         == null ? "empty" : value.toString())
+                           .append(producerValue == null ? "empty:" : producerValue.toString())
+                           .append(value         == null ? "empty"  : value.toString())
                            .append(']');
         }
 
diff --git a/src/proguard/evaluation/TracedVariables.java b/src/proguard/evaluation/TracedVariables.java
index e515101..375150f 100644
--- a/src/proguard/evaluation/TracedVariables.java
+++ b/src/proguard/evaluation/TracedVariables.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -219,9 +219,8 @@ public class TracedVariables extends Variables
             Value value         = this.values[index];
             Value producerValue = producerVariables.getValue(index);
             buffer = buffer.append('[')
-                           .append(producerValue == null ? "empty" : producerValue.toString())
-                           .append('>')
-                           .append(value         == null ? "empty" : value.toString())
+                           .append(producerValue == null ? "empty:" : producerValue.toString())
+                           .append(value         == null ? "empty"  : value.toString())
                            .append(']');
         }
 
diff --git a/src/proguard/evaluation/Variables.java b/src/proguard/evaluation/Variables.java
index 2a78260..53d5db0 100644
--- a/src/proguard/evaluation/Variables.java
+++ b/src/proguard/evaluation/Variables.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/Category1Value.java b/src/proguard/evaluation/value/Category1Value.java
index 74aa421..7db7eca 100644
--- a/src/proguard/evaluation/value/Category1Value.java
+++ b/src/proguard/evaluation/value/Category1Value.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/Category2Value.java b/src/proguard/evaluation/value/Category2Value.java
index fba6c29..95e22db 100644
--- a/src/proguard/evaluation/value/Category2Value.java
+++ b/src/proguard/evaluation/value/Category2Value.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/ComparisonValue.java
similarity index 55%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/ComparisonValue.java
index 9bb6ca8..6fcc22b 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/ComparisonValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,25 @@
 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.
+ * This IntegerValue represents the result of a comparions of two scalar
+ * values.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class ComparisonValue extends SpecificIntegerValue
 {
-    // Implementations for Value.
+    private final Value value1;
+    private final Value value2;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new comparison integer value of the two given scalar values.
+     */
+    public ComparisonValue(Value integerValue1,
+                           Value integerValue2)
     {
-        return null;
+        this.value1 = integerValue1;
+        this.value2 = integerValue2;
     }
 
 
@@ -51,19 +47,23 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.value1.equals(((ComparisonValue)object).value1) &&
+               this.value2.equals(((ComparisonValue)object).value2);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               value1.hashCode() ^
+               value2.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "("+value1+"~"+ value2 +")";
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/CompositeDoubleValue.java b/src/proguard/evaluation/value/CompositeDoubleValue.java
new file mode 100644
index 0000000..c3b4c2b
--- /dev/null
+++ b/src/proguard/evaluation/value/CompositeDoubleValue.java
@@ -0,0 +1,81 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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/src/proguard/evaluation/value/CompositeFloatValue.java b/src/proguard/evaluation/value/CompositeFloatValue.java
new file mode 100644
index 0000000..73698fb
--- /dev/null
+++ b/src/proguard/evaluation/value/CompositeFloatValue.java
@@ -0,0 +1,81 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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/src/proguard/evaluation/value/CompositeIntegerValue.java b/src/proguard/evaluation/value/CompositeIntegerValue.java
new file mode 100644
index 0000000..72ffbc9
--- /dev/null
+++ b/src/proguard/evaluation/value/CompositeIntegerValue.java
@@ -0,0 +1,87 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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/src/proguard/evaluation/value/CompositeLongValue.java b/src/proguard/evaluation/value/CompositeLongValue.java
new file mode 100644
index 0000000..7f2b5f8
--- /dev/null
+++ b/src/proguard/evaluation/value/CompositeLongValue.java
@@ -0,0 +1,87 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/ConvertedByteValue.java
similarity index 60%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/ConvertedByteValue.java
index 9bb6ca8..b32665a 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/ConvertedByteValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,22 @@
 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.
+ * This IntegerValue represents a byte value that is converted from an
+ * integer value.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class ConvertedByteValue extends SpecificIntegerValue
 {
-    // Implementations for Value.
+    private final IntegerValue value;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new converted byte value of the given integer value.
+     */
+    public ConvertedByteValue(IntegerValue value)
     {
-        return null;
+        this.value = value;
     }
 
 
@@ -51,19 +44,21 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.value.equals(((ConvertedByteValue)object).value);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               value.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "(byte)("+value+")";
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/ConvertedCharacterValue.java
similarity index 60%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/ConvertedCharacterValue.java
index 9bb6ca8..a0ce754 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/ConvertedCharacterValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,22 @@
 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.
+ * This IntegerValue represents a character value that is converted from an
+ * integer value.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class ConvertedCharacterValue extends SpecificIntegerValue
 {
-    // Implementations for Value.
+    private final IntegerValue value;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new converted character value of the given integer value.
+     */
+    public ConvertedCharacterValue(IntegerValue value)
     {
-        return null;
+        this.value = value;
     }
 
 
@@ -51,19 +44,21 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.value.equals(((ConvertedCharacterValue)object).value);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               value.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "(char)("+value+")";
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/ConvertedDoubleValue.java
similarity index 60%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/ConvertedDoubleValue.java
index 9bb6ca8..b39dce2 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/ConvertedDoubleValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,22 @@
 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.
+ * This DoubleValue represents a double value that is converted from another
+ * scalar value.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class ConvertedDoubleValue extends SpecificDoubleValue
 {
-    // Implementations for Value.
+    private final Value value;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new converted double value of the given value.
+     */
+    public ConvertedDoubleValue(Value value)
     {
-        return null;
+        this.value = value;
     }
 
 
@@ -51,19 +44,21 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.value.equals(((ConvertedDoubleValue)object).value);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               value.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "(double)("+value+")";
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/ConvertedFloatValue.java
similarity index 60%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/ConvertedFloatValue.java
index 9bb6ca8..cabf6ef 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/ConvertedFloatValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,22 @@
 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.
+ * This FloatValue represents a float value that is converted from another
+ * scalar value.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class ConvertedFloatValue extends SpecificFloatValue
 {
-    // Implementations for Value.
+    private final Value value;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new converted float value of the given value.
+     */
+    public ConvertedFloatValue(Value value)
     {
-        return null;
+        this.value = value;
     }
 
 
@@ -51,19 +44,21 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.value.equals(((ConvertedFloatValue)object).value);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               value.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "(float)("+value+")";
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/ConvertedIntegerValue.java
similarity index 60%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/ConvertedIntegerValue.java
index 9bb6ca8..3bc6b2a 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/ConvertedIntegerValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,22 @@
 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.
+ * This IntegerValue represents a integer value that is converted from another
+ * scalar value.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class ConvertedIntegerValue extends SpecificIntegerValue
 {
-    // Implementations for Value.
+    private final Value value;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new converted integer value of the given value.
+     */
+    public ConvertedIntegerValue(Value value)
     {
-        return null;
+        this.value = value;
     }
 
 
@@ -51,19 +44,21 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.value.equals(((ConvertedIntegerValue)object).value);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               value.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "(int)("+value+")";
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/ConvertedLongValue.java
similarity index 60%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/ConvertedLongValue.java
index 9bb6ca8..427a539 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/ConvertedLongValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,22 @@
 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.
+ * This LongValue represents a long value that is converted from another
+ * scalar value.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class ConvertedLongValue extends SpecificLongValue
 {
-    // Implementations for Value.
+    private final Value value;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new converted long value of the given value.
+     */
+    public ConvertedLongValue(Value value)
     {
-        return null;
+        this.value = value;
     }
 
 
@@ -51,19 +44,21 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.value.equals(((ConvertedLongValue)object).value);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               value.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "(long)("+value+")";
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/ConvertedShortValue.java
similarity index 60%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/ConvertedShortValue.java
index 9bb6ca8..183c513 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/ConvertedShortValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,22 @@
 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.
+ * This IntegerValue represents a short value that is converted from an
+ * integer value.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class ConvertedShortValue extends SpecificIntegerValue
 {
-    // Implementations for Value.
+    private final IntegerValue value;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new converted short value of the given integer value.
+     */
+    public ConvertedShortValue(IntegerValue value)
     {
-        return null;
+        this.value = value;
     }
 
 
@@ -51,19 +44,21 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.value.equals(((ConvertedShortValue)object).value);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               value.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "(short)("+value+")";
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/DoubleValue.java b/src/proguard/evaluation/value/DoubleValue.java
index b55f492..f83a639 100644
--- a/src/proguard/evaluation/value/DoubleValue.java
+++ b/src/proguard/evaluation/value/DoubleValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -27,7 +27,7 @@ import proguard.classfile.ClassConstants;
  *
  * @author Eric Lafortune
  */
-public class DoubleValue extends Category2Value
+public abstract class DoubleValue extends Category2Value
 {
     /**
      * Returns the specific double value, if applicable.
@@ -38,90 +38,83 @@ public class DoubleValue extends Category2Value
     }
 
 
+    // 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 DoubleValue generalize(DoubleValue other)
-    {
-        return this;
-    }
+    public abstract DoubleValue generalize(DoubleValue other);
 
 
     /**
      * Returns the sum of this DoubleValue and the given DoubleValue.
      */
-    public DoubleValue add(DoubleValue other)
-    {
-        return this;
-    }
+    public abstract DoubleValue add(DoubleValue other);
 
     /**
      * Returns the difference of this DoubleValue and the given DoubleValue.
      */
-    public DoubleValue subtract(DoubleValue other)
-    {
-        return this;
-    }
+    public abstract DoubleValue subtract(DoubleValue other);
 
     /**
      * Returns the difference of the given DoubleValue and this DoubleValue.
      */
-    public DoubleValue subtractFrom(DoubleValue other)
-    {
-        return this;
-    }
+    public abstract DoubleValue subtractFrom(DoubleValue other);
 
     /**
      * Returns the product of this DoubleValue and the given DoubleValue.
      */
-    public DoubleValue multiply(DoubleValue other)
-    {
-        return this;
-    }
+    public abstract DoubleValue multiply(DoubleValue other);
 
     /**
      * Returns the quotient of this DoubleValue and the given DoubleValue.
      */
-    public DoubleValue divide(DoubleValue other)
-    {
-        return this;
-    }
+    public abstract DoubleValue divide(DoubleValue other);
 
     /**
      * Returns the quotient of the given DoubleValue and this DoubleValue.
      */
-    public DoubleValue divideOf(DoubleValue other)
-    {
-        return this;
-    }
+    public abstract DoubleValue divideOf(DoubleValue other);
 
     /**
      * Returns the remainder of this DoubleValue divided by the given DoubleValue.
      */
-    public DoubleValue remainder(DoubleValue other)
-    {
-        return this;
-    }
+    public abstract DoubleValue remainder(DoubleValue other);
 
     /**
      * Returns the remainder of the given DoubleValue divided by this DoubleValue.
      */
-    public DoubleValue remainderOf(DoubleValue other)
-    {
-        return this;
-    }
+    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 IntegerValue compare(DoubleValue other, ValueFactory valueFactory)
-    {
-        return valueFactory.createIntegerValue();
-    }
+    public abstract IntegerValue compare(DoubleValue other);
 
 
     // Derived binary methods.
@@ -130,44 +123,9 @@ public class DoubleValue extends Category2Value
      * 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, ValueFactory valueFactory)
+    public final IntegerValue compareReverse(DoubleValue other)
     {
-        return compare(other, valueFactory).negate();
-    }
-
-
-    // Basic unary methods.
-
-    /**
-     * Returns the negated value of this DoubleValue.
-     */
-    public DoubleValue negate()
-    {
-        return this;
-    }
-
-    /**
-     * Converts this DoubleValue to an IntegerValue.
-     */
-    public IntegerValue convertToInteger(ValueFactory valueFactory)
-    {
-        return valueFactory.createIntegerValue();
-    }
-
-    /**
-     * Converts this DoubleValue to a LongValue.
-     */
-    public LongValue convertToLong(ValueFactory valueFactory)
-    {
-        return valueFactory.createLongValue();
-    }
-
-    /**
-     * Converts this DoubleValue to a FloatValue.
-     */
-    public FloatValue convertToFloat(ValueFactory valueFactory)
-    {
-        return valueFactory.createFloatValue();
+        return compare(other).negate();
     }
 
 
@@ -179,7 +137,7 @@ public class DoubleValue extends Category2Value
      */
     public DoubleValue generalize(SpecificDoubleValue other)
     {
-        return this;
+        return generalize((DoubleValue)other);
     }
 
 
@@ -188,7 +146,7 @@ public class DoubleValue extends Category2Value
      */
     public DoubleValue add(SpecificDoubleValue other)
     {
-        return this;
+        return add((DoubleValue)other);
     }
 
     /**
@@ -196,7 +154,7 @@ public class DoubleValue extends Category2Value
      */
     public DoubleValue subtract(SpecificDoubleValue other)
     {
-        return this;
+        return subtract((DoubleValue)other);
     }
 
     /**
@@ -204,7 +162,7 @@ public class DoubleValue extends Category2Value
      */
     public DoubleValue subtractFrom(SpecificDoubleValue other)
     {
-        return this;
+        return subtractFrom((DoubleValue)other);
     }
 
     /**
@@ -212,7 +170,7 @@ public class DoubleValue extends Category2Value
      */
     public DoubleValue multiply(SpecificDoubleValue other)
     {
-        return this;
+        return multiply((DoubleValue)other);
     }
 
     /**
@@ -220,7 +178,7 @@ public class DoubleValue extends Category2Value
      */
     public DoubleValue divide(SpecificDoubleValue other)
     {
-        return this;
+        return divide((DoubleValue)other);
     }
 
     /**
@@ -229,7 +187,7 @@ public class DoubleValue extends Category2Value
      */
     public DoubleValue divideOf(SpecificDoubleValue other)
     {
-        return this;
+        return divideOf((DoubleValue)other);
     }
 
     /**
@@ -238,7 +196,7 @@ public class DoubleValue extends Category2Value
      */
     public DoubleValue remainder(SpecificDoubleValue other)
     {
-        return this;
+        return remainder((DoubleValue)other);
     }
 
     /**
@@ -247,7 +205,7 @@ public class DoubleValue extends Category2Value
      */
     public DoubleValue remainderOf(SpecificDoubleValue other)
     {
-        return this;
+        return remainderOf((DoubleValue)other);
     }
 
     /**
@@ -255,9 +213,9 @@ public class DoubleValue extends Category2Value
      * less than, equal to, or greater than the given SpecificDoubleValue,
      * respectively.
      */
-    public IntegerValue compare(SpecificDoubleValue other, ValueFactory valueFactory)
+    public IntegerValue compare(SpecificDoubleValue other)
     {
-        return valueFactory.createIntegerValue();
+        return compare((DoubleValue)other);
     }
 
 
@@ -268,52 +226,139 @@ public class DoubleValue extends Category2Value
      * less than, equal to, or greater than the given SpecificDoubleValue,
      * respectively.
      */
-    public final IntegerValue compareReverse(SpecificDoubleValue other, ValueFactory valueFactory)
+    public final IntegerValue compareReverse(SpecificDoubleValue other)
     {
-        return compare(other, valueFactory).negate();
+        return compare(other).negate();
     }
 
 
-    // Implementations for Value.
+    // Similar binary methods, but this time with particular arguments.
 
-    public final DoubleValue doubleValue()
+    /**
+     * Returns the generalization of this DoubleValue and the given other
+     * ParticularDoubleValue.
+     */
+    public DoubleValue generalize(ParticularDoubleValue other)
     {
-        return this;
+        return generalize((SpecificDoubleValue)other);
     }
 
-    public final Value generalize(Value other)
+
+    /**
+     * Returns the sum of this DoubleValue and the given ParticularDoubleValue.
+     */
+    public DoubleValue add(ParticularDoubleValue other)
     {
-        return this.generalize(other.doubleValue());
+        return add((SpecificDoubleValue)other);
     }
 
-    public final int computationalType()
+    /**
+     * Returns the difference of this DoubleValue and the given ParticularDoubleValue.
+     */
+    public DoubleValue subtract(ParticularDoubleValue other)
     {
-        return TYPE_DOUBLE;
+        return subtract((SpecificDoubleValue)other);
     }
 
-    public final String internalType()
+    /**
+     * Returns the difference of the given ParticularDoubleValue and this DoubleValue.
+     */
+    public DoubleValue subtractFrom(ParticularDoubleValue other)
     {
-        return String.valueOf(ClassConstants.INTERNAL_TYPE_DOUBLE);
+        return subtractFrom((SpecificDoubleValue)other);
     }
 
+    /**
+     * Returns the product of this DoubleValue and the given ParticularDoubleValue.
+     */
+    public DoubleValue multiply(ParticularDoubleValue other)
+    {
+        return multiply((SpecificDoubleValue)other);
+    }
 
-    // Implementations for Object.
+    /**
+     * Returns the quotient of this DoubleValue and the given ParticularDoubleValue.
+     */
+    public DoubleValue divide(ParticularDoubleValue other)
+    {
+        return divide((SpecificDoubleValue)other);
+    }
 
-    public boolean equals(Object object)
+    /**
+     * Returns the quotient of the given ParticularDoubleValue and this
+     * DoubleValue.
+     */
+    public DoubleValue divideOf(ParticularDoubleValue other)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return divideOf((SpecificDoubleValue)other);
     }
 
+    /**
+     * Returns the remainder of this DoubleValue divided by the given
+     * ParticularDoubleValue.
+     */
+    public DoubleValue remainder(ParticularDoubleValue other)
+    {
+        return remainder((SpecificDoubleValue)other);
+    }
 
-    public int hashCode()
+    /**
+     * Returns the remainder of the given ParticularDoubleValue and this
+     * DoubleValue.
+     */
+    public DoubleValue remainderOf(ParticularDoubleValue other)
     {
-        return this.getClass().hashCode();
+        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 Value refresh()
+    {
+        return this;
+    }
+
+    public final Value generalize(Value other)
+    {
+        return this.generalize(other.doubleValue());
+    }
+
+    public final int computationalType()
+    {
+        return TYPE_DOUBLE;
+    }
 
-    public String toString()
+    public final String internalType()
     {
-        return "d";
+        return String.valueOf(ClassConstants.INTERNAL_TYPE_DOUBLE);
     }
 }
diff --git a/src/proguard/evaluation/value/FloatValue.java b/src/proguard/evaluation/value/FloatValue.java
index 5a9e87b..b981155 100644
--- a/src/proguard/evaluation/value/FloatValue.java
+++ b/src/proguard/evaluation/value/FloatValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -27,7 +27,7 @@ import proguard.classfile.ClassConstants;
  *
  * @author Eric Lafortune
  */
-public class FloatValue extends Category1Value
+public abstract class FloatValue extends Category1Value
 {
     /**
      * Returns the specific float value, if applicable.
@@ -38,90 +38,83 @@ public class FloatValue extends Category1Value
     }
 
 
+    // 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 FloatValue generalize(FloatValue other)
-    {
-        return this;
-    }
+    public abstract FloatValue generalize(FloatValue other);
 
 
     /**
      * Returns the sum of this FloatValue and the given FloatValue.
      */
-    public FloatValue add(FloatValue other)
-    {
-        return this;
-    }
+    public abstract FloatValue add(FloatValue other);
 
     /**
      * Returns the difference of this FloatValue and the given FloatValue.
      */
-    public FloatValue subtract(FloatValue other)
-    {
-        return this;
-    }
+    public abstract FloatValue subtract(FloatValue other);
 
     /**
      * Returns the difference of the given FloatValue and this FloatValue.
      */
-    public FloatValue subtractFrom(FloatValue other)
-    {
-        return this;
-    }
+    public abstract FloatValue subtractFrom(FloatValue other);
 
     /**
      * Returns the product of this FloatValue and the given FloatValue.
      */
-    public FloatValue multiply(FloatValue other)
-    {
-        return this;
-    }
+    public abstract FloatValue multiply(FloatValue other);
 
     /**
      * Returns the quotient of this FloatValue and the given FloatValue.
      */
-    public FloatValue divide(FloatValue other)
-    {
-        return this;
-    }
+    public abstract FloatValue divide(FloatValue other);
 
     /**
      * Returns the quotient of the given FloatValue and this FloatValue.
      */
-    public FloatValue divideOf(FloatValue other)
-    {
-        return this;
-    }
+    public abstract FloatValue divideOf(FloatValue other);
 
     /**
      * Returns the remainder of this FloatValue divided by the given FloatValue.
      */
-    public FloatValue remainder(FloatValue other)
-    {
-        return this;
-    }
+    public abstract FloatValue remainder(FloatValue other);
 
     /**
      * Returns the remainder of the given FloatValue divided by this FloatValue.
      */
-    public FloatValue remainderOf(FloatValue other)
-    {
-        return this;
-    }
+    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 IntegerValue compare(FloatValue other, ValueFactory valueFactory)
-    {
-        return valueFactory.createIntegerValue();
-    }
+    public abstract IntegerValue compare(FloatValue other);
 
 
     // Derived binary methods.
@@ -130,44 +123,9 @@ public class FloatValue extends Category1Value
      * 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, ValueFactory valueFactory)
-    {
-        return compare(other, valueFactory).negate();
-    }
-
-
-    // Basic unary methods.
-
-    /**
-     * Returns the negated value of this FloatValue.
-     */
-    public FloatValue negate()
-    {
-        return this;
-    }
-
-    /**
-     * Converts this FloatValue to an IntegerValue.
-     */
-    public IntegerValue convertToInteger(ValueFactory valueFactory)
-    {
-        return valueFactory.createIntegerValue();
-    }
-
-    /**
-     * Converts this FloatValue to a LongValue.
-     */
-    public LongValue convertToLong(ValueFactory valueFactory)
+    public final IntegerValue compareReverse(FloatValue other)
     {
-        return valueFactory.createLongValue();
-    }
-
-    /**
-     * Converts this FloatValue to a DoubleValue.
-     */
-    public DoubleValue convertToDouble(ValueFactory valueFactory)
-    {
-        return valueFactory.createDoubleValue();
+        return compare(other).negate();
     }
 
 
@@ -179,7 +137,7 @@ public class FloatValue extends Category1Value
      */
     public FloatValue generalize(SpecificFloatValue other)
     {
-        return this;
+        return generalize((FloatValue)other);
     }
 
 
@@ -188,7 +146,7 @@ public class FloatValue extends Category1Value
      */
     public FloatValue add(SpecificFloatValue other)
     {
-        return this;
+        return add((FloatValue)other);
     }
 
     /**
@@ -196,7 +154,7 @@ public class FloatValue extends Category1Value
      */
     public FloatValue subtract(SpecificFloatValue other)
     {
-        return this;
+        return subtract((FloatValue)other);
     }
 
     /**
@@ -204,7 +162,7 @@ public class FloatValue extends Category1Value
      */
     public FloatValue subtractFrom(SpecificFloatValue other)
     {
-        return this;
+        return subtractFrom((FloatValue)other);
     }
 
     /**
@@ -212,7 +170,7 @@ public class FloatValue extends Category1Value
      */
     public FloatValue multiply(SpecificFloatValue other)
     {
-        return this;
+        return multiply((FloatValue)other);
     }
 
     /**
@@ -220,7 +178,7 @@ public class FloatValue extends Category1Value
      */
     public FloatValue divide(SpecificFloatValue other)
     {
-        return this;
+        return divide((FloatValue)other);
     }
 
     /**
@@ -229,7 +187,7 @@ public class FloatValue extends Category1Value
      */
     public FloatValue divideOf(SpecificFloatValue other)
     {
-        return this;
+        return divideOf((FloatValue)other);
     }
 
     /**
@@ -238,7 +196,7 @@ public class FloatValue extends Category1Value
      */
     public FloatValue remainder(SpecificFloatValue other)
     {
-        return this;
+        return remainder((FloatValue)other);
     }
 
     /**
@@ -247,7 +205,7 @@ public class FloatValue extends Category1Value
      */
     public FloatValue remainderOf(SpecificFloatValue other)
     {
-        return this;
+        return remainderOf((FloatValue)other);
     }
 
     /**
@@ -255,9 +213,9 @@ public class FloatValue extends Category1Value
      * less than, equal to, or greater than the given SpecificFloatValue,
      * respectively.
      */
-    public IntegerValue compare(SpecificFloatValue other, ValueFactory valueFactory)
+    public IntegerValue compare(SpecificFloatValue other)
     {
-        return valueFactory.createIntegerValue();
+        return compare((FloatValue)other);
     }
 
 
@@ -268,52 +226,134 @@ public class FloatValue extends Category1Value
      * less than, equal to, or greater than the given SpecificFloatValue,
      * respectively.
      */
-    public final IntegerValue compareReverse(SpecificFloatValue other, ValueFactory valueFactory)
+    public final IntegerValue compareReverse(SpecificFloatValue other)
     {
-        return compare(other, valueFactory).negate();
+        return compare(other).negate();
     }
 
 
-    // Implementations for Value.
+    // Similar binary methods, but this time with particular arguments.
 
-    public final FloatValue floatValue()
+    /**
+     * Returns the generalization of this FloatValue and the given other
+     * ParticularFloatValue.
+     */
+    public FloatValue generalize(ParticularFloatValue other)
     {
-        return this;
+        return generalize((SpecificFloatValue)other);
     }
 
-    public final Value generalize(Value other)
+
+    /**
+     * Returns the sum of this FloatValue and the given ParticularFloatValue.
+     */
+    public FloatValue add(ParticularFloatValue other)
     {
-        return this.generalize(other.floatValue());
+        return add((SpecificFloatValue)other);
     }
 
-    public final int computationalType()
+    /**
+     * Returns the difference of this FloatValue and the given ParticularFloatValue.
+     */
+    public FloatValue subtract(ParticularFloatValue other)
     {
-        return TYPE_FLOAT;
+        return subtract((SpecificFloatValue)other);
     }
 
-    public final String internalType()
+    /**
+     * Returns the difference of the given ParticularFloatValue and this FloatValue.
+     */
+    public FloatValue subtractFrom(ParticularFloatValue other)
     {
-        return String.valueOf(ClassConstants.INTERNAL_TYPE_FLOAT);
+        return subtractFrom((SpecificFloatValue)other);
     }
 
+    /**
+     * Returns the product of this FloatValue and the given ParticularFloatValue.
+     */
+    public FloatValue multiply(ParticularFloatValue other)
+    {
+        return multiply((SpecificFloatValue)other);
+    }
 
-    // Implementations for Object.
+    /**
+     * Returns the quotient of this FloatValue and the given ParticularFloatValue.
+     */
+    public FloatValue divide(ParticularFloatValue other)
+    {
+        return divide((SpecificFloatValue)other);
+    }
 
-    public boolean equals(Object object)
+    /**
+     * Returns the quotient of the given ParticularFloatValue and this
+     * FloatValue.
+     */
+    public FloatValue divideOf(ParticularFloatValue other)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return divideOf((SpecificFloatValue)other);
     }
 
+    /**
+     * Returns the remainder of this FloatValue divided by the given
+     * ParticularFloatValue.
+     */
+    public FloatValue remainder(ParticularFloatValue other)
+    {
+        return remainder((SpecificFloatValue)other);
+    }
 
-    public int hashCode()
+    /**
+     * 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 this.getClass().hashCode();
+        return compare((SpecificFloatValue)other);
     }
 
 
-    public String toString()
+    // 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 "f";
+        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.INTERNAL_TYPE_FLOAT);
     }
 }
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/IdentifiedDoubleValue.java
similarity index 56%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/IdentifiedDoubleValue.java
index 9bb6ca8..44d3769 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/IdentifiedDoubleValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,23 @@
 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.
+ * This DoubleValue represents a double value that is identified by a unique ID.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class IdentifiedDoubleValue extends SpecificDoubleValue
 {
-    // Implementations for Value.
+    private final ValueFactory valuefactory;
+    private final int          id;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new double value with the given ID.
+     */
+    public IdentifiedDoubleValue(ValueFactory valuefactory, int id)
     {
-        return null;
+        this.valuefactory = valuefactory;
+        this.id           = id;
     }
 
 
@@ -51,19 +45,23 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.valuefactory.equals(((IdentifiedDoubleValue)object).valuefactory) &&
+               this.id == ((IdentifiedDoubleValue)object).id;
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               valuefactory.hashCode() ^
+               id;
     }
 
 
     public String toString()
     {
-        return "T";
+        return "d"+id;
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/IdentifiedFloatValue.java
similarity index 56%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/IdentifiedFloatValue.java
index 9bb6ca8..1bf7b51 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/IdentifiedFloatValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,23 @@
 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.
+ * This FloatValue represents a float value that is identified by a unique ID.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class IdentifiedFloatValue extends SpecificFloatValue
 {
-    // Implementations for Value.
+    private final ValueFactory valuefactory;
+    private final int          id;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new float value with the given ID.
+     */
+    public IdentifiedFloatValue(ValueFactory valuefactory, int id)
     {
-        return null;
+        this.valuefactory = valuefactory;
+        this.id           = id;
     }
 
 
@@ -51,19 +45,23 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.valuefactory.equals(((IdentifiedFloatValue)object).valuefactory) &&
+               this.id == ((IdentifiedFloatValue)object).id;
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               valuefactory.hashCode() ^
+               id;
     }
 
 
     public String toString()
     {
-        return "T";
+        return "f"+id;
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/IdentifiedIntegerValue.java
similarity index 56%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/IdentifiedIntegerValue.java
index 9bb6ca8..9c9e490 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/IdentifiedIntegerValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,23 @@
 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.
+ * This IntegerValue represents a integer value that is identified by a unique ID.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class IdentifiedIntegerValue extends SpecificIntegerValue
 {
-    // Implementations for Value.
+    private final ValueFactory valuefactory;
+    private final int          id;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new integer value with the given ID.
+     */
+    public IdentifiedIntegerValue(ValueFactory valuefactory, int id)
     {
-        return null;
+        this.valuefactory = valuefactory;
+        this.id           = id;
     }
 
 
@@ -51,19 +45,23 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.valuefactory.equals(((IdentifiedIntegerValue)object).valuefactory) &&
+               this.id == ((IdentifiedIntegerValue)object).id;
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               valuefactory.hashCode() ^
+               id;
     }
 
 
     public String toString()
     {
-        return "T";
+        return "i"+id;
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/IdentifiedLongValue.java
similarity index 57%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/IdentifiedLongValue.java
index 9bb6ca8..33bb78e 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/IdentifiedLongValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,23 @@
 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.
+ * This LongValue represents a long value that is identified by a unique ID.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class IdentifiedLongValue extends SpecificLongValue
 {
-    // Implementations for Value.
+    private final ValueFactory valuefactory;
+    private final int          id;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
-
-    public final int computationalType()
-    {
-        return TYPE_TOP;
-    }
 
-    public final String internalType()
+    /**
+     * Creates a new long value with the given ID.
+     */
+    public IdentifiedLongValue(ValueFactory valuefactory, int id)
     {
-        return null;
+        this.valuefactory = valuefactory;
+        this.id           = id;
     }
 
 
@@ -51,19 +45,23 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.valuefactory.equals(((IdentifiedLongValue)object).valuefactory) &&
+               this.id == ((IdentifiedLongValue)object).id;
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               valuefactory.hashCode() ^
+               id;
     }
 
 
     public String toString()
     {
-        return "T";
+        return "l"+id;
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/IdentifiedReferenceValue.java b/src/proguard/evaluation/value/IdentifiedReferenceValue.java
new file mode 100644
index 0000000..323b93f
--- /dev/null
+++ b/src/proguard/evaluation/value/IdentifiedReferenceValue.java
@@ -0,0 +1,91 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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 LongValue represents a reference value that is identified by a unique ID.
+ *
+ * @author Eric Lafortune
+ */
+final class IdentifiedReferenceValue extends ReferenceValue
+{
+    private final ValueFactory valuefactory;
+    private final int          id;
+
+
+    /**
+     * Creates a new long 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 for ReferenceValue.
+
+    public int equal(ReferenceValue other)
+    {
+        return this.equals(other) ? ALWAYS : MAYBE;
+    }
+
+
+    // 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/src/proguard/evaluation/value/IdentifiedValueFactory.java b/src/proguard/evaluation/value/IdentifiedValueFactory.java
new file mode 100644
index 0000000..0b37ee7
--- /dev/null
+++ b/src/proguard/evaluation/value/IdentifiedValueFactory.java
@@ -0,0 +1,75 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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 IntegerValue objects.
+ *
+ * @author Eric Lafortune
+ */
+public class IdentifiedValueFactory
+extends      SpecificValueFactory
+{
+    private int integerID;
+    private int longID;
+    private int floatID;
+    private int doubleID;
+    private 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++);
+    }
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/InstructionOffsetValue.java b/src/proguard/evaluation/value/InstructionOffsetValue.java
index 3dcbfc2..a60008e 100644
--- a/src/proguard/evaluation/value/InstructionOffsetValue.java
+++ b/src/proguard/evaluation/value/InstructionOffsetValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -209,6 +209,16 @@ public class InstructionOffsetValue extends Category1Value
         return this;
     }
 
+    public boolean isSpecific()
+    {
+        return true;
+    }
+
+    public boolean isParticular()
+    {
+        return true;
+    }
+
     public final Value generalize(Value other)
     {
         return this.generalize(other.instructionOffsetValue());
@@ -278,7 +288,7 @@ public class InstructionOffsetValue extends Category1Value
 
     public String toString()
     {
-        StringBuffer buffer = new StringBuffer("o:");
+        StringBuffer buffer = new StringBuffer();
 
         if (values != null)
         {
@@ -292,6 +302,6 @@ public class InstructionOffsetValue extends Category1Value
             }
         }
 
-        return buffer.toString();
+        return buffer.append(':').toString();
     }
 }
diff --git a/src/proguard/evaluation/value/IntegerValue.java b/src/proguard/evaluation/value/IntegerValue.java
index d434abe..3de3aae 100644
--- a/src/proguard/evaluation/value/IntegerValue.java
+++ b/src/proguard/evaluation/value/IntegerValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -27,7 +27,7 @@ import proguard.classfile.ClassConstants;
  *
  * @author Eric Lafortune
  */
-public class IntegerValue extends Category1Value
+public abstract class IntegerValue extends Category1Value
 {
     /**
      * Returns the specific integer value, if applicable.
@@ -38,309 +38,459 @@ public class IntegerValue extends Category1Value
     }
 
 
+    // 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 IntegerValue generalize(IntegerValue other)
-    {
-        return this;
-    }
-
+    public abstract IntegerValue generalize(IntegerValue other);
 
     /**
      * Returns the sum of this IntegerValue and the given IntegerValue.
      */
-    public IntegerValue add(IntegerValue other)
-    {
-        return this;
-    }
+    public abstract IntegerValue add(IntegerValue other);
 
     /**
      * Returns the difference of this IntegerValue and the given IntegerValue.
      */
-    public IntegerValue subtract(IntegerValue other)
-    {
-        return this;
-    }
+    public abstract IntegerValue subtract(IntegerValue other);
 
     /**
      * Returns the difference of the given IntegerValue and this IntegerValue.
      */
-    public IntegerValue subtractFrom(IntegerValue other)
-    {
-        return this;
-    }
+    public abstract IntegerValue subtractFrom(IntegerValue other);
 
     /**
      * Returns the product of this IntegerValue and the given IntegerValue.
      */
-    public IntegerValue multiply(IntegerValue other)
-    throws ArithmeticException
-    {
-        return this;
-    }
+    public abstract IntegerValue multiply(IntegerValue other)
+    throws ArithmeticException;
 
     /**
      * Returns the quotient of this IntegerValue and the given IntegerValue.
      */
-    public IntegerValue divide(IntegerValue other)
-    throws ArithmeticException
-    {
-        return this;
-    }
+    public abstract IntegerValue divide(IntegerValue other)
+    throws ArithmeticException;
 
     /**
      * Returns the quotient of the given IntegerValue and this IntegerValue.
      */
-    public IntegerValue divideOf(IntegerValue other)
-    throws ArithmeticException
-    {
-        return this;
-    }
+    public abstract IntegerValue divideOf(IntegerValue other)
+    throws ArithmeticException;
 
     /**
      * Returns the remainder of this IntegerValue divided by the given
      * IntegerValue.
      */
-    public IntegerValue remainder(IntegerValue other)
-    throws ArithmeticException
-    {
-        return this;
-    }
+    public abstract IntegerValue remainder(IntegerValue other)
+    throws ArithmeticException;
 
     /**
      * Returns the remainder of the given IntegerValue divided by this
      * IntegerValue.
      */
-    public IntegerValue remainderOf(IntegerValue other)
-    throws ArithmeticException
-    {
-        return this;
-    }
+    public abstract IntegerValue remainderOf(IntegerValue other)
+    throws ArithmeticException;
 
     /**
      * Returns this IntegerValue, shifted left by the given IntegerValue.
      */
-    public IntegerValue shiftLeft(IntegerValue other)
+    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 this;
+        return -equal(other);
     }
 
     /**
-     * Returns the given IntegerValue, shifted left by this IntegerValue.
+     * Returns whether this IntegerValue is greater than the given IntegerValue:
+     * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
      */
-    public IntegerValue shiftLeftOf(IntegerValue other)
+    public final int greaterThan(IntegerValue other)
     {
-        return this;
+        return -lessThanOrEqual(other);
     }
 
     /**
-     * Returns this IntegerValue, shifted right by the given IntegerValue.
+     * Returns whether this IntegerValue is greater than or equal to the given IntegerValue:
+     * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
      */
-    public IntegerValue shiftRight(IntegerValue other)
+    public final int greaterThanOrEqual(IntegerValue other)
     {
-        return this;
+        return -lessThan(other);
     }
 
+
+    // Similar binary methods, but this time with unknown arguments.
+
     /**
-     * Returns the given IntegerValue, shifted right by this IntegerValue.
+     * Returns the generalization of this IntegerValue and the given other
+     * UnknownIntegerValue.
      */
-    public IntegerValue shiftRightOf(IntegerValue other)
+    public IntegerValue generalize(UnknownIntegerValue other)
     {
-        return this;
+        return generalize((IntegerValue)other);
     }
 
+
     /**
-     * Returns this unsigned IntegerValue, shifted left by the given
-     * IntegerValue.
+     * Returns the sum of this IntegerValue and the given UnknownIntegerValue.
      */
-    public IntegerValue unsignedShiftRight(IntegerValue other)
+    public IntegerValue add(UnknownIntegerValue other)
     {
-        return this;
+        return add((IntegerValue)other);
     }
 
     /**
-     * Returns the given unsigned IntegerValue, shifted left by this
-     * IntegerValue.
+     * Returns the difference of this IntegerValue and the given UnknownIntegerValue.
      */
-    public IntegerValue unsignedShiftRightOf(IntegerValue other)
+    public IntegerValue subtract(UnknownIntegerValue other)
     {
-        return this;
+        return subtract((IntegerValue)other);
     }
 
     /**
-     * Returns the given LongValue, shifted left by this IntegerValue.
+     * Returns the difference of the given UnknownIntegerValue and this IntegerValue.
      */
-    public LongValue shiftLeftOf(LongValue other)
+    public IntegerValue subtractFrom(UnknownIntegerValue other)
     {
-        return ValueFactory.LONG_VALUE;
+        return subtractFrom((IntegerValue)other);
     }
 
     /**
-     * Returns the given LongValue, shifted right by this IntegerValue.
+     * Returns the product of this IntegerValue and the given UnknownIntegerValue.
      */
-    public LongValue shiftRightOf(LongValue other)
+    public IntegerValue multiply(UnknownIntegerValue other)
     {
-        return ValueFactory.LONG_VALUE;
+        return multiply((IntegerValue)other);
     }
 
     /**
-     * Returns the given unsigned LongValue, shifted right by this IntegerValue.
+     * Returns the quotient of this IntegerValue and the given
+     * UnknownIntegerValue.
      */
-    public LongValue unsignedShiftRightOf(LongValue other)
+    public IntegerValue divide(UnknownIntegerValue other)
     {
-        return ValueFactory.LONG_VALUE;
+        return divide((IntegerValue)other);
     }
 
     /**
-     * Returns the logical <i>and</i> of this IntegerValue and the given
+     * Returns the quotient of the given UnknownIntegerValue and this
      * IntegerValue.
      */
-    public IntegerValue and(IntegerValue other)
+    public IntegerValue divideOf(UnknownIntegerValue other)
     {
-        return this;
+        return divideOf((IntegerValue)other);
     }
 
     /**
-     * Returns the logical <i>or</i> of this IntegerValue and the given
-     * IntegerValue.
+     * Returns the remainder of this IntegerValue divided by the given
+     * UnknownIntegerValue.
      */
-    public IntegerValue or(IntegerValue other)
+    public IntegerValue remainder(UnknownIntegerValue other)
     {
-        return this;
+        return remainder((IntegerValue)other);
     }
 
     /**
-     * Returns the logical <i>xor</i> of this IntegerValue and the given
+     * Returns the remainder of the given UnknownIntegerValue divided by this
      * IntegerValue.
      */
-    public IntegerValue xor(IntegerValue other)
+    public IntegerValue remainderOf(UnknownIntegerValue other)
     {
-        return this;
+        return remainderOf((IntegerValue)other);
     }
 
     /**
-     * Returns whether this IntegerValue and the given IntegerValue are equal:
-     * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+     * Returns this IntegerValue, shifted left by the given UnknownIntegerValue.
      */
-    public int equal(IntegerValue other)
+    public IntegerValue shiftLeft(UnknownIntegerValue other)
     {
-        return MAYBE;
+        return shiftLeft((IntegerValue)other);
     }
 
     /**
-     * Returns whether this IntegerValue is less than the given IntegerValue:
-     * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+     * Returns this IntegerValue, shifted right by the given UnknownIntegerValue.
      */
-    public int lessThan(IntegerValue other)
+    public IntegerValue shiftRight(UnknownIntegerValue other)
     {
-        return MAYBE;
+        return shiftRight((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>.
+     * Returns this unsigned IntegerValue, shifted right by the given
+     * UnknownIntegerValue.
      */
-    public int lessThanOrEqual(IntegerValue other)
+    public IntegerValue unsignedShiftRight(UnknownIntegerValue other)
     {
-        return MAYBE;
+        return unsignedShiftRight((IntegerValue)other);
     }
 
+    /**
+     * Returns the given UnknownIntegerValue, shifted left by this IntegerValue.
+     */
+    public IntegerValue shiftLeftOf(UnknownIntegerValue other)
+    {
+        return shiftLeftOf((IntegerValue)other);
+    }
 
-    // Derived binary methods.
+    /**
+     * Returns the given UnknownIntegerValue, shifted right by this IntegerValue.
+     */
+    public IntegerValue shiftRightOf(UnknownIntegerValue other)
+    {
+        return shiftRightOf((IntegerValue)other);
+    }
 
     /**
-     * Returns whether this IntegerValue and the given IntegerValue are different:
-     * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+     * Returns the given unsigned UnknownIntegerValue, shifted right by this
+     * IntegerValue.
      */
-    public final int notEqual(IntegerValue other)
+    public IntegerValue unsignedShiftRightOf(UnknownIntegerValue other)
     {
-        return -equal(other);
+        return unsignedShiftRightOf((IntegerValue)other);
     }
 
     /**
-     * Returns whether this IntegerValue is greater than the given IntegerValue:
-     * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+     * Returns the given UnknownLongValue, shifted left by this IntegerValue.
      */
-    public final int greaterThan(IntegerValue other)
+    public LongValue shiftLeftOf(UnknownLongValue other)
     {
-        return -lessThanOrEqual(other);
+        return shiftLeftOf((LongValue)other);
     }
 
     /**
-     * Returns whether this IntegerValue is greater than or equal to the given IntegerValue:
-     * <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
+     * Returns the given UnknownLongValue, shifted right by this IntegerValue.
      */
-    public final int greaterThanOrEqual(IntegerValue other)
+    public LongValue shiftRightOf(UnknownLongValue other)
     {
-        return -lessThan(other);
+        return shiftRightOf((LongValue)other);
     }
 
+    /**
+     * Returns the given unsigned UnknownLongValue, shifted right by this
+     * IntegerValue.
+     */
+    public LongValue unsignedShiftRightOf(UnknownLongValue other)
+    {
+        return unsignedShiftRightOf((LongValue)other);
+    }
 
-    // Basic unary methods.
+    /**
+     * Returns the logical <i>and</i> of this IntegerValue and the given
+     * UnknownIntegerValue.
+     */
+    public IntegerValue and(UnknownIntegerValue other)
+    {
+        return and((IntegerValue)other);
+    }
 
     /**
-     * Returns the negated value of this IntegerValue.
+     * Returns the logical <i>or</i> of this IntegerValue and the given
+     * UnknownIntegerValue.
      */
-    public IntegerValue negate()
+    public IntegerValue or(UnknownIntegerValue other)
     {
-        return this;
+        return or((IntegerValue)other);
     }
 
     /**
-     * Converts this IntegerValue to a byte IntegerValue.
+     * Returns the logical <i>xor</i> of this IntegerValue and the given
+     * UnknownIntegerValue.
      */
-    public IntegerValue convertToByte(ValueFactory valueFactory)
+    public IntegerValue xor(UnknownIntegerValue other)
     {
-        return this;
+        return xor((IntegerValue)other);
     }
 
     /**
-     * Converts this IntegerValue to a character IntegerValue.
+     * Returns whether this IntegerValue and the given UnknownIntegerValue are
+     * equal: <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
      */
-    public IntegerValue convertToCharacter(ValueFactory valueFactory)
+    public int equal(UnknownIntegerValue other)
     {
-        return this;
+        return equal((IntegerValue)other);
     }
 
     /**
-     * Converts this IntegerValue to a short IntegerValue.
+     * Returns whether this IntegerValue is less than the given
+     * UnknownIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+     * <code>ALWAYS</code>.
      */
-    public IntegerValue convertToShort(ValueFactory valueFactory)
+    public int lessThan(UnknownIntegerValue other)
     {
-        return this;
+        return lessThan((IntegerValue)other);
     }
 
     /**
-     * Converts this IntegerValue to a LongValue.
+     * Returns whether this IntegerValue is less than or equal to the given
+     * UnknownIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+     * <code>ALWAYS</code>.
      */
-    public LongValue convertToLong(ValueFactory valueFactory)
+    public int lessThanOrEqual(UnknownIntegerValue other)
     {
-        return valueFactory.createLongValue();
+        return lessThanOrEqual((IntegerValue)other);
     }
 
+
+    // Derived binary methods.
+
     /**
-     * Converts this IntegerValue to a FloatValue.
+     * Returns whether this IntegerValue and the given UnknownIntegerValue are
+     * different: <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>.
      */
-    public FloatValue convertToFloat(ValueFactory valueFactory)
+    public final int notEqual(UnknownIntegerValue other)
     {
-        return valueFactory.createFloatValue();
+        return -equal(other);
     }
 
     /**
-     * Converts this IntegerValue to a DoubleValue.
+     * Returns whether this IntegerValue is greater than the given
+     * UnknownIntegerValue: <code>NEVER</code>, <code>MAYBE</code>, or
+     * <code>ALWAYS</code>.
      */
-    public DoubleValue convertToDouble(ValueFactory valueFactory)
+    public final int greaterThan(UnknownIntegerValue other)
     {
-        return valueFactory.createDoubleValue();
+        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 more specific arguments.
+
+    // Similar binary methods, but this time with specific arguments.
 
     /**
      * Returns the generalization of this IntegerValue and the given other
@@ -348,7 +498,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue generalize(SpecificIntegerValue other)
     {
-        return this;
+        return generalize((IntegerValue)other);
     }
 
 
@@ -357,7 +507,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue add(SpecificIntegerValue other)
     {
-        return this;
+        return add((IntegerValue)other);
     }
 
     /**
@@ -365,7 +515,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue subtract(SpecificIntegerValue other)
     {
-        return this;
+        return subtract((IntegerValue)other);
     }
 
     /**
@@ -373,7 +523,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue subtractFrom(SpecificIntegerValue other)
     {
-        return this;
+        return subtractFrom((IntegerValue)other);
     }
 
     /**
@@ -381,7 +531,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue multiply(SpecificIntegerValue other)
     {
-        return this;
+        return multiply((IntegerValue)other);
     }
 
     /**
@@ -390,7 +540,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue divide(SpecificIntegerValue other)
     {
-        return this;
+        return divide((IntegerValue)other);
     }
 
     /**
@@ -399,7 +549,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue divideOf(SpecificIntegerValue other)
     {
-        return this;
+        return divideOf((IntegerValue)other);
     }
 
     /**
@@ -408,7 +558,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue remainder(SpecificIntegerValue other)
     {
-        return this;
+        return remainder((IntegerValue)other);
     }
 
     /**
@@ -417,7 +567,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue remainderOf(SpecificIntegerValue other)
     {
-        return this;
+        return remainderOf((IntegerValue)other);
     }
 
     /**
@@ -425,40 +575,40 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue shiftLeft(SpecificIntegerValue other)
     {
-        return this;
+        return shiftLeft((IntegerValue)other);
     }
 
     /**
-     * Returns the given SpecificIntegerValue, shifted left by this IntegerValue.
+     * Returns this IntegerValue, shifted right by the given SpecificIntegerValue.
      */
-    public IntegerValue shiftLeftOf(SpecificIntegerValue other)
+    public IntegerValue shiftRight(SpecificIntegerValue other)
     {
-        return this;
+        return shiftRight((IntegerValue)other);
     }
 
     /**
-     * Returns this IntegerValue, shifted right by the given SpecificIntegerValue.
+     * Returns this unsigned IntegerValue, shifted right by the given
+     * SpecificIntegerValue.
      */
-    public IntegerValue shiftRight(SpecificIntegerValue other)
+    public IntegerValue unsignedShiftRight(SpecificIntegerValue other)
     {
-        return this;
+        return unsignedShiftRight((IntegerValue)other);
     }
 
     /**
-     * Returns the given SpecificIntegerValue, shifted right by this IntegerValue.
+     * Returns the given SpecificIntegerValue, shifted left by this IntegerValue.
      */
-    public IntegerValue shiftRightOf(SpecificIntegerValue other)
+    public IntegerValue shiftLeftOf(SpecificIntegerValue other)
     {
-        return this;
+        return shiftLeftOf((IntegerValue)other);
     }
 
     /**
-     * Returns this unsigned IntegerValue, shifted right by the given
-     * SpecificIntegerValue.
+     * Returns the given SpecificIntegerValue, shifted right by this IntegerValue.
      */
-    public IntegerValue unsignedShiftRight(SpecificIntegerValue other)
+    public IntegerValue shiftRightOf(SpecificIntegerValue other)
     {
-        return this;
+        return shiftRightOf((IntegerValue)other);
     }
 
     /**
@@ -467,7 +617,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue unsignedShiftRightOf(SpecificIntegerValue other)
     {
-        return this;
+        return unsignedShiftRightOf((IntegerValue)other);
     }
 
     /**
@@ -475,7 +625,7 @@ public class IntegerValue extends Category1Value
      */
     public LongValue shiftLeftOf(SpecificLongValue other)
     {
-        return ValueFactory.LONG_VALUE;
+        return shiftLeftOf((LongValue)other);
     }
 
     /**
@@ -483,7 +633,7 @@ public class IntegerValue extends Category1Value
      */
     public LongValue shiftRightOf(SpecificLongValue other)
     {
-        return ValueFactory.LONG_VALUE;
+        return shiftRightOf((LongValue)other);
     }
 
     /**
@@ -492,7 +642,7 @@ public class IntegerValue extends Category1Value
      */
     public LongValue unsignedShiftRightOf(SpecificLongValue other)
     {
-        return ValueFactory.LONG_VALUE;
+        return unsignedShiftRightOf((LongValue)other);
     }
 
     /**
@@ -501,7 +651,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue and(SpecificIntegerValue other)
     {
-        return this;
+        return and((IntegerValue)other);
     }
 
     /**
@@ -510,7 +660,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue or(SpecificIntegerValue other)
     {
-        return this;
+        return or((IntegerValue)other);
     }
 
     /**
@@ -519,7 +669,7 @@ public class IntegerValue extends Category1Value
      */
     public IntegerValue xor(SpecificIntegerValue other)
     {
-        return this;
+        return xor((IntegerValue)other);
     }
 
     /**
@@ -528,7 +678,7 @@ public class IntegerValue extends Category1Value
      */
     public int equal(SpecificIntegerValue other)
     {
-        return MAYBE;
+        return equal((IntegerValue)other);
     }
 
     /**
@@ -538,7 +688,7 @@ public class IntegerValue extends Category1Value
      */
     public int lessThan(SpecificIntegerValue other)
     {
-        return MAYBE;
+        return lessThan((IntegerValue)other);
     }
 
     /**
@@ -548,7 +698,7 @@ public class IntegerValue extends Category1Value
      */
     public int lessThanOrEqual(SpecificIntegerValue other)
     {
-        return MAYBE;
+        return lessThanOrEqual((IntegerValue)other);
     }
 
 
@@ -584,46 +734,269 @@ public class IntegerValue extends Category1Value
     }
 
 
-    // Implementations for Value.
+    // Similar binary methods, but this time with particular arguments.
 
-    public final IntegerValue integerValue()
+    /**
+     * Returns the generalization of this IntegerValue and the given other
+     * ParticularIntegerValue.
+     */
+    public IntegerValue generalize(ParticularIntegerValue other)
     {
-        return this;
+        return generalize((SpecificIntegerValue)other);
     }
 
-    public final Value generalize(Value other)
+
+    /**
+     * Returns the sum of this IntegerValue and the given ParticularIntegerValue.
+     */
+    public IntegerValue add(ParticularIntegerValue other)
     {
-        return this.generalize(other.integerValue());
+        return add((SpecificIntegerValue)other);
     }
 
-    public final int computationalType()
+    /**
+     * Returns the difference of this IntegerValue and the given ParticularIntegerValue.
+     */
+    public IntegerValue subtract(ParticularIntegerValue other)
     {
-        return TYPE_INTEGER;
+        return subtract((SpecificIntegerValue)other);
     }
 
-    public final String internalType()
+    /**
+     * Returns the difference of the given ParticularIntegerValue and this IntegerValue.
+     */
+    public IntegerValue subtractFrom(ParticularIntegerValue other)
     {
-        return String.valueOf(ClassConstants.INTERNAL_TYPE_INT);
+        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);
+    }
 
-    // Implementations for Object.
+    /**
+     * Returns the given ParticularIntegerValue, shifted left by this IntegerValue.
+     */
+    public IntegerValue shiftLeftOf(ParticularIntegerValue other)
+    {
+        return shiftLeftOf((SpecificIntegerValue)other);
+    }
 
-    public boolean equals(Object object)
+    /**
+     * Returns the given ParticularIntegerValue, shifted right by this IntegerValue.
+     */
+    public IntegerValue shiftRightOf(ParticularIntegerValue other)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        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);
+    }
 
-    public int hashCode()
+    /**
+     * Returns the given ParticularLongValue, shifted right by this IntegerValue.
+     */
+    public LongValue shiftRightOf(ParticularLongValue other)
     {
-        return this.getClass().hashCode();
+        return shiftRightOf((SpecificLongValue)other);
     }
 
+    /**
+     * Returns the given unsigned ParticularLongValue, shifted right by this
+     * IntegerValue.
+     */
+    public LongValue unsignedShiftRightOf(ParticularLongValue other)
+    {
+        return unsignedShiftRightOf((SpecificLongValue)other);
+    }
 
-    public String toString()
+    /**
+     * 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 "i";
+        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.INTERNAL_TYPE_INT);
     }
 }
diff --git a/src/proguard/evaluation/value/LongValue.java b/src/proguard/evaluation/value/LongValue.java
index 86c442f..be51d5d 100644
--- a/src/proguard/evaluation/value/LongValue.java
+++ b/src/proguard/evaluation/value/LongValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -27,17 +27,41 @@ import proguard.classfile.ClassConstants;
  *
  * @author Eric Lafortune
  */
-public class LongValue extends Category2Value
+public abstract class LongValue extends Category2Value
 {
     /**
      * Returns the specific long value, if applicable.
      */
     public long value()
     {
-        return 0L;
+        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.
 
     /**
@@ -46,16 +70,15 @@ public class LongValue extends Category2Value
      */
     public LongValue generalize(LongValue other)
     {
-        return this;
+        return other.generalize(this);
     }
 
-
     /**
      * Returns the sum of this LongValue and the given LongValue.
      */
     public LongValue add(LongValue other)
     {
-        return this;
+        return other.add(this);
     }
 
     /**
@@ -63,7 +86,7 @@ public class LongValue extends Category2Value
      */
     public LongValue subtract(LongValue other)
     {
-        return this;
+        return other.subtractFrom(this);
     }
 
     /**
@@ -71,47 +94,54 @@ public class LongValue extends Category2Value
      */
     public LongValue subtractFrom(LongValue other)
     {
-        return this;
+        return other.subtract(this);
     }
 
     /**
      * Returns the product of this LongValue and the given LongValue.
      */
     public LongValue multiply(LongValue other)
+    throws ArithmeticException
     {
-        return this;
+        return other.multiply(this);
     }
 
     /**
      * Returns the quotient of this LongValue and the given LongValue.
      */
     public LongValue divide(LongValue other)
+    throws ArithmeticException
     {
-        return this;
+        return other.divideOf(this);
     }
 
     /**
      * Returns the quotient of the given LongValue and this LongValue.
      */
     public LongValue divideOf(LongValue other)
+    throws ArithmeticException
     {
-        return this;
+        return other.divide(this);
     }
 
     /**
-     * Returns the remainder of this LongValue divided by the given LongValue.
+     * Returns the remainder of this LongValue divided by the given
+     * LongValue.
      */
     public LongValue remainder(LongValue other)
+    throws ArithmeticException
     {
-        return this;
+        return other.remainderOf(this);
     }
 
     /**
-     * Returns the remainder of the given LongValue divided by this LongValue.
+     * Returns the remainder of the given LongValue divided by this
+     * LongValue.
      */
     public LongValue remainderOf(LongValue other)
+    throws ArithmeticException
     {
-        return this;
+        return other.remainder(this);
     }
 
     /**
@@ -119,7 +149,7 @@ public class LongValue extends Category2Value
      */
     public LongValue shiftLeft(IntegerValue other)
     {
-        return this;
+        return other.shiftLeftOf(this);
     }
 
     /**
@@ -127,7 +157,7 @@ public class LongValue extends Category2Value
      */
     public LongValue shiftRight(IntegerValue other)
     {
-        return this;
+        return other.shiftRightOf(this);
     }
 
     /**
@@ -136,7 +166,7 @@ public class LongValue extends Category2Value
      */
     public LongValue unsignedShiftRight(IntegerValue other)
     {
-        return this;
+        return other.unsignedShiftRightOf(this);
     }
 
     /**
@@ -145,7 +175,7 @@ public class LongValue extends Category2Value
      */
     public LongValue and(LongValue other)
     {
-        return this;
+        return other.and(this);
     }
 
     /**
@@ -154,7 +184,7 @@ public class LongValue extends Category2Value
      */
     public LongValue or(LongValue other)
     {
-        return this;
+        return other.or(this);
     }
 
     /**
@@ -163,16 +193,16 @@ public class LongValue extends Category2Value
      */
     public LongValue xor(LongValue other)
     {
-        return this;
+        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, ValueFactory valueFactory)
+    public IntegerValue compare(LongValue other)
     {
-        return valueFactory.createIntegerValue();
+        return other.compareReverse(this);
     }
 
 
@@ -182,44 +212,9 @@ public class LongValue extends Category2Value
      * 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, ValueFactory valueFactory)
-    {
-        return compare(other, valueFactory).negate();
-    }
-
-
-    // Basic unary methods.
-
-    /**
-     * Returns the negated value of this LongValue.
-     */
-    public LongValue negate()
-    {
-        return this;
-    }
-
-    /**
-     * Converts this LongValue to an IntegerValue.
-     */
-    public IntegerValue convertToInteger(ValueFactory valueFactory)
-    {
-        return valueFactory.createIntegerValue();
-    }
-
-    /**
-     * Converts this LongValue to a FloatValue.
-     */
-    public FloatValue convertToFloat(ValueFactory valueFactory)
-    {
-        return valueFactory.createFloatValue();
-    }
-
-    /**
-     * Converts this LongValue to a DoubleValue.
-     */
-    public DoubleValue convertToDouble(ValueFactory valueFactory)
+    public final IntegerValue compareReverse(LongValue other)
     {
-        return valueFactory.createDoubleValue();
+        return compare(other).negate();
     }
 
 
@@ -268,7 +263,8 @@ public class LongValue extends Category2Value
     }
 
     /**
-     * Returns the quotient of this LongValue and the given SpecificLongValue.
+     * Returns the quotient of this LongValue and the given
+     * SpecificLongValue.
      */
     public LongValue divide(SpecificLongValue other)
     {
@@ -276,7 +272,8 @@ public class LongValue extends Category2Value
     }
 
     /**
-     * Returns the quotient of the given SpecificLongValue and this LongValue.
+     * Returns the quotient of the given SpecificLongValue and this
+     * LongValue.
      */
     public LongValue divideOf(SpecificLongValue other)
     {
@@ -293,7 +290,7 @@ public class LongValue extends Category2Value
     }
 
     /**
-     * Returns the remainder of the given SpecificLongValue and this
+     * Returns the remainder of the given SpecificLongValue divided by this
      * LongValue.
      */
     public LongValue remainderOf(SpecificLongValue other)
@@ -302,26 +299,26 @@ public class LongValue extends Category2Value
     }
 
     /**
-     * Returns this LongValue, shifted left by the given SpecificIntegerValue.
+     * Returns this LongValue, shifted left by the given SpecificLongValue.
      */
-    public LongValue shiftLeft(SpecificIntegerValue other)
+    public LongValue shiftLeft(SpecificLongValue other)
     {
         return this;
     }
 
     /**
-     * Returns this LongValue, shifted right by the given SpecificIntegerValue.
+     * Returns this LongValue, shifted right by the given SpecificLongValue.
      */
-    public LongValue shiftRight(SpecificIntegerValue other)
+    public LongValue shiftRight(SpecificLongValue other)
     {
         return this;
     }
 
     /**
-     * Returns this unsigned LongValue, shifted left by the given
-     * SpecificIntegerValue.
+     * Returns this unsigned LongValue, shifted right by the given
+     * SpecificLongValue.
      */
-    public LongValue unsignedShiftRight(SpecificIntegerValue other)
+    public LongValue unsignedShiftRight(SpecificLongValue other)
     {
         return this;
     }
@@ -358,9 +355,9 @@ public class LongValue extends Category2Value
      * less than, equal to, or greater than the given SpecificLongValue,
      * respectively.
      */
-    public IntegerValue compare(SpecificLongValue other, ValueFactory valueFactory)
+    public IntegerValue compare(SpecificLongValue other)
     {
-        return valueFactory.createIntegerValue();
+        return new ComparisonValue(this, other);
     }
 
 
@@ -371,52 +368,187 @@ public class LongValue extends Category2Value
      * less than, equal to, or greater than the given SpecificLongValue,
      * respectively.
      */
-    public final IntegerValue compareReverse(SpecificLongValue other, ValueFactory valueFactory)
+    public final IntegerValue compareReverse(SpecificLongValue other)
     {
-        return compare(other, valueFactory).negate();
+        return compare(other).negate();
     }
 
 
-    // Implementations for Value.
+    // Similar binary methods, but this time with particular arguments.
 
-    public final LongValue longValue()
+    /**
+     * Returns the generalization of this LongValue and the given other
+     * ParticularLongValue.
+     */
+    public LongValue generalize(ParticularLongValue other)
     {
-        return this;
+        return generalize((SpecificLongValue)other);
     }
 
-    public final Value generalize(Value other)
+
+    /**
+     * Returns the sum of this LongValue and the given ParticularLongValue.
+     */
+    public LongValue add(ParticularLongValue other)
     {
-        return this.generalize(other.longValue());
+        return add((SpecificLongValue)other);
     }
 
-    public final int computationalType()
+    /**
+     * Returns the difference of this LongValue and the given ParticularLongValue.
+     */
+    public LongValue subtract(ParticularLongValue other)
     {
-        return TYPE_LONG;
+        return subtract((SpecificLongValue)other);
     }
 
-    public final String internalType()
+    /**
+     * 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 String.valueOf(ClassConstants.INTERNAL_TYPE_LONG);
+        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);
     }
 
 
-    // Implementations for Object.
+    // Derived binary methods.
 
-    public boolean equals(Object object)
+    /**
+     * 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 object != null &&
-               this.getClass() == object.getClass();
+        return compare(other).negate();
     }
 
 
-    public int hashCode()
+    // Implementations for Value.
+
+    public final LongValue longValue()
+    {
+        return this;
+    }
+
+    public final Value generalize(Value other)
     {
-        return this.getClass().hashCode();
+        return this.generalize(other.longValue());
     }
 
+    public final int computationalType()
+    {
+        return TYPE_LONG;
+    }
 
-    public String toString()
+    public final String internalType()
     {
-        return "l";
+        return String.valueOf(ClassConstants.INTERNAL_TYPE_INT);
     }
 }
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/NegatedDoubleValue.java
similarity index 58%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/NegatedDoubleValue.java
index 9bb6ca8..44a1978 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/NegatedDoubleValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,29 @@
 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.
+ * This DoubleValue represents a double value that is negated.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class NegatedDoubleValue extends SpecificDoubleValue
 {
-    // Implementations for Value.
+    private final DoubleValue doubleValue;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
 
-    public final int computationalType()
+    /**
+     * Creates a new negated double value of the given double value.
+     */
+    public NegatedDoubleValue(DoubleValue doubleValue)
     {
-        return TYPE_TOP;
+        this.doubleValue = doubleValue;
     }
 
-    public final String internalType()
+
+    // Implementations of unary methods of DoubleValue.
+
+    public DoubleValue negate()
     {
-        return null;
+        return doubleValue;
     }
 
 
@@ -51,19 +51,21 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.doubleValue.equals(((NegatedDoubleValue)object).doubleValue);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               doubleValue.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "-"+doubleValue;
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/NegatedFloatValue.java
similarity index 59%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/NegatedFloatValue.java
index 9bb6ca8..31b338c 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/NegatedFloatValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,29 @@
 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.
+ * This FloatValue represents a float value that is negated.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class NegatedFloatValue extends SpecificFloatValue
 {
-    // Implementations for Value.
+    private final FloatValue floatValue;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
 
-    public final int computationalType()
+    /**
+     * Creates a new negated float value of the given float value.
+     */
+    public NegatedFloatValue(FloatValue floatValue)
     {
-        return TYPE_TOP;
+        this.floatValue = floatValue;
     }
 
-    public final String internalType()
+
+    // Implementations of unary methods of FloatValue.
+
+    public FloatValue negate()
     {
-        return null;
+        return floatValue;
     }
 
 
@@ -51,19 +51,21 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.floatValue.equals(((NegatedFloatValue)object).floatValue);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               floatValue.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "-"+floatValue;
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/NegatedIntegerValue.java
similarity index 57%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/NegatedIntegerValue.java
index 9bb6ca8..22f9c5f 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/NegatedIntegerValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,29 @@
 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.
+ * This IntegerValue represents a integer value that is negated.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class NegatedIntegerValue extends SpecificIntegerValue
 {
-    // Implementations for Value.
+    private final IntegerValue integerValue;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
 
-    public final int computationalType()
+    /**
+     * Creates a new negated integer value of the given integer value.
+     */
+    public NegatedIntegerValue(IntegerValue integerValue)
     {
-        return TYPE_TOP;
+        this.integerValue = integerValue;
     }
 
-    public final String internalType()
+
+    // Implementations of unary methods of IntegerValue.
+
+    public IntegerValue negate()
     {
-        return null;
+        return integerValue;
     }
 
 
@@ -51,19 +51,21 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.integerValue.equals(((NegatedIntegerValue)object).integerValue);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               integerValue.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "-"+integerValue;
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/NegatedLongValue.java
similarity index 59%
copy from src/proguard/evaluation/value/TopValue.java
copy to src/proguard/evaluation/value/NegatedLongValue.java
index 9bb6ca8..52ee767 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/NegatedLongValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,29 +21,29 @@
 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.
+ * This LongValue represents a long value that is negated.
  *
  * @author Eric Lafortune
  */
-public class TopValue extends Category1Value
+final class NegatedLongValue extends SpecificLongValue
 {
-    // Implementations for Value.
+    private final LongValue longValue;
 
-    public final Value generalize(Value other)
-    {
-        return this.getClass() == other.getClass() ? this : null;
-    }
 
-    public final int computationalType()
+    /**
+     * Creates a new negated long value of the given long value.
+     */
+    public NegatedLongValue(LongValue longValue)
     {
-        return TYPE_TOP;
+        this.longValue = longValue;
     }
 
-    public final String internalType()
+
+    // Implementations of unary methods of LongValue.
+
+    public LongValue negate()
     {
-        return null;
+        return longValue;
     }
 
 
@@ -51,19 +51,21 @@ public class TopValue extends Category1Value
 
     public boolean equals(Object object)
     {
-        return object != null &&
-               this.getClass() == object.getClass();
+        return this == object ||
+               super.equals(object) &&
+               this.longValue.equals(((NegatedLongValue)object).longValue);
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode();
+        return super.hashCode() ^
+               longValue.hashCode();
     }
 
 
     public String toString()
     {
-        return "T";
+        return "-"+longValue;
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/SpecificDoubleValue.java b/src/proguard/evaluation/value/ParticularDoubleValue.java
similarity index 52%
copy from src/proguard/evaluation/value/SpecificDoubleValue.java
copy to src/proguard/evaluation/value/ParticularDoubleValue.java
index 7076ce5..e436b9c 100644
--- a/src/proguard/evaluation/value/SpecificDoubleValue.java
+++ b/src/proguard/evaluation/value/ParticularDoubleValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -14,26 +14,26 @@
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  * more details.
  *
- * You should have received a copy of the GNU General Public License adouble
+ * You should have received a copy of the GNU General Public License along
  * 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.
+ * This DoubleValue represents a particular double value.
  *
  * @author Eric Lafortune
  */
-final class SpecificDoubleValue extends DoubleValue
+final class ParticularDoubleValue extends SpecificDoubleValue
 {
     private final double value;
 
 
     /**
-     * Creates a new specific double value.
+     * Creates a new particular double value.
      */
-    public SpecificDoubleValue(double value)
+    public ParticularDoubleValue(double value)
     {
         this.value = value;
     }
@@ -47,10 +47,30 @@ final class SpecificDoubleValue extends DoubleValue
     }
 
 
-    // Implementations of binary methods of DoubleValue.
+    // Implementations of unary methods of DoubleValue.
+
+    public DoubleValue negate()
+    {
+        return new ParticularDoubleValue(-value);
+    }
+
+    public IntegerValue convertToInteger()
+    {
+        return new ParticularIntegerValue((int)value);
+    }
 
-    // Perhaps the other value arguments are more specific than apparent
-    // in these methods, so delegate to them.
+    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)
     {
@@ -59,17 +79,17 @@ final class SpecificDoubleValue extends DoubleValue
 
     public DoubleValue add(DoubleValue other)
     {
-        return other.add(this);
+        return value == 0.0 ? other : other.add(this);
     }
 
     public DoubleValue subtract(DoubleValue other)
     {
-        return other.subtractFrom(this);
+        return value == 0.0 ? other.negate() : other.subtractFrom(this);
     }
 
     public DoubleValue subtractFrom(DoubleValue other)
     {
-        return other.subtract(this);
+        return value == 0.0 ? other : other.subtract(this);
     }
 
     public DoubleValue multiply(DoubleValue other)
@@ -97,84 +117,61 @@ final class SpecificDoubleValue extends DoubleValue
         return other.remainder(this);
     }
 
-    public IntegerValue compare(DoubleValue other, ValueFactory valueFactory)
-    {
-        return other.compareReverse(this, valueFactory);
-    }
-
-
-    // Implementations of unary methods of DoubleValue.
-
-    public DoubleValue negate()
-    {
-        return new SpecificDoubleValue(-value);
-    }
-
-    public IntegerValue convertToInteger(ValueFactory valueFactory)
-    {
-        return new SpecificIntegerValue((int)value);
-    }
-
-    public LongValue convertToLong(ValueFactory valueFactory)
-    {
-        return new SpecificLongValue((long)value);
-    }
-
-    public FloatValue convertToFloat(ValueFactory valueFactory)
+    public IntegerValue compare(DoubleValue other)
     {
-        return new SpecificFloatValue((float)value);
+        return other.compareReverse(this);
     }
 
 
-    // Implementations of binary DoubleValue methods with SpecificDoubleValue
+    // Implementations of binary DoubleValue methods with ParticularDoubleValue
     // arguments.
 
-    public DoubleValue generalize(SpecificDoubleValue other)
+    public DoubleValue generalize(ParticularDoubleValue other)
     {
         return this.value == other.value ? this : ValueFactory.DOUBLE_VALUE;
     }
 
-    public DoubleValue add(SpecificDoubleValue other)
+    public DoubleValue add(ParticularDoubleValue other)
     {
-        return new SpecificDoubleValue(this.value + other.value);
+        return new ParticularDoubleValue(this.value + other.value);
     }
 
-    public DoubleValue subtract(SpecificDoubleValue other)
+    public DoubleValue subtract(ParticularDoubleValue other)
     {
-        return new SpecificDoubleValue(this.value - other.value);
+        return new ParticularDoubleValue(this.value - other.value);
     }
 
-    public DoubleValue subtractFrom(SpecificDoubleValue other)
+    public DoubleValue subtractFrom(ParticularDoubleValue other)
     {
-        return new SpecificDoubleValue(other.value - this.value);
+        return new ParticularDoubleValue(other.value - this.value);
     }
 
-    public DoubleValue multiply(SpecificDoubleValue other)
+    public DoubleValue multiply(ParticularDoubleValue other)
     {
-        return new SpecificDoubleValue(this.value * other.value);
+        return new ParticularDoubleValue(this.value * other.value);
     }
 
-    public DoubleValue divide(SpecificDoubleValue other)
+    public DoubleValue divide(ParticularDoubleValue other)
     {
-        return new SpecificDoubleValue(this.value / other.value);
+        return new ParticularDoubleValue(this.value / other.value);
     }
 
-    public DoubleValue divideOf(SpecificDoubleValue other)
+    public DoubleValue divideOf(ParticularDoubleValue other)
     {
-        return new SpecificDoubleValue(other.value / this.value);
+        return new ParticularDoubleValue(other.value / this.value);
     }
 
-    public DoubleValue remainder(SpecificDoubleValue other)
+    public DoubleValue remainder(ParticularDoubleValue other)
     {
-        return new SpecificDoubleValue(this.value % other.value);
+        return new ParticularDoubleValue(this.value % other.value);
     }
 
-    public DoubleValue remainderOf(SpecificDoubleValue other)
+    public DoubleValue remainderOf(ParticularDoubleValue other)
     {
-        return new SpecificDoubleValue(other.value % this.value);
+        return new ParticularDoubleValue(other.value % this.value);
     }
 
-    public IntegerValue compare(SpecificDoubleValue other, ValueFactory valueFactory)
+    public IntegerValue compare(ParticularDoubleValue other)
     {
         return this.value <  other.value ? SpecificValueFactory.INTEGER_VALUE_M1 :
                this.value == other.value ? SpecificValueFactory.INTEGER_VALUE_0  :
@@ -184,7 +181,7 @@ final class SpecificDoubleValue extends DoubleValue
 
     // Implementations for Value.
 
-    public boolean isSpecific()
+    public boolean isParticular()
     {
         return true;
     }
@@ -194,20 +191,20 @@ final class SpecificDoubleValue extends DoubleValue
 
     public boolean equals(Object object)
     {
-        return object          != null              &&
-               this.getClass() == object.getClass() &&
-               this.value      == ((SpecificDoubleValue)object).value;
+        return super.equals(object) &&
+               this.value == ((ParticularDoubleValue)object).value;
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode() ^ (int)Double.doubleToLongBits(value);
+        return super.hashCode() ^
+               (int)Double.doubleToLongBits(value);
     }
 
 
     public String toString()
     {
-        return "d:"+value;
+        return value+"d";
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/ParticularFloatValue.java b/src/proguard/evaluation/value/ParticularFloatValue.java
new file mode 100644
index 0000000..0bf5306
--- /dev/null
+++ b/src/proguard/evaluation/value/ParticularFloatValue.java
@@ -0,0 +1,210 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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)
+    {
+        return value == 0.0 ? other : other.add(this);
+    }
+
+    public FloatValue subtract(FloatValue other)
+    {
+        return value == 0.0 ? other.negate() : other.subtractFrom(this);
+    }
+
+    public FloatValue subtractFrom(FloatValue other)
+    {
+        return value == 0.0 ? other : 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)
+    {
+        return this.value == 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 ? SpecificValueFactory.INTEGER_VALUE_M1 :
+               this.value == other.value ? SpecificValueFactory.INTEGER_VALUE_0  :
+                                           SpecificValueFactory.INTEGER_VALUE_1;
+    }
+
+
+    // Implementations for Value.
+
+    public boolean isParticular()
+    {
+        return true;
+    }
+
+
+    // Implementations for Object.
+
+    public boolean equals(Object object)
+    {
+        return super.equals(object) &&
+               this.value == ((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/src/proguard/evaluation/value/SpecificIntegerValue.java b/src/proguard/evaluation/value/ParticularIntegerValue.java
similarity index 53%
copy from src/proguard/evaluation/value/SpecificIntegerValue.java
copy to src/proguard/evaluation/value/ParticularIntegerValue.java
index 6ec5dec..b1a2b35 100644
--- a/src/proguard/evaluation/value/SpecificIntegerValue.java
+++ b/src/proguard/evaluation/value/ParticularIntegerValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,16 +21,19 @@
 package proguard.evaluation.value;
 
 /**
- * This IntegerValue represents a specific integer value.
+ * This IntegerValue represents a particular integer value.
  *
  * @author Eric Lafortune
  */
-final class SpecificIntegerValue extends IntegerValue
+final class ParticularIntegerValue extends SpecificIntegerValue
 {
     private final int value;
 
 
-    public SpecificIntegerValue(int value)
+    /**
+     * Creates a new particular integer value.
+     */
+    public ParticularIntegerValue(int value)
     {
         this.value = value;
     }
@@ -44,10 +47,57 @@ final class SpecificIntegerValue extends IntegerValue
     }
 
 
-    // Implementations of binary methods of IntegerValue.
+    // 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;
 
-    // Perhaps the other value arguments are more specific than apparent
-    // in these methods, so delegate to them.
+        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)
     {
@@ -174,184 +224,129 @@ final class SpecificIntegerValue extends IntegerValue
     }
 
 
-    // Implementations of unary methods of IntegerValue.
-
-    public IntegerValue negate()
-    {
-        return new SpecificIntegerValue(-value);
-    }
-
-    public IntegerValue convertToByte(ValueFactory valueFactory)
-    {
-        int byteValue = (byte)value;
-
-        return byteValue == value ?
-            this :
-            new SpecificIntegerValue(byteValue);
-    }
-
-    public IntegerValue convertToCharacter(ValueFactory valueFactory)
-    {
-        int charValue = (char)value;
-
-        return charValue == value ?
-            this :
-            new SpecificIntegerValue(charValue);
-    }
-
-    public IntegerValue convertToShort(ValueFactory valueFactory)
-    {
-        int shortValue = (short)value;
-
-        return shortValue == value ?
-            this :
-            new SpecificIntegerValue(shortValue);
-    }
-
-    public IntegerValue convertToInteger(ValueFactory valueFactory)
-    {
-        return this;
-    }
-
-    public LongValue convertToLong(ValueFactory valueFactory)
-    {
-        return valueFactory.createLongValue((long)value);
-    }
-
-    public FloatValue convertToFloat(ValueFactory valueFactory)
-    {
-        return valueFactory.createFloatValue((float)value);
-    }
-
-    public DoubleValue convertToDouble(ValueFactory valueFactory)
-    {
-        return valueFactory.createDoubleValue((double)value);
-    }
-
-
-    // Implementations of binary IntegerValue methods with SpecificIntegerValue
+    // Implementations of binary IntegerValue methods with ParticularIntegerValue
     // arguments.
 
-    public IntegerValue generalize(SpecificIntegerValue other)
+    public IntegerValue generalize(ParticularIntegerValue other)
     {
-        return this.value == other.value ? this : ValueFactory.INTEGER_VALUE;
+        return generalize((SpecificIntegerValue)other);
     }
 
-    public IntegerValue add(SpecificIntegerValue other)
+    public IntegerValue add(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value + other.value);
+        return new ParticularIntegerValue(this.value + other.value);
     }
 
-    public IntegerValue subtract(SpecificIntegerValue other)
+    public IntegerValue subtract(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value - other.value);
+        return new ParticularIntegerValue(this.value - other.value);
     }
 
-    public IntegerValue subtractFrom(SpecificIntegerValue other)
+    public IntegerValue subtractFrom(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(other.value - this.value);
+        return new ParticularIntegerValue(other.value - this.value);
     }
 
-    public IntegerValue multiply(SpecificIntegerValue other)
+    public IntegerValue multiply(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value * other.value);
+        return new ParticularIntegerValue(this.value * other.value);
     }
 
-    public IntegerValue divide(SpecificIntegerValue other)
+    public IntegerValue divide(ParticularIntegerValue other)
     throws ArithmeticException
     {
-        return new SpecificIntegerValue(this.value / other.value);
+        return new ParticularIntegerValue(this.value / other.value);
     }
 
-    public IntegerValue divideOf(SpecificIntegerValue other)
+    public IntegerValue divideOf(ParticularIntegerValue other)
     throws ArithmeticException
     {
-        return new SpecificIntegerValue(other.value / this.value);
+        return new ParticularIntegerValue(other.value / this.value);
     }
 
-    public IntegerValue remainder(SpecificIntegerValue other)
+    public IntegerValue remainder(ParticularIntegerValue other)
     throws ArithmeticException
     {
-        return new SpecificIntegerValue(this.value % other.value);
+        return new ParticularIntegerValue(this.value % other.value);
     }
 
-    public IntegerValue remainderOf(SpecificIntegerValue other)
+    public IntegerValue remainderOf(ParticularIntegerValue other)
     throws ArithmeticException
     {
-        return new SpecificIntegerValue(other.value % this.value);
+        return new ParticularIntegerValue(other.value % this.value);
     }
 
-    public IntegerValue shiftLeft(SpecificIntegerValue other)
+    public IntegerValue shiftLeft(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value << other.value);
+        return new ParticularIntegerValue(this.value << other.value);
     }
 
-    public IntegerValue shiftLeftOf(SpecificIntegerValue other)
+    public IntegerValue shiftRight(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(other.value << this.value);
+        return new ParticularIntegerValue(this.value >> other.value);
     }
 
-    public IntegerValue shiftRight(SpecificIntegerValue other)
+    public IntegerValue unsignedShiftRight(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value >> other.value);
+        return new ParticularIntegerValue(this.value >>> other.value);
     }
 
-    public IntegerValue shiftRightOf(SpecificIntegerValue other)
+    public IntegerValue shiftLeftOf(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(other.value >> this.value);
+        return new ParticularIntegerValue(other.value << this.value);
     }
 
-    public IntegerValue unsignedShiftRight(SpecificIntegerValue other)
+    public IntegerValue shiftRightOf(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value >>> other.value);
+        return new ParticularIntegerValue(other.value >> this.value);
     }
 
-    public IntegerValue unsignedShiftRightOf(SpecificIntegerValue other)
+    public IntegerValue unsignedShiftRightOf(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(other.value >>> this.value);
+        return new ParticularIntegerValue(other.value >>> this.value);
     }
 
-    public LongValue shiftLeftOf(SpecificLongValue other, ValueFactory valueFactory)
+    public LongValue shiftLeftOf(ParticularLongValue other)
     {
-        return valueFactory.createLongValue(other.value() << this.value);
+        return new ParticularLongValue(other.value() << this.value);
     }
 
-    public LongValue shiftRightOf(SpecificLongValue other, ValueFactory valueFactory)
+    public LongValue shiftRightOf(ParticularLongValue other)
     {
-        return valueFactory.createLongValue(other.value() >> this.value);
+        return new ParticularLongValue(other.value() >> this.value);
     }
 
-    public LongValue unsignedShiftRightOf(SpecificLongValue other, ValueFactory valueFactory)
+    public LongValue unsignedShiftRightOf(ParticularLongValue other)
     {
-        return valueFactory.createLongValue(other.value() >>> this.value);
+        return new ParticularLongValue(other.value() >>> this.value);
     }
 
-    public IntegerValue and(SpecificIntegerValue other)
+    public IntegerValue and(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value & other.value);
+        return new ParticularIntegerValue(this.value & other.value);
     }
 
-    public IntegerValue or(SpecificIntegerValue other)
+    public IntegerValue or(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value | other.value);
+        return new ParticularIntegerValue(this.value | other.value);
     }
 
-    public IntegerValue xor(SpecificIntegerValue other)
+    public IntegerValue xor(ParticularIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value ^ other.value);
+        return new ParticularIntegerValue(this.value ^ other.value);
     }
 
-    public int equal(SpecificIntegerValue other)
+    public int equal(ParticularIntegerValue other)
     {
         return this.value == other.value ? ALWAYS : NEVER;
     }
 
-    public int lessThan(SpecificIntegerValue other)
+    public int lessThan(ParticularIntegerValue other)
     {
         return this.value <  other.value ? ALWAYS : NEVER;
     }
 
-    public int lessThanOrEqual(SpecificIntegerValue other)
+    public int lessThanOrEqual(ParticularIntegerValue other)
     {
         return this.value <= other.value ? ALWAYS : NEVER;
     }
@@ -359,7 +354,7 @@ final class SpecificIntegerValue extends IntegerValue
 
     // Implementations for Value.
 
-    public boolean isSpecific()
+    public boolean isParticular()
     {
         return true;
     }
@@ -369,20 +364,20 @@ final class SpecificIntegerValue extends IntegerValue
 
     public boolean equals(Object object)
     {
-        return object          != null              &&
-               this.getClass() == object.getClass() &&
-               this.value      == ((SpecificIntegerValue)object).value;
+        return super.equals(object) &&
+               this.value == ((ParticularIntegerValue)object).value;
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode() ^ value;
+        return this.getClass().hashCode() ^
+               value;
     }
 
 
     public String toString()
     {
-        return "i:"+value;
+        return Integer.toString(value);
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/ParticularLongValue.java b/src/proguard/evaluation/value/ParticularLongValue.java
new file mode 100644
index 0000000..762c5ba
--- /dev/null
+++ b/src/proguard/evaluation/value/ParticularLongValue.java
@@ -0,0 +1,271 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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/src/proguard/evaluation/value/ReferenceValue.java b/src/proguard/evaluation/value/ReferenceValue.java
index 64829c1..bdc522b 100644
--- a/src/proguard/evaluation/value/ReferenceValue.java
+++ b/src/proguard/evaluation/value/ReferenceValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -38,9 +38,9 @@ public class ReferenceValue extends Category1Value
     private static final boolean DEBUG = false;
 
 
-    private final String  type;
-    private final Clazz   referencedClass;
-    private final boolean mayBeNull;
+    protected final String  type;
+    protected final Clazz   referencedClass;
+    protected final boolean mayBeNull;
 
 
     /**
@@ -216,6 +216,12 @@ public class ReferenceValue extends Category1Value
      */
     public ReferenceValue generalize(ReferenceValue 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;
 
@@ -461,7 +467,7 @@ public class ReferenceValue extends Category1Value
         return this.generalize(other.referenceValue());
     }
 
-    public boolean isSpecific()
+    public boolean isParticular()
     {
         return type == null;
     }
@@ -486,6 +492,11 @@ public class ReferenceValue extends Category1Value
 
     public boolean equals(Object object)
     {
+        if (this == object)
+        {
+            return true;
+        }
+        
         if (object == null ||
             this.getClass() != object.getClass())
         {
@@ -508,8 +519,8 @@ public class ReferenceValue extends Category1Value
 
     public String toString()
     {
-        return "a:" + (type == null ?
+        return type == null ?
             "null" :
-            type + (referencedClass == null ? "?" : "") + (mayBeNull ? "" : "!"));
+            type + (referencedClass == null ? "?" : "") + (mayBeNull ? "" : "!");
     }
 }
diff --git a/src/proguard/evaluation/value/SpecificDoubleValue.java b/src/proguard/evaluation/value/SpecificDoubleValue.java
index 7076ce5..973b678 100644
--- a/src/proguard/evaluation/value/SpecificDoubleValue.java
+++ b/src/proguard/evaluation/value/SpecificDoubleValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -14,7 +14,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  * more details.
  *
- * You should have received a copy of the GNU General Public License adouble
+ * You should have received a copy of the GNU General Public License along
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
@@ -25,33 +25,33 @@ package proguard.evaluation.value;
  *
  * @author Eric Lafortune
  */
-final class SpecificDoubleValue extends DoubleValue
+abstract class SpecificDoubleValue extends DoubleValue
 {
-    private final double value;
-
+    // Implementations of unary methods of DoubleValue.
 
-    /**
-     * Creates a new specific double value.
-     */
-    public SpecificDoubleValue(double value)
+    public DoubleValue negate()
     {
-        this.value = value;
+        return new NegatedDoubleValue(this);
     }
 
+    public IntegerValue convertToInteger()
+    {
+        return new ConvertedIntegerValue(this);
+    }
 
-    // Implementations for DoubleValue.
+    public LongValue convertToLong()
+    {
+        return new ConvertedLongValue(this);
+    }
 
-    public double value()
+    public FloatValue convertToFloat()
     {
-        return value;
+        return new ConvertedFloatValue(this);
     }
 
 
     // Implementations of binary methods of DoubleValue.
 
-    // Perhaps the other value arguments are more specific than apparent
-    // in these methods, so delegate to them.
-
     public DoubleValue generalize(DoubleValue other)
     {
         return other.generalize(this);
@@ -97,32 +97,9 @@ final class SpecificDoubleValue extends DoubleValue
         return other.remainder(this);
     }
 
-    public IntegerValue compare(DoubleValue other, ValueFactory valueFactory)
-    {
-        return other.compareReverse(this, valueFactory);
-    }
-
-
-    // Implementations of unary methods of DoubleValue.
-
-    public DoubleValue negate()
-    {
-        return new SpecificDoubleValue(-value);
-    }
-
-    public IntegerValue convertToInteger(ValueFactory valueFactory)
-    {
-        return new SpecificIntegerValue((int)value);
-    }
-
-    public LongValue convertToLong(ValueFactory valueFactory)
+    public IntegerValue compare(DoubleValue other)
     {
-        return new SpecificLongValue((long)value);
-    }
-
-    public FloatValue convertToFloat(ValueFactory valueFactory)
-    {
-        return new SpecificFloatValue((float)value);
+        return other.compareReverse(this);
     }
 
 
@@ -131,54 +108,54 @@ final class SpecificDoubleValue extends DoubleValue
 
     public DoubleValue generalize(SpecificDoubleValue other)
     {
-        return this.value == other.value ? this : ValueFactory.DOUBLE_VALUE;
+        return this.equals(other) ? this : ValueFactory.DOUBLE_VALUE;
     }
 
     public DoubleValue add(SpecificDoubleValue other)
     {
-        return new SpecificDoubleValue(this.value + other.value);
+        return new CompositeDoubleValue(this, CompositeDoubleValue.ADD, other);
     }
 
     public DoubleValue subtract(SpecificDoubleValue other)
     {
-        return new SpecificDoubleValue(this.value - other.value);
+        return new CompositeDoubleValue(this, CompositeDoubleValue.SUBTRACT, other);
     }
 
     public DoubleValue subtractFrom(SpecificDoubleValue other)
     {
-        return new SpecificDoubleValue(other.value - this.value);
+        return new CompositeDoubleValue(other, CompositeDoubleValue.SUBTRACT, this);
     }
 
     public DoubleValue multiply(SpecificDoubleValue other)
     {
-        return new SpecificDoubleValue(this.value * other.value);
+        return new CompositeDoubleValue(this, CompositeDoubleValue.MULTIPLY, other);
     }
 
     public DoubleValue divide(SpecificDoubleValue other)
     {
-        return new SpecificDoubleValue(this.value / other.value);
+        return new CompositeDoubleValue(this, CompositeDoubleValue.DIVIDE, other);
     }
 
     public DoubleValue divideOf(SpecificDoubleValue other)
     {
-        return new SpecificDoubleValue(other.value / this.value);
+        return new CompositeDoubleValue(other, CompositeDoubleValue.DIVIDE, this);
     }
 
     public DoubleValue remainder(SpecificDoubleValue other)
     {
-        return new SpecificDoubleValue(this.value % other.value);
+        return new CompositeDoubleValue(this, CompositeDoubleValue.REMAINDER, other);
     }
 
     public DoubleValue remainderOf(SpecificDoubleValue other)
     {
-        return new SpecificDoubleValue(other.value % this.value);
+        return new CompositeDoubleValue(other, CompositeDoubleValue.REMAINDER, this);
     }
 
-    public IntegerValue compare(SpecificDoubleValue other, ValueFactory valueFactory)
+    public IntegerValue compare(SpecificDoubleValue other)
     {
-        return this.value <  other.value ? SpecificValueFactory.INTEGER_VALUE_M1 :
-               this.value == other.value ? SpecificValueFactory.INTEGER_VALUE_0  :
-                                           SpecificValueFactory.INTEGER_VALUE_1;
+        return this.equals(other) ?
+            SpecificValueFactory.INTEGER_VALUE_0 :
+            new ComparisonValue(this, other);
     }
 
 
@@ -194,20 +171,13 @@ final class SpecificDoubleValue extends DoubleValue
 
     public boolean equals(Object object)
     {
-        return object          != null              &&
-               this.getClass() == object.getClass() &&
-               this.value      == ((SpecificDoubleValue)object).value;
+        return object != null &&
+               this.getClass() == object.getClass();
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode() ^ (int)Double.doubleToLongBits(value);
-    }
-
-
-    public String toString()
-    {
-        return "d:"+value;
+        return this.getClass().hashCode();
     }
 }
diff --git a/src/proguard/evaluation/value/SpecificFloatValue.java b/src/proguard/evaluation/value/SpecificFloatValue.java
index b0e37d3..e507e76 100644
--- a/src/proguard/evaluation/value/SpecificFloatValue.java
+++ b/src/proguard/evaluation/value/SpecificFloatValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -14,7 +14,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  * more details.
  *
- * You should have received a copy of the GNU General Public License afloat
+ * You should have received a copy of the GNU General Public License along
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
@@ -25,33 +25,33 @@ package proguard.evaluation.value;
  *
  * @author Eric Lafortune
  */
-final class SpecificFloatValue extends FloatValue
+abstract class SpecificFloatValue extends FloatValue
 {
-    private final float value;
-
+    // Implementations of unary methods of FloatValue.
 
-    /**
-     * Creates a new specific float value.
-     */
-    public SpecificFloatValue(float value)
+    public FloatValue negate()
     {
-        this.value = value;
+        return new NegatedFloatValue(this);
     }
 
+    public IntegerValue convertToInteger()
+    {
+        return new ConvertedIntegerValue(this);
+    }
 
-    // Implementations for FloatValue.
+    public LongValue convertToLong()
+    {
+        return new ConvertedLongValue(this);
+    }
 
-    public float value()
+    public DoubleValue convertToDouble()
     {
-        return value;
+        return new ConvertedDoubleValue(this);
     }
 
 
     // Implementations of binary methods of FloatValue.
 
-    // Perhaps the other value arguments are more specific than apparent
-    // in these methods, so delegate to them.
-
     public FloatValue generalize(FloatValue other)
     {
         return other.generalize(this);
@@ -97,32 +97,9 @@ final class SpecificFloatValue extends FloatValue
         return other.remainder(this);
     }
 
-    public IntegerValue compare(FloatValue other, ValueFactory valueFactory)
-    {
-        return other.compareReverse(this, valueFactory);
-    }
-
-
-    // Implementations of unary methods of FloatValue.
-
-    public FloatValue negate()
-    {
-        return new SpecificFloatValue(-value);
-    }
-
-    public IntegerValue convertToInteger(ValueFactory valueFactory)
-    {
-        return valueFactory.createIntegerValue((int)value);
-    }
-
-    public LongValue convertToLong(ValueFactory valueFactory)
+    public IntegerValue compare(FloatValue other)
     {
-        return valueFactory.createLongValue((long)value);
-    }
-
-    public DoubleValue convertToDouble(ValueFactory valueFactory)
-    {
-        return valueFactory.createDoubleValue((double)value);
+        return other.compareReverse(this);
     }
 
 
@@ -131,54 +108,54 @@ final class SpecificFloatValue extends FloatValue
 
     public FloatValue generalize(SpecificFloatValue other)
     {
-        return this.value == other.value ? this : ValueFactory.FLOAT_VALUE;
+        return this.equals(other) ? this : ValueFactory.FLOAT_VALUE;
     }
 
     public FloatValue add(SpecificFloatValue other)
     {
-        return new SpecificFloatValue(this.value + other.value);
+        return new CompositeFloatValue(this, CompositeFloatValue.ADD, other);
     }
 
     public FloatValue subtract(SpecificFloatValue other)
     {
-        return new SpecificFloatValue(this.value - other.value);
+        return new CompositeFloatValue(this, CompositeFloatValue.SUBTRACT, other);
     }
 
     public FloatValue subtractFrom(SpecificFloatValue other)
     {
-        return new SpecificFloatValue(other.value - this.value);
+        return new CompositeFloatValue(other, CompositeFloatValue.SUBTRACT, this);
     }
 
     public FloatValue multiply(SpecificFloatValue other)
     {
-        return new SpecificFloatValue(this.value * other.value);
+        return new CompositeFloatValue(this, CompositeFloatValue.MULTIPLY, other);
     }
 
     public FloatValue divide(SpecificFloatValue other)
     {
-        return new SpecificFloatValue(this.value / other.value);
+        return new CompositeFloatValue(this, CompositeFloatValue.DIVIDE, other);
     }
 
     public FloatValue divideOf(SpecificFloatValue other)
     {
-        return new SpecificFloatValue(other.value / this.value);
+        return new CompositeFloatValue(other, CompositeFloatValue.DIVIDE, this);
     }
 
     public FloatValue remainder(SpecificFloatValue other)
     {
-        return new SpecificFloatValue(this.value % other.value);
+        return new CompositeFloatValue(this, CompositeFloatValue.REMAINDER, other);
     }
 
     public FloatValue remainderOf(SpecificFloatValue other)
     {
-        return new SpecificFloatValue(other.value % this.value);
+        return new CompositeFloatValue(other, CompositeFloatValue.REMAINDER, this);
     }
 
-    public IntegerValue compare(SpecificFloatValue other, ValueFactory valueFactory)
+    public IntegerValue compare(SpecificFloatValue other)
     {
-        return this.value <  other.value ? valueFactory.createIntegerValue(-1) :
-               this.value == other.value ? valueFactory.createIntegerValue(0) :
-                                           valueFactory.createIntegerValue(1);
+        return this.equals(other) ?
+            SpecificValueFactory.INTEGER_VALUE_0 :
+            new ComparisonValue(this, other);
     }
 
 
@@ -194,20 +171,13 @@ final class SpecificFloatValue extends FloatValue
 
     public boolean equals(Object object)
     {
-        return object          != null              &&
-               this.getClass() == object.getClass() &&
-               this.value      == ((SpecificFloatValue)object).value;
+        return object != null &&
+               this.getClass() == object.getClass();
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode() ^ Float.floatToIntBits(value);
-    }
-
-
-    public String toString()
-    {
-        return "f:"+value;
+        return this.getClass().hashCode();
     }
 }
diff --git a/src/proguard/evaluation/value/SpecificIntegerValue.java b/src/proguard/evaluation/value/SpecificIntegerValue.java
index 6ec5dec..5e1e594 100644
--- a/src/proguard/evaluation/value/SpecificIntegerValue.java
+++ b/src/proguard/evaluation/value/SpecificIntegerValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -25,30 +25,48 @@ package proguard.evaluation.value;
  *
  * @author Eric Lafortune
  */
-final class SpecificIntegerValue extends IntegerValue
+abstract class SpecificIntegerValue extends IntegerValue
 {
-    private final int value;
+    // 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 SpecificIntegerValue(int value)
+    public IntegerValue convertToShort()
     {
-        this.value = value;
+        return new ConvertedShortValue(this);
     }
 
+    public LongValue convertToLong()
+    {
+        return new ConvertedLongValue(this);
+    }
 
-    // Implementations for IntegerValue.
+    public FloatValue convertToFloat()
+    {
+        return new ConvertedFloatValue(this);
+    }
 
-    public int value()
+    public DoubleValue convertToDouble()
     {
-        return value;
+        return new ConvertedDoubleValue(this);
     }
 
 
     // Implementations of binary methods of IntegerValue.
 
-    // Perhaps the other value arguments are more specific than apparent
-    // in these methods, so delegate to them.
-
     public IntegerValue generalize(IntegerValue other)
     {
         return other.generalize(this);
@@ -174,186 +192,141 @@ final class SpecificIntegerValue extends IntegerValue
     }
 
 
-    // Implementations of unary methods of IntegerValue.
-
-    public IntegerValue negate()
-    {
-        return new SpecificIntegerValue(-value);
-    }
-
-    public IntegerValue convertToByte(ValueFactory valueFactory)
-    {
-        int byteValue = (byte)value;
-
-        return byteValue == value ?
-            this :
-            new SpecificIntegerValue(byteValue);
-    }
-
-    public IntegerValue convertToCharacter(ValueFactory valueFactory)
-    {
-        int charValue = (char)value;
-
-        return charValue == value ?
-            this :
-            new SpecificIntegerValue(charValue);
-    }
-
-    public IntegerValue convertToShort(ValueFactory valueFactory)
-    {
-        int shortValue = (short)value;
-
-        return shortValue == value ?
-            this :
-            new SpecificIntegerValue(shortValue);
-    }
-
-    public IntegerValue convertToInteger(ValueFactory valueFactory)
-    {
-        return this;
-    }
-
-    public LongValue convertToLong(ValueFactory valueFactory)
-    {
-        return valueFactory.createLongValue((long)value);
-    }
-
-    public FloatValue convertToFloat(ValueFactory valueFactory)
-    {
-        return valueFactory.createFloatValue((float)value);
-    }
-
-    public DoubleValue convertToDouble(ValueFactory valueFactory)
-    {
-        return valueFactory.createDoubleValue((double)value);
-    }
-
-
     // Implementations of binary IntegerValue methods with SpecificIntegerValue
     // arguments.
 
     public IntegerValue generalize(SpecificIntegerValue other)
     {
-        return this.value == other.value ? this : ValueFactory.INTEGER_VALUE;
+        return this.equals(other) ? this : ValueFactory.INTEGER_VALUE;
     }
 
     public IntegerValue add(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value + other.value);
+        return new CompositeIntegerValue(this, CompositeIntegerValue.ADD, other);
     }
 
     public IntegerValue subtract(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value - other.value);
+        return this.equals(other) ?
+            SpecificValueFactory.INTEGER_VALUE_0 :
+            new CompositeIntegerValue(this, CompositeIntegerValue.SUBTRACT, other);
     }
 
     public IntegerValue subtractFrom(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(other.value - this.value);
+        return this.equals(other) ?
+            SpecificValueFactory.INTEGER_VALUE_0 :
+            new CompositeIntegerValue(other, CompositeIntegerValue.SUBTRACT, this);
     }
 
     public IntegerValue multiply(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value * other.value);
+        return new CompositeIntegerValue(this, CompositeIntegerValue.MULTIPLY, other);
     }
 
     public IntegerValue divide(SpecificIntegerValue other)
     throws ArithmeticException
     {
-        return new SpecificIntegerValue(this.value / other.value);
+        return new CompositeIntegerValue(this, CompositeIntegerValue.DIVIDE, other);
     }
 
     public IntegerValue divideOf(SpecificIntegerValue other)
     throws ArithmeticException
     {
-        return new SpecificIntegerValue(other.value / this.value);
+        return new CompositeIntegerValue(other, CompositeIntegerValue.DIVIDE, this);
     }
 
     public IntegerValue remainder(SpecificIntegerValue other)
     throws ArithmeticException
     {
-        return new SpecificIntegerValue(this.value % other.value);
+        return new CompositeIntegerValue(this, CompositeIntegerValue.REMAINDER, other);
     }
 
     public IntegerValue remainderOf(SpecificIntegerValue other)
     throws ArithmeticException
     {
-        return new SpecificIntegerValue(other.value % this.value);
+        return new CompositeIntegerValue(other, CompositeIntegerValue.REMAINDER, this);
     }
 
     public IntegerValue shiftLeft(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value << other.value);
+        return new CompositeIntegerValue(this, CompositeIntegerValue.SHIFT_LEFT, other);
     }
 
-    public IntegerValue shiftLeftOf(SpecificIntegerValue other)
+    public IntegerValue shiftRight(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(other.value << this.value);
+        return new CompositeIntegerValue(this, CompositeIntegerValue.SHIFT_RIGHT, other);
     }
 
-    public IntegerValue shiftRight(SpecificIntegerValue other)
+    public IntegerValue unsignedShiftRight(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value >> other.value);
+        return new CompositeIntegerValue(this, CompositeIntegerValue.UNSIGNED_SHIFT_RIGHT, other);
     }
 
-    public IntegerValue shiftRightOf(SpecificIntegerValue other)
+    public IntegerValue shiftLeftOf(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(other.value >> this.value);
+        return new CompositeIntegerValue(other, CompositeIntegerValue.SHIFT_LEFT, this);
     }
 
-    public IntegerValue unsignedShiftRight(SpecificIntegerValue other)
+    public IntegerValue shiftRightOf(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value >>> other.value);
+        return new CompositeIntegerValue(other, CompositeIntegerValue.SHIFT_RIGHT, this);
     }
 
     public IntegerValue unsignedShiftRightOf(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(other.value >>> this.value);
+        return new CompositeIntegerValue(other, CompositeIntegerValue.UNSIGNED_SHIFT_RIGHT, this);
     }
 
-    public LongValue shiftLeftOf(SpecificLongValue other, ValueFactory valueFactory)
+    public LongValue shiftLeftOf(SpecificLongValue other)
     {
-        return valueFactory.createLongValue(other.value() << this.value);
+        return new CompositeLongValue(other, CompositeLongValue.SHIFT_LEFT, this);
     }
 
-    public LongValue shiftRightOf(SpecificLongValue other, ValueFactory valueFactory)
+    public LongValue shiftRightOf(SpecificLongValue other)
     {
-        return valueFactory.createLongValue(other.value() >> this.value);
+        return new CompositeLongValue(other, CompositeLongValue.SHIFT_RIGHT, this);
     }
 
-    public LongValue unsignedShiftRightOf(SpecificLongValue other, ValueFactory valueFactory)
+    public LongValue unsignedShiftRightOf(SpecificLongValue other)
     {
-        return valueFactory.createLongValue(other.value() >>> this.value);
+        return new CompositeLongValue(other, CompositeLongValue.UNSIGNED_SHIFT_RIGHT, this);
     }
 
     public IntegerValue and(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value & other.value);
+        return this.equals(other) ?
+            this :
+            new CompositeIntegerValue(other, CompositeIntegerValue.AND, this);
     }
 
     public IntegerValue or(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value | other.value);
+        return this.equals(other) ?
+            this :
+            new CompositeIntegerValue(other, CompositeIntegerValue.OR, this);
     }
 
     public IntegerValue xor(SpecificIntegerValue other)
     {
-        return new SpecificIntegerValue(this.value ^ other.value);
+        return this.equals(other) ?
+            SpecificValueFactory.INTEGER_VALUE_0 :
+            new CompositeIntegerValue(other, CompositeIntegerValue.XOR, this);
     }
 
     public int equal(SpecificIntegerValue other)
     {
-        return this.value == other.value ? ALWAYS : NEVER;
+        return this.equals(other) ? ALWAYS : MAYBE;
     }
 
     public int lessThan(SpecificIntegerValue other)
     {
-        return this.value <  other.value ? ALWAYS : NEVER;
+        return this.equals(other) ? NEVER : MAYBE;
     }
 
     public int lessThanOrEqual(SpecificIntegerValue other)
     {
-        return this.value <= other.value ? ALWAYS : NEVER;
+        return this.equals(other) ? ALWAYS : MAYBE;
     }
 
 
@@ -369,20 +342,13 @@ final class SpecificIntegerValue extends IntegerValue
 
     public boolean equals(Object object)
     {
-        return object          != null              &&
-               this.getClass() == object.getClass() &&
-               this.value      == ((SpecificIntegerValue)object).value;
+        return object != null &&
+               this.getClass() == object.getClass();
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode() ^ value;
-    }
-
-
-    public String toString()
-    {
-        return "i:"+value;
+        return this.getClass().hashCode();
     }
 }
diff --git a/src/proguard/evaluation/value/SpecificLongValue.java b/src/proguard/evaluation/value/SpecificLongValue.java
index c92e54d..0b07daf 100644
--- a/src/proguard/evaluation/value/SpecificLongValue.java
+++ b/src/proguard/evaluation/value/SpecificLongValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -25,33 +25,33 @@ package proguard.evaluation.value;
  *
  * @author Eric Lafortune
  */
-final class SpecificLongValue extends LongValue
+abstract class SpecificLongValue extends LongValue
 {
-    private final long value;
-
+    // Implementations of unary methods of LongValue.
 
-    /**
-     * Creates a new specific long value.
-     */
-    public SpecificLongValue(long value)
+    public LongValue negate()
     {
-        this.value = value;
+        return new NegatedLongValue(this);
     }
 
+    public IntegerValue convertToInteger()
+    {
+        return new ConvertedIntegerValue(this);
+    }
 
-    // Implementations for LongValue.
+    public FloatValue convertToFloat()
+    {
+        return new ConvertedFloatValue(this);
+    }
 
-    public long value()
+    public DoubleValue convertToDouble()
     {
-        return value;
+        return new ConvertedDoubleValue(this);
     }
 
 
     // Implementations of binary methods of LongValue.
 
-    // Perhaps the other value arguments are more specific than apparent
-    // in these methods, so delegate to them.
-
     public LongValue generalize(LongValue other)
     {
         return other.generalize(this);
@@ -78,21 +78,25 @@ final class SpecificLongValue extends LongValue
     }
 
     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);
     }
@@ -127,32 +131,9 @@ final class SpecificLongValue extends LongValue
         return other.xor(this);
     }
 
-    public IntegerValue compare(LongValue other, ValueFactory valueFactory)
-    {
-        return other.compareReverse(this, valueFactory);
-    }
-
-
-    // Implementations of unary methods of LongValue.
-
-    public LongValue negate()
-    {
-        return new SpecificLongValue(-value);
-    }
-
-    public IntegerValue convertToInteger(ValueFactory valueFactory)
-    {
-        return valueFactory.createIntegerValue((int)value);
-    }
-
-    public FloatValue convertToFloat(ValueFactory valueFactory)
+    public IntegerValue compare(LongValue other)
     {
-        return valueFactory.createFloatValue((float)value);
-    }
-
-    public DoubleValue convertToDouble(ValueFactory valueFactory)
-    {
-        return valueFactory.createDoubleValue((double)value);
+        return other.compareReverse(this);
     }
 
 
@@ -161,84 +142,96 @@ final class SpecificLongValue extends LongValue
 
     public LongValue generalize(SpecificLongValue other)
     {
-        return this.value == other.value ? this : ValueFactory.LONG_VALUE;
+        return this.equals(other) ? this : ValueFactory.LONG_VALUE;
     }
 
     public LongValue add(SpecificLongValue other)
     {
-        return new SpecificLongValue(this.value + other.value);
+        return new CompositeLongValue(this, CompositeLongValue.ADD, other);
     }
 
     public LongValue subtract(SpecificLongValue other)
     {
-        return new SpecificLongValue(this.value - other.value);
+        return this.equals(other) ?
+            SpecificValueFactory.LONG_VALUE_0 :
+            new CompositeLongValue(this, CompositeLongValue.SUBTRACT, other);
     }
 
     public LongValue subtractFrom(SpecificLongValue other)
     {
-        return new SpecificLongValue(other.value - this.value);
+        return this.equals(other) ?
+            SpecificValueFactory.LONG_VALUE_0 :
+            new CompositeLongValue(other, CompositeLongValue.SUBTRACT, this);
     }
 
     public LongValue multiply(SpecificLongValue other)
     {
-        return new SpecificLongValue(this.value * other.value);
+        return new CompositeLongValue(this, CompositeLongValue.MULTIPLY, other);
     }
 
     public LongValue divide(SpecificLongValue other)
+    throws ArithmeticException
     {
-        return new SpecificLongValue(this.value / other.value);
+        return new CompositeLongValue(this, CompositeLongValue.DIVIDE, other);
     }
 
     public LongValue divideOf(SpecificLongValue other)
+    throws ArithmeticException
     {
-        return new SpecificLongValue(other.value / this.value);
+        return new CompositeLongValue(other, CompositeLongValue.DIVIDE, this);
     }
 
     public LongValue remainder(SpecificLongValue other)
+    throws ArithmeticException
     {
-        return new SpecificLongValue(this.value % other.value);
+        return new CompositeLongValue(this, CompositeLongValue.REMAINDER, other);
     }
 
     public LongValue remainderOf(SpecificLongValue other)
+    throws ArithmeticException
     {
-        return new SpecificLongValue(other.value % this.value);
+        return new CompositeLongValue(other, CompositeLongValue.REMAINDER, this);
     }
 
-    public LongValue shiftLeft(SpecificIntegerValue other)
+    public LongValue shiftLeft(SpecificLongValue other)
     {
-        return new SpecificLongValue(this.value << other.value());
+        return new CompositeLongValue(this, CompositeLongValue.SHIFT_LEFT, other);
     }
 
-    public LongValue shiftRight(SpecificIntegerValue other)
+    public LongValue shiftRight(SpecificLongValue other)
     {
-        return new SpecificLongValue(this.value >> other.value());
+        return new CompositeLongValue(this, CompositeLongValue.SHIFT_RIGHT, other);
     }
 
-    public LongValue unsignedShiftRight(SpecificIntegerValue other)
+    public LongValue unsignedShiftRight(SpecificLongValue other)
     {
-        return new SpecificLongValue(this.value >>> other.value());
+        return new CompositeLongValue(this, CompositeLongValue.UNSIGNED_SHIFT_RIGHT, other);
     }
 
     public LongValue and(SpecificLongValue other)
     {
-        return new SpecificLongValue(this.value & other.value);
+        return this.equals(other) ?
+            this :
+            new CompositeLongValue(other, CompositeLongValue.AND, this);
     }
 
     public LongValue or(SpecificLongValue other)
     {
-        return new SpecificLongValue(this.value | other.value);
+        return this.equals(other) ?
+            this :
+            new CompositeLongValue(other, CompositeLongValue.OR, this);
     }
 
     public LongValue xor(SpecificLongValue other)
     {
-        return new SpecificLongValue(this.value ^ other.value);
+        return this.equals(other) ?
+            SpecificValueFactory.LONG_VALUE_0 :
+            new CompositeLongValue(other, CompositeLongValue.XOR, this);
     }
 
-    public IntegerValue compare(SpecificLongValue other, ValueFactory valueFactory)
+    public IntegerValue compare(SpecificLongValue other)
     {
-        return this.value <  other.value ? valueFactory.createIntegerValue(-1) :
-               this.value == other.value ? valueFactory.createIntegerValue(0) :
-                                           valueFactory.createIntegerValue(1);
+        return new ComparisonValue(this, other);
     }
 
 
@@ -254,20 +247,13 @@ final class SpecificLongValue extends LongValue
 
     public boolean equals(Object object)
     {
-        return object          != null              &&
-               this.getClass() == object.getClass() &&
-               this.value      == ((SpecificLongValue)object).value;
+        return object != null &&
+               this.getClass() == object.getClass();
     }
 
 
     public int hashCode()
     {
-        return this.getClass().hashCode() ^ (int)value;
-    }
-
-
-    public String toString()
-    {
-        return "l:"+value;
+        return this.getClass().hashCode();
     }
 }
diff --git a/src/proguard/evaluation/value/SpecificValueFactory.java b/src/proguard/evaluation/value/SpecificValueFactory.java
index 5efec24..5bc5b7e 100644
--- a/src/proguard/evaluation/value/SpecificValueFactory.java
+++ b/src/proguard/evaluation/value/SpecificValueFactory.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -29,20 +29,20 @@ public class SpecificValueFactory
 extends      ValueFactory
 {
     // Shared copies of Value objects, to avoid creating a lot of objects.
-    static final IntegerValue INTEGER_VALUE_M1 = new SpecificIntegerValue(-1);
-    static final IntegerValue INTEGER_VALUE_0  = new SpecificIntegerValue(0);
-    static final IntegerValue INTEGER_VALUE_1  = new SpecificIntegerValue(1);
-    static final IntegerValue INTEGER_VALUE_2  = new SpecificIntegerValue(2);
-    static final IntegerValue INTEGER_VALUE_3  = new SpecificIntegerValue(3);
-    static final IntegerValue INTEGER_VALUE_4  = new SpecificIntegerValue(4);
-    static final IntegerValue INTEGER_VALUE_5  = new SpecificIntegerValue(5);
-    static final LongValue    LONG_VALUE_0     = new SpecificLongValue(0);
-    static final LongValue    LONG_VALUE_1     = new SpecificLongValue(1);
-    static final FloatValue   FLOAT_VALUE_0    = new SpecificFloatValue(0.0f);
-    static final FloatValue   FLOAT_VALUE_1    = new SpecificFloatValue(1.0f);
-    static final FloatValue   FLOAT_VALUE_2    = new SpecificFloatValue(2.0f);
-    static final DoubleValue  DOUBLE_VALUE_0   = new SpecificDoubleValue(0.0);
-    static final DoubleValue  DOUBLE_VALUE_1   = new SpecificDoubleValue(1.0);
+    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);
 
 
     // Implementations for ValueFactory.
@@ -58,7 +58,7 @@ extends      ValueFactory
             case  3: return INTEGER_VALUE_3;
             case  4: return INTEGER_VALUE_4;
             case  5: return INTEGER_VALUE_5;
-            default: return new SpecificIntegerValue(value);
+            default: return new ParticularIntegerValue(value);
         }
     }
 
@@ -67,7 +67,7 @@ extends      ValueFactory
     {
         return value == 0 ? LONG_VALUE_0 :
                value == 1 ? LONG_VALUE_1 :
-                            new SpecificLongValue(value);
+                            new ParticularLongValue(value);
     }
 
 
@@ -76,7 +76,7 @@ extends      ValueFactory
         return value == 0.0f ? FLOAT_VALUE_0 :
                value == 1.0f ? FLOAT_VALUE_1 :
                value == 2.0f ? FLOAT_VALUE_2 :
-                               new SpecificFloatValue(value);
+                               new ParticularFloatValue(value);
     }
 
 
@@ -84,6 +84,6 @@ extends      ValueFactory
     {
         return value == 0.0 ? DOUBLE_VALUE_0 :
                value == 1.0 ? DOUBLE_VALUE_1 :
-                              new SpecificDoubleValue(value);
+                              new ParticularDoubleValue(value);
     }
 }
diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/TopValue.java
index 9bb6ca8..0a53e7e 100644
--- a/src/proguard/evaluation/value/TopValue.java
+++ b/src/proguard/evaluation/value/TopValue.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -31,6 +31,16 @@ 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;
diff --git a/src/proguard/evaluation/value/UnknownDoubleValue.java b/src/proguard/evaluation/value/UnknownDoubleValue.java
new file mode 100644
index 0000000..dd2d519
--- /dev/null
+++ b/src/proguard/evaluation/value/UnknownDoubleValue.java
@@ -0,0 +1,125 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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/src/proguard/evaluation/value/UnknownFloatValue.java b/src/proguard/evaluation/value/UnknownFloatValue.java
new file mode 100644
index 0000000..bd1d745
--- /dev/null
+++ b/src/proguard/evaluation/value/UnknownFloatValue.java
@@ -0,0 +1,125 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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 "d";
+    }
+}
\ No newline at end of file
diff --git a/src/proguard/evaluation/value/UnknownIntegerValue.java b/src/proguard/evaluation/value/UnknownIntegerValue.java
new file mode 100644
index 0000000..f25b398
--- /dev/null
+++ b/src/proguard/evaluation/value/UnknownIntegerValue.java
@@ -0,0 +1,216 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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/src/proguard/evaluation/value/UnknownLongValue.java b/src/proguard/evaluation/value/UnknownLongValue.java
new file mode 100644
index 0000000..f169208
--- /dev/null
+++ b/src/proguard/evaluation/value/UnknownLongValue.java
@@ -0,0 +1,160 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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/src/proguard/evaluation/value/Value.java b/src/proguard/evaluation/value/Value.java
index 2cc4619..f3f6393 100644
--- a/src/proguard/evaluation/value/Value.java
+++ b/src/proguard/evaluation/value/Value.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -98,7 +98,7 @@ public abstract class Value
     }
 
     /**
-     * Returns this Value as a InstructionOffsetValue.
+     * Returns this Value as an InstructionOffsetValue.
      */
     public InstructionOffsetValue instructionOffsetValue()
     {
@@ -107,7 +107,8 @@ public abstract class Value
 
 
     /**
-     * Returns whether this Value represents a single specific value.
+     * Returns whether this Value represents a single specific (but possibly
+     * unknown) value.
      */
     public boolean isSpecific()
     {
@@ -116,6 +117,16 @@ public abstract class Value
 
 
     /**
+     * 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);
diff --git a/src/proguard/evaluation/value/ValueFactory.java b/src/proguard/evaluation/value/ValueFactory.java
index 72f3e68..1a84d58 100644
--- a/src/proguard/evaluation/value/ValueFactory.java
+++ b/src/proguard/evaluation/value/ValueFactory.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -31,10 +31,10 @@ import proguard.classfile.util.ClassUtil;
 public class ValueFactory
 {
     // Shared copies of Value objects, to avoid creating a lot of objects.
-    static final IntegerValue INTEGER_VALUE = new IntegerValue();
-    static final LongValue    LONG_VALUE    = new LongValue();
-    static final FloatValue   FLOAT_VALUE   = new FloatValue();
-    static final DoubleValue  DOUBLE_VALUE  = new DoubleValue();
+    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 ReferenceValue(null, null, true);
     static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL = new ReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT, null, true);
@@ -42,7 +42,7 @@ public class ValueFactory
 
 
     /**
-     * Creates a new undefined Value of the given type.
+     * Creates a new Value of the given type.
      * The type must be a fully specified internal type for primitives, classes,
      * or arrays.
      */
@@ -55,10 +55,10 @@ public class ValueFactory
             case ClassConstants.INTERNAL_TYPE_BYTE:
             case ClassConstants.INTERNAL_TYPE_CHAR:
             case ClassConstants.INTERNAL_TYPE_SHORT:
-            case ClassConstants.INTERNAL_TYPE_INT:     return INTEGER_VALUE;
-            case ClassConstants.INTERNAL_TYPE_LONG:    return LONG_VALUE;
-            case ClassConstants.INTERNAL_TYPE_FLOAT:   return FLOAT_VALUE;
-            case ClassConstants.INTERNAL_TYPE_DOUBLE:  return DOUBLE_VALUE;
+            case ClassConstants.INTERNAL_TYPE_INT:     return createIntegerValue();
+            case ClassConstants.INTERNAL_TYPE_LONG:    return createLongValue();
+            case ClassConstants.INTERNAL_TYPE_FLOAT:   return createFloatValue();
+            case ClassConstants.INTERNAL_TYPE_DOUBLE:  return createDoubleValue();
             default:                                   return createReferenceValue(ClassUtil.isInternalArrayType(type) ?
                                                                                        type :
                                                                                        ClassUtil.internalClassNameFromClassType(type),
@@ -76,7 +76,7 @@ public class ValueFactory
     }
 
     /**
-     * Creates a new IntegerValue with a given specific value.
+     * Creates a new IntegerValue with a given particular value.
      */
     public IntegerValue createIntegerValue(int value)
     {
@@ -93,7 +93,7 @@ public class ValueFactory
     }
 
     /**
-     * Creates a new LongValue with a given specific value.
+     * Creates a new LongValue with a given particular value.
      */
     public LongValue createLongValue(long value)
     {
@@ -110,7 +110,7 @@ public class ValueFactory
     }
 
     /**
-     * Creates a new FloatValue with a given specific value.
+     * Creates a new FloatValue with a given particular value.
      */
     public FloatValue createFloatValue(float value)
     {
@@ -127,7 +127,7 @@ public class ValueFactory
     }
 
     /**
-     * Creates a new DoubleValue with a given specific value.
+     * Creates a new DoubleValue with a given particular value.
      */
     public DoubleValue createDoubleValue(double value)
     {
diff --git a/src/proguard/gui/ClassPathPanel.java b/src/proguard/gui/ClassPathPanel.java
index d336f2f..29532f3 100644
--- a/src/proguard/gui/ClassPathPanel.java
+++ b/src/proguard/gui/ClassPathPanel.java
@@ -1,8 +1,8 @@
-/* $Id: ClassPathPanel.java,v 1.22 2007/08/18 10:34:56 eric Exp $
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
  *
- * ProGuard -- shrinking, optimization, and obfuscation of Java class files.
- *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ClassSpecificationDialog.java b/src/proguard/gui/ClassSpecificationDialog.java
index 794d96c..d2478b2 100644
--- a/src/proguard/gui/ClassSpecificationDialog.java
+++ b/src/proguard/gui/ClassSpecificationDialog.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -62,8 +62,10 @@ final class ClassSpecificationDialog extends JDialog
 
     private final JRadioButton[] publicRadioButtons;
     private final JRadioButton[] finalRadioButtons;
-    private final JRadioButton[] interfaceRadioButtons;
     private final JRadioButton[] abstractRadioButtons;
+    private final JRadioButton[] enumRadioButtons;
+    private final JRadioButton[] annotationRadioButtons;
+    private final JRadioButton[] interfaceRadioButtons;
 
     private final JTextField annotationTypeTextField        = new JTextField(20);
     private final JTextField classNameTextField             = new JTextField(20);
@@ -194,10 +196,12 @@ final class ClassSpecificationDialog extends JDialog
         accessPanel.add(tip(new JLabel(msg("dontCare")), "dontCareTip"), labelConstraints);
         accessPanel.add(Box.createGlue(),                                constraintsLastStretch);
 
-        publicRadioButtons    = addRadioButtonTriplet("Public",    accessPanel);
-        finalRadioButtons     = addRadioButtonTriplet("Final",     accessPanel);
-        interfaceRadioButtons = addRadioButtonTriplet("Interface", accessPanel);
-        abstractRadioButtons  = addRadioButtonTriplet("Abstract",  accessPanel);
+        publicRadioButtons     = addRadioButtonTriplet("Public",     accessPanel);
+        finalRadioButtons      = addRadioButtonTriplet("Final",      accessPanel);
+        abstractRadioButtons   = addRadioButtonTriplet("Abstract",   accessPanel);
+        enumRadioButtons       = addRadioButtonTriplet("Enum",       accessPanel);
+        annotationRadioButtons = addRadioButtonTriplet("Annotation", accessPanel);
+        interfaceRadioButtons  = addRadioButtonTriplet("Interface",  accessPanel);
 
         // Create the annotation type panel.
         final JPanel annotationTypePanel = new JPanel(layout);
@@ -386,10 +390,12 @@ final class ClassSpecificationDialog extends JDialog
         commentsTextArea.setText(comments == null ? "" : comments);
 
         // Set the access radio buttons.
-        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_PUBLIC,    publicRadioButtons);
-        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_FINAL,     finalRadioButtons);
-        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_INTERFACE, interfaceRadioButtons);
-        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT,  abstractRadioButtons);
+        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_PUBLIC,      publicRadioButtons);
+        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_FINAL,       finalRadioButtons);
+        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT,    abstractRadioButtons);
+        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM,        enumRadioButtons);
+        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
+        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_INTERFACE,   interfaceRadioButtons);
 
         // Set the class and annotation text fields.
         annotationTypeTextField       .setText(annotationType        == null ? ""  : ClassUtil.externalType(annotationType));
@@ -444,10 +450,12 @@ final class ClassSpecificationDialog extends JDialog
                                    extendsClassName.equals("")      ? null : ClassUtil.internalClassName(extendsClassName));
 
         // Also get the access radio button settings.
-        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_PUBLIC,    publicRadioButtons);
-        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_FINAL,     finalRadioButtons);
-        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_INTERFACE, interfaceRadioButtons);
-        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT,  abstractRadioButtons);
+        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_PUBLIC,      publicRadioButtons);
+        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_FINAL,       finalRadioButtons);
+        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT,    abstractRadioButtons);
+        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM,        enumRadioButtons);
+        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
+        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_INTERFACE,   interfaceRadioButtons);
 
         // Get the keep class member option lists.
         classSpecification.fieldSpecifications  = memberSpecificationsPanel.getMemberSpecifications(true);
diff --git a/src/proguard/gui/ClassSpecificationsPanel.java b/src/proguard/gui/ClassSpecificationsPanel.java
index 4f32976..03ee429 100644
--- a/src/proguard/gui/ClassSpecificationsPanel.java
+++ b/src/proguard/gui/ClassSpecificationsPanel.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ExtensionFileFilter.java b/src/proguard/gui/ExtensionFileFilter.java
index 88dfdd0..ef66a7a 100644
--- a/src/proguard/gui/ExtensionFileFilter.java
+++ b/src/proguard/gui/ExtensionFileFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/FilterDialog.java b/src/proguard/gui/FilterDialog.java
index f2d5c9b..1d82ad9 100644
--- a/src/proguard/gui/FilterDialog.java
+++ b/src/proguard/gui/FilterDialog.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/GUIResources.java b/src/proguard/gui/GUIResources.java
index ae52210..868de88 100644
--- a/src/proguard/gui/GUIResources.java
+++ b/src/proguard/gui/GUIResources.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/GUIResources.properties b/src/proguard/gui/GUIResources.properties
index 9fa29b1..28568eb 100644
--- a/src/proguard/gui/GUIResources.properties
+++ b/src/proguard/gui/GUIResources.properties
@@ -1,5 +1,5 @@
 # ProGuard -- shrinking, optimization, and obfuscation of Java class files.
-# Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+# Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
 
 #
 # Tab names.
@@ -25,7 +25,7 @@ preverification = Preverification
 #
 # Panel titles.
 #
-welcome                       = Welcome to ProGuard, version 4.2
+welcome                       = Welcome to ProGuard, version 4.3
 options                       = Options
 keepAdditional                = Keep additional classes and class members
 keepNamesAdditional           = Keep additional class names and class member names
@@ -64,7 +64,7 @@ proGuardInfo = \
   \n\n\
   Distributed under the GNU General Public License.\
   \n\
-  Copyright (c) 2002-2007.
+  Copyright (c) 2002-2008.
 
 processingInfo = \
   You can now start processing your code, \
@@ -88,12 +88,15 @@ printUsage                       = Print usage
 
 optimize                         = Optimize
 allowAccessModification          = Allow access modification
+mergeInterfacesAggressively      = Merge interfaces aggressively
 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
 flattenPackageHierarchy          = Flatten package hierarchy
@@ -108,7 +111,7 @@ preverify                        = Preverify
 microEdition                     = Micro Edition
 
 verbose                          = Verbose
-note                             = Note special or unusual input
+note                             = Note potential mistakes in the configuration
 warn                             = Warn about possibly erronous input
 ignoreWarnings                   = Ignore warnings about possibly erronous input
 skipNonPublicLibraryClasses      = Skip non-public library classes
@@ -139,6 +142,9 @@ 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>
 optimizationPassesTip = \
   The number of optimization passes to be performed.
 
@@ -150,6 +156,10 @@ 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>
diff --git a/src/proguard/gui/KeepSpecificationsPanel.java b/src/proguard/gui/KeepSpecificationsPanel.java
index 8bfd16b..3a3d4b8 100644
--- a/src/proguard/gui/KeepSpecificationsPanel.java
+++ b/src/proguard/gui/KeepSpecificationsPanel.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ListPanel.java b/src/proguard/gui/ListPanel.java
index 6b92358..e0ab998 100644
--- a/src/proguard/gui/ListPanel.java
+++ b/src/proguard/gui/ListPanel.java
@@ -1,8 +1,8 @@
-/* $Id: ListPanel.java,v 1.15 2007/08/18 10:34:56 eric Exp $
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
  *
- * ProGuard -- shrinking, optimization, and obfuscation of Java class files.
- *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/MANIFEST.MF b/src/proguard/gui/MANIFEST.MF
new file mode 100644
index 0000000..05403b4
--- /dev/null
+++ b/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/src/proguard/gui/MemberSpecificationDialog.java b/src/proguard/gui/MemberSpecificationDialog.java
index 31b6b4e..22f5b88 100644
--- a/src/proguard/gui/MemberSpecificationDialog.java
+++ b/src/proguard/gui/MemberSpecificationDialog.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/MemberSpecificationsPanel.java b/src/proguard/gui/MemberSpecificationsPanel.java
index 73981ba..9fe5b9f 100644
--- a/src/proguard/gui/MemberSpecificationsPanel.java
+++ b/src/proguard/gui/MemberSpecificationsPanel.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/MessageDialogRunnable.java b/src/proguard/gui/MessageDialogRunnable.java
index 588c748..00a02b3 100644
--- a/src/proguard/gui/MessageDialogRunnable.java
+++ b/src/proguard/gui/MessageDialogRunnable.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ProGuardGUI.java b/src/proguard/gui/ProGuardGUI.java
index 6d3705a..da9e74f 100644
--- a/src/proguard/gui/ProGuardGUI.java
+++ b/src/proguard/gui/ProGuardGUI.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -87,24 +87,27 @@ public class ProGuardGUI extends JFrame
     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 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 overloadAggressivelyCheckBox      = new JCheckBox(msg("overloadAggressively"));
-    private final JCheckBox useUniqueClassMemberNamesCheckBox = new JCheckBox(msg("useUniqueClassMemberNames"));
-    private final JCheckBox useMixedCaseClassNamesCheckBox    = new JCheckBox(msg("useMixedCaseClassNames"));
-    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 newSourceFileAttributeCheckBox    = new JCheckBox(msg("renameSourceFileAttribute"));
-    private final JCheckBox adaptResourceFileNamesCheckBox    = new JCheckBox(msg("adaptResourceFileNames"));
-    private final JCheckBox adaptResourceFileContentsCheckBox = new JCheckBox(msg("adaptResourceFileContents"));
+    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    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 flattenPackageHierarchyCheckBox      = new JCheckBox(msg("flattenPackageHierarchy"));
+    private final JCheckBox repackageClassesCheckBox             = new JCheckBox(msg("repackageClasses"));
+    private final JCheckBox keepAttributesCheckBox               = new JCheckBox(msg("keepAttributes"));
+    private final JCheckBox newSourceFileAttributeCheckBox       = new JCheckBox(msg("renameSourceFileAttribute"));
+    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"));
@@ -123,19 +126,21 @@ public class ProGuardGUI extends JFrame
     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 printMappingTextField              = new JTextField(40);
-    private final JTextField applyMappingTextField              = new JTextField(40);
-    private final JTextField obfuscationDictionaryTextField     = 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 adaptResourceFileNamesTextField    = new JTextField(40);
-    private final JTextField adaptResourceFileContentsTextField = 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 JTextField printUsageTextField                   = 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 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 adaptResourceFileNamesTextField       = new JTextField(40);
+    private final JTextField adaptResourceFileContentsTextField    = 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);
 
@@ -344,41 +349,51 @@ public class ProGuardGUI extends JFrame
         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 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(overloadAggressivelyCheckBox,       "overloadAggressivelyTip"),         constraintsLastStretch);
-        obfuscationOptionsPanel.add(tip(useUniqueClassMemberNamesCheckBox,  "useUniqueClassMemberNamesTip"),    constraintsLastStretch);
-        obfuscationOptionsPanel.add(tip(useMixedCaseClassNamesCheckBox,     "useMixedCaseClassNamesTip"),       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(newSourceFileAttributeCheckBox,     "renameSourceFileAttributeTip"),    constraints);
-        obfuscationOptionsPanel.add(tip(newSourceFileAttributeTextField,    "sourceFileAttributeTip"),          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);
+        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(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(newSourceFileAttributeCheckBox,          "renameSourceFileAttributeTip"),    constraints);
+        obfuscationOptionsPanel.add(tip(newSourceFileAttributeTextField,         "sourceFileAttributeTip"),          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);
 
@@ -397,10 +412,11 @@ public class ProGuardGUI extends JFrame
         JPanel optimizationOptionsPanel = new JPanel(layout);
         addBorder(optimizationOptionsPanel, "options");
 
-        optimizationOptionsPanel.add(tip(optimizeCheckBox,                "optimizeTip"),                constraintsLastStretch);
-        optimizationOptionsPanel.add(tip(allowAccessModificationCheckBox, "allowAccessModificationTip"), constraintsLastStretch);
-        optimizationOptionsPanel.add(tip(optimizationPassesLabel,         "optimizationPassesTip"),      constraints);
-        optimizationOptionsPanel.add(tip(optimizationPassesSpinner,       "optimizationPassesTip"),      constraintsLast);
+        optimizationOptionsPanel.add(tip(optimizeCheckBox,                    "optimizeTip"),                    constraintsLastStretch);
+        optimizationOptionsPanel.add(tip(allowAccessModificationCheckBox,     "allowAccessModificationTip"),     constraintsLastStretch);
+        optimizationOptionsPanel.add(tip(mergeInterfacesAggressivelyCheckBox, "mergeInterfacesAggressivelyTip"), constraintsLastStretch);
+        optimizationOptionsPanel.add(tip(optimizationPassesLabel,             "optimizationPassesTip"),          constraints);
+        optimizationOptionsPanel.add(tip(optimizationPassesSpinner,           "optimizationPassesTip"),          constraintsLast);
 
         JPanel optimizationPanel = new JPanel(layout);
 
@@ -934,20 +950,23 @@ public class ProGuardGUI extends JFrame
         optimizeCheckBox                        .setSelected(configuration.optimize);
         optimizationPassesSpinner.getModel()    .setValue(new Integer(configuration.optimizationPasses));
         allowAccessModificationCheckBox         .setSelected(configuration.allowAccessModification);
+        mergeInterfacesAggressivelyCheckBox     .setSelected(configuration.mergeInterfacesAggressively);
 
         obfuscateCheckBox                       .setSelected(configuration.obfuscate);
-        printMappingCheckBox                    .setSelected(configuration.printMapping              != null);
-        applyMappingCheckBox                    .setSelected(configuration.applyMapping              != null);
-        obfuscationDictionaryCheckBox           .setSelected(configuration.obfuscationDictionary     != null);
+        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);
-        flattenPackageHierarchyCheckBox         .setSelected(configuration.flattenPackageHierarchy   != null);
-        repackageClassesCheckBox                .setSelected(configuration.repackageClasses          != null);
-        keepAttributesCheckBox                  .setSelected(configuration.keepAttributes            != null);
-        newSourceFileAttributeCheckBox          .setSelected(configuration.newSourceFileAttribute    != null);
-        adaptResourceFileNamesCheckBox          .setSelected(configuration.adaptResourceFileNames    != null);
-        adaptResourceFileContentsCheckBox       .setSelected(configuration.adaptResourceFileContents != null);
+        flattenPackageHierarchyCheckBox         .setSelected(configuration.flattenPackageHierarchy      != null);
+        repackageClassesCheckBox                .setSelected(configuration.repackageClasses             != null);
+        keepAttributesCheckBox                  .setSelected(configuration.keepAttributes               != null);
+        newSourceFileAttributeCheckBox          .setSelected(configuration.newSourceFileAttribute       != null);
+        adaptResourceFileNamesCheckBox          .setSelected(configuration.adaptResourceFileNames       != null);
+        adaptResourceFileContentsCheckBox       .setSelected(configuration.adaptResourceFileContents    != null);
 
         preverifyCheckBox                       .setSelected(configuration.preverify);
         microEditionCheckBox                    .setSelected(configuration.microEdition);
@@ -1084,11 +1103,14 @@ public class ProGuardGUI extends JFrame
         configuration.optimize                         = optimizeCheckBox                        .isSelected();
         configuration.optimizationPasses               = ((SpinnerNumberModel)optimizationPassesSpinner.getModel()).getNumber().intValue();
         configuration.allowAccessModification          = allowAccessModificationCheckBox         .isSelected();
+        configuration.mergeInterfacesAggressively      = mergeInterfacesAggressivelyCheckBox     .isSelected();
 
         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();
diff --git a/src/proguard/gui/ProGuardRunnable.java b/src/proguard/gui/ProGuardRunnable.java
index 3cff177..56ccb36 100644
--- a/src/proguard/gui/ProGuardRunnable.java
+++ b/src/proguard/gui/ProGuardRunnable.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/ReTraceRunnable.java b/src/proguard/gui/ReTraceRunnable.java
index 23df458..e9355a6 100644
--- a/src/proguard/gui/ReTraceRunnable.java
+++ b/src/proguard/gui/ReTraceRunnable.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/SwingUtil.java b/src/proguard/gui/SwingUtil.java
index c03065e..bceccfe 100644
--- a/src/proguard/gui/SwingUtil.java
+++ b/src/proguard/gui/SwingUtil.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/TabbedPane.java b/src/proguard/gui/TabbedPane.java
index a48627f..35dad8f 100644
--- a/src/proguard/gui/TabbedPane.java
+++ b/src/proguard/gui/TabbedPane.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/TextAreaOutputStream.java b/src/proguard/gui/TextAreaOutputStream.java
index a0c8abe..d46b3b1 100644
--- a/src/proguard/gui/TextAreaOutputStream.java
+++ b/src/proguard/gui/TextAreaOutputStream.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/boilerplate.pro b/src/proguard/gui/boilerplate.pro
index cd6b975..70efb82 100644
--- a/src/proguard/gui/boilerplate.pro
+++ b/src/proguard/gui/boilerplate.pro
@@ -24,7 +24,7 @@
 
 # Also keep - Enumerations. Keep the special static methods that are required in
 # enumeration classes.
--keepclassmembers class * extends java.lang.Enum {
+-keepclassmembers enum * {
     public static **[] values();
     public static ** valueOf(java.lang.String);
 }
@@ -49,7 +49,7 @@
     void set*(***);
     void set*(int,***);
 
-    boolean is*(); 
+    boolean is*();
     boolean is*(int);
 
     *** get*();
diff --git a/src/proguard/gui/default.pro b/src/proguard/gui/default.pro
index f9df53f..3bfe2d6 100644
--- a/src/proguard/gui/default.pro
+++ b/src/proguard/gui/default.pro
@@ -10,7 +10,7 @@
 
 # Also keep - Enumerations. Keep the special static methods that are required in
 # enumeration classes.
--keepclassmembers class * extends java.lang.Enum {
+-keepclassmembers enum * {
     public static **[] values();
     public static ** valueOf(java.lang.String);
 }
diff --git a/src/proguard/gui/splash/BufferedSprite.java b/src/proguard/gui/splash/BufferedSprite.java
index 9cd9976..dfa52ec 100644
--- a/src/proguard/gui/splash/BufferedSprite.java
+++ b/src/proguard/gui/splash/BufferedSprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/CircleSprite.java b/src/proguard/gui/splash/CircleSprite.java
index 7747202..26f6782 100644
--- a/src/proguard/gui/splash/CircleSprite.java
+++ b/src/proguard/gui/splash/CircleSprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ClipSprite.java b/src/proguard/gui/splash/ClipSprite.java
index d7bc269..70cd627 100644
--- a/src/proguard/gui/splash/ClipSprite.java
+++ b/src/proguard/gui/splash/ClipSprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ColorSprite.java b/src/proguard/gui/splash/ColorSprite.java
index 739b8c4..c3b2372 100644
--- a/src/proguard/gui/splash/ColorSprite.java
+++ b/src/proguard/gui/splash/ColorSprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/CompositeSprite.java b/src/proguard/gui/splash/CompositeSprite.java
index a3d4d04..b8b524a 100644
--- a/src/proguard/gui/splash/CompositeSprite.java
+++ b/src/proguard/gui/splash/CompositeSprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantColor.java b/src/proguard/gui/splash/ConstantColor.java
index 6e25cbf..e520fac 100644
--- a/src/proguard/gui/splash/ConstantColor.java
+++ b/src/proguard/gui/splash/ConstantColor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantDouble.java b/src/proguard/gui/splash/ConstantDouble.java
index d66eb97..1ae8386 100644
--- a/src/proguard/gui/splash/ConstantDouble.java
+++ b/src/proguard/gui/splash/ConstantDouble.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantFont.java b/src/proguard/gui/splash/ConstantFont.java
index e96a17a..4a01c6e 100644
--- a/src/proguard/gui/splash/ConstantFont.java
+++ b/src/proguard/gui/splash/ConstantFont.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantInt.java b/src/proguard/gui/splash/ConstantInt.java
index 913765c..da39e66 100644
--- a/src/proguard/gui/splash/ConstantInt.java
+++ b/src/proguard/gui/splash/ConstantInt.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantString.java b/src/proguard/gui/splash/ConstantString.java
index 50e50ac..6ab1548 100644
--- a/src/proguard/gui/splash/ConstantString.java
+++ b/src/proguard/gui/splash/ConstantString.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ConstantTiming.java b/src/proguard/gui/splash/ConstantTiming.java
index 25af3d9..19ba182 100644
--- a/src/proguard/gui/splash/ConstantTiming.java
+++ b/src/proguard/gui/splash/ConstantTiming.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/FontSprite.java b/src/proguard/gui/splash/FontSprite.java
index 0c9f82b..11c77cb 100644
--- a/src/proguard/gui/splash/FontSprite.java
+++ b/src/proguard/gui/splash/FontSprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ImageSprite.java b/src/proguard/gui/splash/ImageSprite.java
index 183460e..afdea51 100644
--- a/src/proguard/gui/splash/ImageSprite.java
+++ b/src/proguard/gui/splash/ImageSprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearColor.java b/src/proguard/gui/splash/LinearColor.java
index 35857f2..83c22fd 100644
--- a/src/proguard/gui/splash/LinearColor.java
+++ b/src/proguard/gui/splash/LinearColor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearDouble.java b/src/proguard/gui/splash/LinearDouble.java
index ac64d05..cb3b7f9 100644
--- a/src/proguard/gui/splash/LinearDouble.java
+++ b/src/proguard/gui/splash/LinearDouble.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearInt.java b/src/proguard/gui/splash/LinearInt.java
index 96d8c65..80d5b2b 100644
--- a/src/proguard/gui/splash/LinearInt.java
+++ b/src/proguard/gui/splash/LinearInt.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/LinearTiming.java b/src/proguard/gui/splash/LinearTiming.java
index c85e7f8..dfd9171 100644
--- a/src/proguard/gui/splash/LinearTiming.java
+++ b/src/proguard/gui/splash/LinearTiming.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/OverrideGraphics2D.java b/src/proguard/gui/splash/OverrideGraphics2D.java
index 5a14087..45277b6 100644
--- a/src/proguard/gui/splash/OverrideGraphics2D.java
+++ b/src/proguard/gui/splash/OverrideGraphics2D.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/RectangleSprite.java b/src/proguard/gui/splash/RectangleSprite.java
index cb09550..5f81330 100644
--- a/src/proguard/gui/splash/RectangleSprite.java
+++ b/src/proguard/gui/splash/RectangleSprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SawToothTiming.java b/src/proguard/gui/splash/SawToothTiming.java
index 6c05c44..e470d50 100644
--- a/src/proguard/gui/splash/SawToothTiming.java
+++ b/src/proguard/gui/splash/SawToothTiming.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/ShadowedSprite.java b/src/proguard/gui/splash/ShadowedSprite.java
index 53630fd..a273e46 100644
--- a/src/proguard/gui/splash/ShadowedSprite.java
+++ b/src/proguard/gui/splash/ShadowedSprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SineTiming.java b/src/proguard/gui/splash/SineTiming.java
index 5b69b81..90ea8b8 100644
--- a/src/proguard/gui/splash/SineTiming.java
+++ b/src/proguard/gui/splash/SineTiming.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SmoothTiming.java b/src/proguard/gui/splash/SmoothTiming.java
index 2a19c06..69f9aba 100644
--- a/src/proguard/gui/splash/SmoothTiming.java
+++ b/src/proguard/gui/splash/SmoothTiming.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/SplashPanel.java b/src/proguard/gui/splash/SplashPanel.java
index 871fe9c..2d49646 100644
--- a/src/proguard/gui/splash/SplashPanel.java
+++ b/src/proguard/gui/splash/SplashPanel.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/Sprite.java b/src/proguard/gui/splash/Sprite.java
index 9e5e842..990c53a 100644
--- a/src/proguard/gui/splash/Sprite.java
+++ b/src/proguard/gui/splash/Sprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/TextSprite.java b/src/proguard/gui/splash/TextSprite.java
index 2450e62..d287914 100644
--- a/src/proguard/gui/splash/TextSprite.java
+++ b/src/proguard/gui/splash/TextSprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/TimeSwitchSprite.java b/src/proguard/gui/splash/TimeSwitchSprite.java
index 3199f14..49c3b27 100644
--- a/src/proguard/gui/splash/TimeSwitchSprite.java
+++ b/src/proguard/gui/splash/TimeSwitchSprite.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/Timing.java b/src/proguard/gui/splash/Timing.java
index d954deb..84b09e9 100644
--- a/src/proguard/gui/splash/Timing.java
+++ b/src/proguard/gui/splash/Timing.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/TypeWriterString.java b/src/proguard/gui/splash/TypeWriterString.java
index d4e3641..d576e28 100644
--- a/src/proguard/gui/splash/TypeWriterString.java
+++ b/src/proguard/gui/splash/TypeWriterString.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableColor.java b/src/proguard/gui/splash/VariableColor.java
index 5c60bb6..908e057 100644
--- a/src/proguard/gui/splash/VariableColor.java
+++ b/src/proguard/gui/splash/VariableColor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableDouble.java b/src/proguard/gui/splash/VariableDouble.java
index 86d7db0..b72362b 100644
--- a/src/proguard/gui/splash/VariableDouble.java
+++ b/src/proguard/gui/splash/VariableDouble.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableFont.java b/src/proguard/gui/splash/VariableFont.java
index 3e6ecdd..1676b63 100644
--- a/src/proguard/gui/splash/VariableFont.java
+++ b/src/proguard/gui/splash/VariableFont.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableInt.java b/src/proguard/gui/splash/VariableInt.java
index bbdfa76..a58d138 100644
--- a/src/proguard/gui/splash/VariableInt.java
+++ b/src/proguard/gui/splash/VariableInt.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableSizeFont.java b/src/proguard/gui/splash/VariableSizeFont.java
index 945ac7d..949eeb0 100644
--- a/src/proguard/gui/splash/VariableSizeFont.java
+++ b/src/proguard/gui/splash/VariableSizeFont.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/gui/splash/VariableString.java b/src/proguard/gui/splash/VariableString.java
index f95ce6f..e98b93e 100644
--- a/src/proguard/gui/splash/VariableString.java
+++ b/src/proguard/gui/splash/VariableString.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/CascadingDataEntryWriter.java b/src/proguard/io/CascadingDataEntryWriter.java
index cd78336..6347bf0 100644
--- a/src/proguard/io/CascadingDataEntryWriter.java
+++ b/src/proguard/io/CascadingDataEntryWriter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ClassFilter.java b/src/proguard/io/ClassFilter.java
index 2e255a4..01fbaf3 100644
--- a/src/proguard/io/ClassFilter.java
+++ b/src/proguard/io/ClassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ClassReader.java b/src/proguard/io/ClassReader.java
index 01b38dd..d6c28d3 100644
--- a/src/proguard/io/ClassReader.java
+++ b/src/proguard/io/ClassReader.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ClassRewriter.java b/src/proguard/io/ClassRewriter.java
index 5e3ce0a..98cafdd 100644
--- a/src/proguard/io/ClassRewriter.java
+++ b/src/proguard/io/ClassRewriter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntry.java b/src/proguard/io/DataEntry.java
index e6bb0dd..d5d9018 100644
--- a/src/proguard/io/DataEntry.java
+++ b/src/proguard/io/DataEntry.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryCopier.java b/src/proguard/io/DataEntryCopier.java
index 7b249f6..2f6e37e 100644
--- a/src/proguard/io/DataEntryCopier.java
+++ b/src/proguard/io/DataEntryCopier.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryFilter.java b/src/proguard/io/DataEntryFilter.java
index 1e179a6..e84c4c6 100644
--- a/src/proguard/io/DataEntryFilter.java
+++ b/src/proguard/io/DataEntryFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryNameFilter.java b/src/proguard/io/DataEntryNameFilter.java
index 8263bcc..21947e1 100644
--- a/src/proguard/io/DataEntryNameFilter.java
+++ b/src/proguard/io/DataEntryNameFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryParentFilter.java b/src/proguard/io/DataEntryParentFilter.java
index 52cef2d..838ea54 100644
--- a/src/proguard/io/DataEntryParentFilter.java
+++ b/src/proguard/io/DataEntryParentFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryPump.java b/src/proguard/io/DataEntryPump.java
index 4da2eb7..d897685 100644
--- a/src/proguard/io/DataEntryPump.java
+++ b/src/proguard/io/DataEntryPump.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryReader.java b/src/proguard/io/DataEntryReader.java
index 0e70129..4759310 100644
--- a/src/proguard/io/DataEntryReader.java
+++ b/src/proguard/io/DataEntryReader.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryRenamer.java b/src/proguard/io/DataEntryRenamer.java
index 43bb246..34f5a21 100644
--- a/src/proguard/io/DataEntryRenamer.java
+++ b/src/proguard/io/DataEntryRenamer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -67,7 +67,7 @@ public class DataEntryRenamer implements DataEntryReader
              suffixIndex--)
         {
             char c = dataEntryName.charAt(suffixIndex);
-            if (!Character.isJavaIdentifierPart(c))
+            if (!Character.isLetterOrDigit(c))
             {
                 // Stop looking at the first package separator.
                 if (c == ClassConstants.INTERNAL_PACKAGE_SEPARATOR)
diff --git a/src/proguard/io/DataEntryRewriter.java b/src/proguard/io/DataEntryRewriter.java
index c138524..7c28381 100644
--- a/src/proguard/io/DataEntryRewriter.java
+++ b/src/proguard/io/DataEntryRewriter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DataEntryWriter.java b/src/proguard/io/DataEntryWriter.java
index 477a434..b30bb62 100644
--- a/src/proguard/io/DataEntryWriter.java
+++ b/src/proguard/io/DataEntryWriter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DirectoryPump.java b/src/proguard/io/DirectoryPump.java
index 881cb6e..04eee76 100644
--- a/src/proguard/io/DirectoryPump.java
+++ b/src/proguard/io/DirectoryPump.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/DirectoryWriter.java b/src/proguard/io/DirectoryWriter.java
index 0513fc0..172966d 100644
--- a/src/proguard/io/DirectoryWriter.java
+++ b/src/proguard/io/DirectoryWriter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/FileDataEntry.java b/src/proguard/io/FileDataEntry.java
index 2a7246b..0c484ca 100644
--- a/src/proguard/io/FileDataEntry.java
+++ b/src/proguard/io/FileDataEntry.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/FilteredDataEntryReader.java b/src/proguard/io/FilteredDataEntryReader.java
index d740dc2..40e733d 100644
--- a/src/proguard/io/FilteredDataEntryReader.java
+++ b/src/proguard/io/FilteredDataEntryReader.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/FilteredDataEntryWriter.java b/src/proguard/io/FilteredDataEntryWriter.java
index af6d3bf..6c50bea 100644
--- a/src/proguard/io/FilteredDataEntryWriter.java
+++ b/src/proguard/io/FilteredDataEntryWriter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/Finisher.java b/src/proguard/io/Finisher.java
index c1ec5ad..792e032 100644
--- a/src/proguard/io/Finisher.java
+++ b/src/proguard/io/Finisher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/JarReader.java b/src/proguard/io/JarReader.java
index c9bcf4e..7e366f9 100644
--- a/src/proguard/io/JarReader.java
+++ b/src/proguard/io/JarReader.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/JarWriter.java b/src/proguard/io/JarWriter.java
index 2612133..cb0f0a8 100644
--- a/src/proguard/io/JarWriter.java
+++ b/src/proguard/io/JarWriter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ParentDataEntryWriter.java b/src/proguard/io/ParentDataEntryWriter.java
index f9fc681..5def90c 100644
--- a/src/proguard/io/ParentDataEntryWriter.java
+++ b/src/proguard/io/ParentDataEntryWriter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/RenamedDataEntry.java b/src/proguard/io/RenamedDataEntry.java
index 1d31b8d..410523d 100644
--- a/src/proguard/io/RenamedDataEntry.java
+++ b/src/proguard/io/RenamedDataEntry.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/io/ZipDataEntry.java b/src/proguard/io/ZipDataEntry.java
index 0c722e1..a760709 100644
--- a/src/proguard/io/ZipDataEntry.java
+++ b/src/proguard/io/ZipDataEntry.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/AttributeShrinker.java b/src/proguard/obfuscate/AttributeShrinker.java
index 12ab5e9..e5a99e6 100644
--- a/src/proguard/obfuscate/AttributeShrinker.java
+++ b/src/proguard/obfuscate/AttributeShrinker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/AttributeUsageMarker.java b/src/proguard/obfuscate/AttributeUsageMarker.java
index 85206c0..d195386 100644
--- a/src/proguard/obfuscate/AttributeUsageMarker.java
+++ b/src/proguard/obfuscate/AttributeUsageMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/ClassObfuscator.java b/src/proguard/obfuscate/ClassObfuscator.java
index 320ba85..9e6ec83 100644
--- a/src/proguard/obfuscate/ClassObfuscator.java
+++ b/src/proguard/obfuscate/ClassObfuscator.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -46,10 +46,12 @@ implements   ClassVisitor,
              InnerClassesInfoVisitor,
              ConstantVisitor
 {
-    private final boolean useMixedCaseClassNames;
-    private final String  flattenPackageHierarchy;
-    private final String  repackageClasses;
-    private final boolean allowAccessModification;
+    private final DictionaryNameFactory classNameFactory;
+    private final DictionaryNameFactory packageNameFactory;
+    private final boolean               useMixedCaseClassNames;
+    private final String                flattenPackageHierarchy;
+    private final String                repackageClasses;
+    private final boolean               allowAccessModification;
 
     private final Set classNamesToAvoid                  = new HashSet();
 
@@ -71,21 +73,29 @@ implements   ClassVisitor,
      * Creates a new ClassObfuscator.
      * @param programClassPool        the class pool in which class names
      *                                have to be unique.
-     * @param useMixedCaseClassNames  specifies whether obfuscated packages
-     *                                and classes can get mixed-case names.
-     * @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.
+     * @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 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,
-                           boolean   useMixedCaseClassNames,
-                           String    flattenPackageHierarchy,
-                           String    repackageClasses,
-                           boolean   allowAccessModification)
+    public ClassObfuscator(ClassPool             programClassPool,
+                           DictionaryNameFactory classNameFactory,
+                           DictionaryNameFactory packageNameFactory,
+                           boolean               useMixedCaseClassNames,
+                           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)
@@ -301,6 +311,13 @@ implements   ClassVisitor,
             // 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);
         }
@@ -333,6 +350,13 @@ implements   ClassVisitor,
             // 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);
         }
diff --git a/src/proguard/obfuscate/ClassOpener.java b/src/proguard/obfuscate/ClassOpener.java
deleted file mode 100644
index 57abe96..0000000
--- a/src/proguard/obfuscate/ClassOpener.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- *             of Java bytecode.
- *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * 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.*;
-import proguard.classfile.constant.visitor.ConstantVisitor;
-import proguard.classfile.util.*;
-
-/**
- * This <code>ConstantVisitor</code> makes package visible classes and class
- * members public, if they are referenced by visited references from different
- * packages.
- *
- * @author Eric Lafortune
- */
-public class ClassOpener
-extends      SimplifiedVisitor
-implements   ConstantVisitor
-{
-    // Implementations for ConstantVisitor.
-
-    public void visitAnyConstant(Clazz clazz, Constant constant) {}
-
-
-    public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
-    {
-        fixPackageVisibility(clazz,
-                             stringConstant.referencedClass,
-                             stringConstant.referencedMember);
-    }
-
-
-    public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
-    {
-        fixPackageVisibility(clazz,
-                             refConstant.referencedClass,
-                             refConstant.referencedMember);
-    }
-
-
-    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
-    {
-        // Do we know the referenced class?
-        Clazz referencedClass = classConstant.referencedClass;
-        if (referencedClass != null)
-        {
-            int accessFlags = referencedClass.getAccessFlags();
-
-            // Make it public if necessary.
-            if (isNotPublic(accessFlags)                 &&
-                referencedClass instanceof ProgramClass  &&
-                inDifferentPackages(clazz, referencedClass))
-            {
-                ((ProgramClass)referencedClass).u2accessFlags =
-                    AccessUtil.replaceAccessFlags(accessFlags,
-                                                  ClassConstants.INTERNAL_ACC_PUBLIC);
-            }
-        }
-    }
-
-
-    // Small utility methods.
-
-    /**
-     * Fixes the package visibility of the given referenced class member,
-     * if necessary.
-     */
-    private void fixPackageVisibility(Clazz clazz, Clazz referencedClass, Member referencedMember)
-    {
-        // Do we know the referenced class member?
-        if (referencedMember != null)
-        {
-            int accessFlags = referencedMember.getAccessFlags();
-
-            // Make it public if necessary.
-            if (isNotPublic(accessFlags)                  &&
-                referencedMember instanceof ProgramMember &&
-                inDifferentPackages(clazz, referencedClass))
-            {
-                ((ProgramMember)referencedMember).u2accessFlags =
-                    AccessUtil.replaceAccessFlags(accessFlags,
-                                                  clazz.extends_(referencedClass) ?
-                                                  ClassConstants.INTERNAL_ACC_PROTECTED :
-                                                  ClassConstants.INTERNAL_ACC_PUBLIC);
-            }
-        }
-    }
-
-
-    /**
-     * Returns whether the given classes are in different packages..
-     */
-    private boolean inDifferentPackages(Clazz class1, Clazz class2)
-    {
-        return !ClassUtil.internalPackageName(class1.getName()).equals(
-                ClassUtil.internalPackageName(class2.getName()));
-    }
-
-
-    /**
-     * Returns whether the given access flags specify a non-public class
-     * or class member.
-     */
-    private boolean isNotPublic(int accessFlags)
-    {
-        return (accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) == 0;
-    }
-}
diff --git a/src/proguard/obfuscate/ClassRenamer.java b/src/proguard/obfuscate/ClassRenamer.java
index b78bead..bde6982 100644
--- a/src/proguard/obfuscate/ClassRenamer.java
+++ b/src/proguard/obfuscate/ClassRenamer.java
@@ -2,20 +2,20 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  * more details.
  *
  * You should have received a copy of the GNU General Public License along
- * with this library; if not, write to the Free Software Foundation, Inc.,
+ * 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;
@@ -33,6 +33,7 @@ import proguard.classfile.visitor.*;
  * obfuscator.
  *
  * @see ClassObfuscator
+ * @see MemberObfuscator
  *
  * @author Eric Lafortune
  */
@@ -42,15 +43,12 @@ implements   ClassVisitor,
              MemberVisitor,
              ConstantVisitor
 {
-    private final ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor();
-
-
     // Implementations for ClassVisitor.
 
     public void visitProgramClass(ProgramClass programClass)
     {
         // Rename this class.
-        programClass.constantPoolEntryAccept(programClass.u2thisClass, this);
+        programClass.thisClassConstantAccept(this);
 
         // Rename the class members.
         programClass.fieldsAccept(this);
@@ -80,12 +78,12 @@ implements   ClassVisitor,
             !newName.equals(name))
         {
             programMember.u2nameIndex =
-                constantPoolEditor.addUtf8Constant(programClass, newName);
+                new ConstantPoolEditor(programClass).addUtf8Constant(newName);
         }
     }
 
     public void visitLibraryMember(LibraryClass  libraryClass,
-                                     LibraryMember libraryMember)
+                                   LibraryMember libraryMember)
     {
         String newName = MemberObfuscator.newMemberName(libraryMember);
         if (newName != null)
@@ -105,8 +103,7 @@ implements   ClassVisitor,
         {
             // Refer to a new Utf8 entry.
             classConstant.u2nameIndex =
-                constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                                   newName);
+                new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newName);
         }
     }
 }
diff --git a/src/proguard/obfuscate/DictionaryNameFactory.java b/src/proguard/obfuscate/DictionaryNameFactory.java
index 408e541..b0ca387 100644
--- a/src/proguard/obfuscate/DictionaryNameFactory.java
+++ b/src/proguard/obfuscate/DictionaryNameFactory.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -35,8 +35,8 @@ public class DictionaryNameFactory implements NameFactory
     private static final char COMMENT_CHARACTER = '#';
 
 
+    private final List        names;
     private final NameFactory nameFactory;
-    private final List        names = new ArrayList();
 
     private int index = 0;
 
@@ -50,6 +50,7 @@ public class DictionaryNameFactory implements NameFactory
     public DictionaryNameFactory(File        file,
                                  NameFactory nameFactory) throws IOException
     {
+        this.names       = new ArrayList();
         this.nameFactory = nameFactory;
 
         Reader reader = new FileReader(file);
@@ -118,6 +119,22 @@ public class DictionaryNameFactory implements NameFactory
     }
 
 
+    /**
+     * 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()
diff --git a/src/proguard/obfuscate/MapCleaner.java b/src/proguard/obfuscate/MapCleaner.java
index ae81a28..f1fd597 100644
--- a/src/proguard/obfuscate/MapCleaner.java
+++ b/src/proguard/obfuscate/MapCleaner.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MappingKeeper.java b/src/proguard/obfuscate/MappingKeeper.java
index 61e1144..2213b91 100644
--- a/src/proguard/obfuscate/MappingKeeper.java
+++ b/src/proguard/obfuscate/MappingKeeper.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MappingPrinter.java b/src/proguard/obfuscate/MappingPrinter.java
index ae1cd9a..0327687 100644
--- a/src/proguard/obfuscate/MappingPrinter.java
+++ b/src/proguard/obfuscate/MappingPrinter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MappingProcessor.java b/src/proguard/obfuscate/MappingProcessor.java
index aa99e44..972d190 100644
--- a/src/proguard/obfuscate/MappingProcessor.java
+++ b/src/proguard/obfuscate/MappingProcessor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MappingReader.java b/src/proguard/obfuscate/MappingReader.java
index d987919..1bbace3 100644
--- a/src/proguard/obfuscate/MappingReader.java
+++ b/src/proguard/obfuscate/MappingReader.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberNameCleaner.java b/src/proguard/obfuscate/MemberNameCleaner.java
index 43cc241..646d1e5 100644
--- a/src/proguard/obfuscate/MemberNameCleaner.java
+++ b/src/proguard/obfuscate/MemberNameCleaner.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberNameCollector.java b/src/proguard/obfuscate/MemberNameCollector.java
index 9d23879..a168647 100644
--- a/src/proguard/obfuscate/MemberNameCollector.java
+++ b/src/proguard/obfuscate/MemberNameCollector.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberNameConflictFixer.java b/src/proguard/obfuscate/MemberNameConflictFixer.java
index 7921486..d3bb02c 100644
--- a/src/proguard/obfuscate/MemberNameConflictFixer.java
+++ b/src/proguard/obfuscate/MemberNameConflictFixer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberObfuscator.java b/src/proguard/obfuscate/MemberObfuscator.java
index 113480c..bdd11f7 100644
--- a/src/proguard/obfuscate/MemberObfuscator.java
+++ b/src/proguard/obfuscate/MemberObfuscator.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MemberSpecialNameFilter.java b/src/proguard/obfuscate/MemberSpecialNameFilter.java
index 8a11bca..4f252d4 100644
--- a/src/proguard/obfuscate/MemberSpecialNameFilter.java
+++ b/src/proguard/obfuscate/MemberSpecialNameFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/MultiMappingProcessor.java b/src/proguard/obfuscate/MultiMappingProcessor.java
index bccf587..777e3f8 100644
--- a/src/proguard/obfuscate/MultiMappingProcessor.java
+++ b/src/proguard/obfuscate/MultiMappingProcessor.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameAndTypeShrinker.java b/src/proguard/obfuscate/NameAndTypeShrinker.java
index c2672a9..812768b 100644
--- a/src/proguard/obfuscate/NameAndTypeShrinker.java
+++ b/src/proguard/obfuscate/NameAndTypeShrinker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameAndTypeUsageMarker.java b/src/proguard/obfuscate/NameAndTypeUsageMarker.java
index 37b261b..a179781 100644
--- a/src/proguard/obfuscate/NameAndTypeUsageMarker.java
+++ b/src/proguard/obfuscate/NameAndTypeUsageMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameFactory.java b/src/proguard/obfuscate/NameFactory.java
index bfd43d0..095b64d 100644
--- a/src/proguard/obfuscate/NameFactory.java
+++ b/src/proguard/obfuscate/NameFactory.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameFactoryResetter.java b/src/proguard/obfuscate/NameFactoryResetter.java
index cda368c..ae51e7f 100644
--- a/src/proguard/obfuscate/NameFactoryResetter.java
+++ b/src/proguard/obfuscate/NameFactoryResetter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/NameMarker.java b/src/proguard/obfuscate/NameMarker.java
index e889df6..302893e 100644
--- a/src/proguard/obfuscate/NameMarker.java
+++ b/src/proguard/obfuscate/NameMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -21,6 +21,11 @@
 package proguard.obfuscate;
 
 import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
 import proguard.classfile.visitor.*;
 
 
@@ -35,14 +40,21 @@ import proguard.classfile.visitor.*;
  * @author Eric Lafortune
  */
 class      NameMarker
+extends    SimplifiedVisitor
 implements ClassVisitor,
-           MemberVisitor
+           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);
     }
 
 
@@ -78,6 +90,43 @@ implements ClassVisitor,
     }
 
 
+    // 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.
 
     /**
diff --git a/src/proguard/obfuscate/Obfuscator.java b/src/proguard/obfuscate/Obfuscator.java
index 6faaca6..04a80b5 100644
--- a/src/proguard/obfuscate/Obfuscator.java
+++ b/src/proguard/obfuscate/Obfuscator.java
@@ -2,14 +2,13 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- *
  * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
@@ -71,6 +70,25 @@ public class Obfuscator
         programClassPool.classesAccept(new ClassCleaner());
         libraryClassPool.classesAccept(new ClassCleaner());
 
+        // Mark attributes that have to be kept.
+        AttributeUsageMarker requiredAttributeUsageMarker =
+            new AttributeUsageMarker();
+
+        AttributeVisitor optionalAttributeUsageMarker =
+            configuration.keepAttributes == null     ? null :
+            configuration.keepAttributes.size() == 0 ?
+                (AttributeVisitor)requiredAttributeUsageMarker :
+                (AttributeVisitor)new AttributeNameFilter(new ListParser(new NameParser()).parse(configuration.keepAttributes),
+                                                          requiredAttributeUsageMarker);
+
+        programClassPool.classesAccept(
+            new AllAttributeVisitor(true,
+            new RequiredAttributeFilter(requiredAttributeUsageMarker,
+                                        optionalAttributeUsageMarker)));
+
+        // Remove the attributes that can be discarded.
+        programClassPool.classesAccept(new AttributeShrinker());
+
         // 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.
@@ -138,28 +156,19 @@ public class Obfuscator
             }
         }
 
-        // Mark attributes that have to be kept.
-        AttributeUsageMarker requiredAttributeUsageMarker =
-            new AttributeUsageMarker();
-
-        AttributeVisitor optionalAttributeUsageMarker =
-            configuration.keepAttributes == null     ? null :
-            configuration.keepAttributes.size() == 0 ?
-                (AttributeVisitor)requiredAttributeUsageMarker :
-                (AttributeVisitor)new AttributeNameFilter(new ListParser(new NameParser()).parse(configuration.keepAttributes),
-                                                          requiredAttributeUsageMarker);
-
-        programClassPool.classesAccept(
-            new AllAttributeVisitor(true,
-            new RequiredAttributeFilter(requiredAttributeUsageMarker,
-                                        optionalAttributeUsageMarker)));
+        // Come up with new names for all classes.
+        DictionaryNameFactory classNameFactory = configuration.classObfuscationDictionary != null ?
+            new DictionaryNameFactory(configuration.classObfuscationDictionary, null) :
+            null;
 
-        // Remove the attributes that can be discarded.
-        programClassPool.classesAccept(new AttributeShrinker());
+        DictionaryNameFactory packageNameFactory = configuration.packageObfuscationDictionary != null ?
+            new DictionaryNameFactory(configuration.packageObfuscationDictionary, null) :
+            null;
 
-        // Come up with new names for all classes.
         programClassPool.classesAccept(
             new ClassObfuscator(programClassPool,
+                                classNameFactory,
+                                packageNameFactory,
                                 configuration.useMixedCaseClassNames,
                                 configuration.flattenPackageHierarchy,
                                 configuration.repackageClasses,
@@ -397,7 +406,7 @@ public class Obfuscator
         {
             programClassPool.classesAccept(
                 new AllConstantVisitor(
-                new ClassOpener()));
+                new AccessFixer()));
         }
 
         // Rename the source file attributes, if requested.
diff --git a/src/proguard/obfuscate/SimpleNameFactory.java b/src/proguard/obfuscate/SimpleNameFactory.java
index 23b0441..211dbc3 100644
--- a/src/proguard/obfuscate/SimpleNameFactory.java
+++ b/src/proguard/obfuscate/SimpleNameFactory.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/SourceFileRenamer.java b/src/proguard/obfuscate/SourceFileRenamer.java
index 562fb46..daf4df6 100644
--- a/src/proguard/obfuscate/SourceFileRenamer.java
+++ b/src/proguard/obfuscate/SourceFileRenamer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -39,8 +39,6 @@ extends      SimplifiedVisitor
 implements   ClassVisitor,
              AttributeVisitor
 {
-    private final ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor();
-
     private final String newSourceFileAttribute;
 
 
@@ -79,8 +77,7 @@ implements   ClassVisitor,
     {
         // Fix the source file attribute.
         sourceFileAttribute.u2sourceFileIndex =
-            constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                               newSourceFileAttribute);
+            new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSourceFileAttribute);
     }
 
 
@@ -88,7 +85,6 @@ implements   ClassVisitor,
     {
         // Fix the source file attribute.
         sourceDirAttribute.u2sourceDirIndex =
-            constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                               newSourceFileAttribute);
+            new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSourceFileAttribute);
     }
 }
diff --git a/src/proguard/obfuscate/SpecialNameFactory.java b/src/proguard/obfuscate/SpecialNameFactory.java
index 4e1b42d..64607aa 100644
--- a/src/proguard/obfuscate/SpecialNameFactory.java
+++ b/src/proguard/obfuscate/SpecialNameFactory.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/Utf8Shrinker.java b/src/proguard/obfuscate/Utf8Shrinker.java
index 85d16bc..9ceb02c 100644
--- a/src/proguard/obfuscate/Utf8Shrinker.java
+++ b/src/proguard/obfuscate/Utf8Shrinker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/obfuscate/Utf8UsageMarker.java b/src/proguard/obfuscate/Utf8UsageMarker.java
index 23a55e9..b521193 100644
--- a/src/proguard/obfuscate/Utf8UsageMarker.java
+++ b/src/proguard/obfuscate/Utf8UsageMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/ChangedCodePrinter.java b/src/proguard/optimize/ChangedCodePrinter.java
index 8086eae..29d21ee 100644
--- a/src/proguard/optimize/ChangedCodePrinter.java
+++ b/src/proguard/optimize/ChangedCodePrinter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/ConstantMemberFilter.java b/src/proguard/optimize/ConstantMemberFilter.java
index 5b8ff64..4058eb1 100644
--- a/src/proguard/optimize/ConstantMemberFilter.java
+++ b/src/proguard/optimize/ConstantMemberFilter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
@@ -58,7 +58,7 @@ implements   MemberVisitor
     {
         Value value = StoringInvocationUnit.getFieldValue(programField);
         if (value != null &&
-            value.isSpecific())
+            value.isParticular())
         {
             constantMemberVisitor.visitProgramField(programClass, programField);
         }
@@ -69,7 +69,7 @@ implements   MemberVisitor
     {
         Value value = StoringInvocationUnit.getMethodReturnValue(programMethod);
         if (value != null &&
-            value.isSpecific())
+            value.isParticular())
         {
             constantMemberVisitor.visitProgramMethod(programClass, programMethod);
         }
diff --git a/src/proguard/optimize/DuplicateInitializerFixer.java b/src/proguard/optimize/DuplicateInitializerFixer.java
index 50e23b0..27c655b 100644
--- a/src/proguard/optimize/DuplicateInitializerFixer.java
+++ b/src/proguard/optimize/DuplicateInitializerFixer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -51,8 +51,6 @@ implements   MemberVisitor,
 
     private final MemberVisitor extraFixedInitializerVisitor;
 
-    private final ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor();
-
 
     /**
      * Creates a new DuplicateInitializerFixer.
@@ -115,8 +113,7 @@ implements   MemberVisitor,
 
                         // Update the descriptor.
                         programMethod.u2descriptorIndex =
-                            constantPoolEditor.addUtf8Constant(programClass,
-                                                               newDescriptor);
+                            new ConstantPoolEditor(programClass).addUtf8Constant(newDescriptor);
 
                         // Fix the local variable frame size, the method
                         // signature, and the parameter annotations, if
@@ -176,14 +173,12 @@ implements   MemberVisitor,
 
         // Update the signature.
         signatureAttribute.u2signatureIndex =
-            constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                               newSignature);
+            new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature);
     }
 
 
-public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
+    public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
     {
-
         // Update the number of parameters.
         int oldParametersCount = parameterAnnotationsAttribute.u2parametersCount++;
 
diff --git a/src/proguard/optimize/DuplicateInitializerInvocationFixer.java b/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
index 49111b1..23973c9 100644
--- a/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
+++ b/src/proguard/optimize/DuplicateInitializerInvocationFixer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -44,13 +44,35 @@ implements   AttributeVisitor,
 {
     private static final boolean DEBUG = false;
 
+    private final InstructionVisitor extraAddedInstructionVisitor;
+
     private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
 
     private String  descriptor;
     private boolean hasBeenFixed;
 
 
-    // Implementations for AttributeVisitor.
+    /**
+     * Creates a new EvaluationSimplifier.
+     */
+    public DuplicateInitializerInvocationFixer()
+    {
+        this(null);
+    }
+
+
+    /**
+     * Creates a new EvaluationSimplifier.
+     * @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) {}
 
@@ -96,6 +118,11 @@ implements   AttributeVisitor,
                     System.out.println("DuplicateInitializerInvocationFixer:");
                     System.out.println("  Inserting "+extraInstruction.toString()+" before "+constantInstruction.toString(offset));
                 }
+
+                if (extraAddedInstructionVisitor != null)
+                {
+                    extraInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
+                }
             }
         }
     }
diff --git a/src/proguard/optimize/KeepMarker.java b/src/proguard/optimize/KeepMarker.java
index 161c53a..704bde5 100644
--- a/src/proguard/optimize/KeepMarker.java
+++ b/src/proguard/optimize/KeepMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/MemberDescriptorSpecializer.java b/src/proguard/optimize/MemberDescriptorSpecializer.java
index 184dd8e..1e1ba75 100644
--- a/src/proguard/optimize/MemberDescriptorSpecializer.java
+++ b/src/proguard/optimize/MemberDescriptorSpecializer.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/optimize/MethodDescriptorShrinker.java b/src/proguard/optimize/MethodDescriptorShrinker.java
index 0b2c1da..52c1134 100644
--- a/src/proguard/optimize/MethodDescriptorShrinker.java
+++ b/src/proguard/optimize/MethodDescriptorShrinker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -49,8 +49,6 @@ implements   MemberVisitor,
 
     private final MemberVisitor extraParameterMemberVisitor;
 
-    private final ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor();
-
 
     /**
      * Creates a new MethodDescriptorShrinker.
@@ -105,11 +103,14 @@ implements   MemberVisitor,
                 System.out.println("                   -> "+newDescriptor);
             }
 
+            ConstantPoolEditor constantPoolEditor =
+                new ConstantPoolEditor(programClass);
+
             // Update the name, if necessary.
             if (!newName.equals(name))
             {
                 programMethod.u2nameIndex =
-                constantPoolEditor.addUtf8Constant(programClass, newName);
+                    constantPoolEditor.addUtf8Constant(newName);
             }
 
             // Update the referenced classes.
@@ -120,7 +121,7 @@ implements   MemberVisitor,
 
             // Finally, update the descriptor itself.
             programMethod.u2descriptorIndex =
-                constantPoolEditor.addUtf8Constant(programClass, newDescriptor);
+                constantPoolEditor.addUtf8Constant(newDescriptor);
 
             // Visit the method, if required.
             if (extraParameterMemberVisitor != null)
@@ -144,8 +145,7 @@ implements   MemberVisitor,
 
         // Update the signature.
         signatureAttribute.u2signatureIndex =
-            constantPoolEditor.addUtf8Constant((ProgramClass)clazz,
-                                               newSignature);
+            new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature);
 
         // Update the referenced classes.
         signatureAttribute.referencedClasses =
@@ -218,6 +218,8 @@ implements   MemberVisitor,
             new InternalTypeEnumeration(descriptor);
 
         StringBuffer newDescriptorBuffer = new StringBuffer();
+
+        newDescriptorBuffer.append(internalTypeEnumeration.formalTypeParameters());
         newDescriptorBuffer.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN);
 
         while (internalTypeEnumeration.hasMoreTypes())
@@ -264,16 +266,25 @@ implements   MemberVisitor,
             InternalTypeEnumeration internalTypeEnumeration =
                 new InternalTypeEnumeration(descriptor);
 
+            // Also look at 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++];
+            }
+
             while (internalTypeEnumeration.hasMoreTypes())
             {
                 // Consider the classes referenced by this parameter type.
-                String type       = internalTypeEnumeration.nextType();
-                int    classCount = new DescriptorClassEnumeration(type).classCount();
+                type  = internalTypeEnumeration.nextType();
+                count = new DescriptorClassEnumeration(type).classCount();
 
                 if (ParameterUsageMarker.isParameterUsed(method, parameterIndex))
                 {
                     // Copy the referenced classes.
-                    for (int counter = 0; counter < classCount; counter++)
+                    for (int counter = 0; counter < count; counter++)
                     {
                         referencedClasses[newReferencedClassIndex++] =
                             referencedClasses[referencedClassIndex++];
@@ -282,15 +293,15 @@ implements   MemberVisitor,
                 else
                 {
                     // Skip the referenced classes.
-                    referencedClassIndex += classCount;
+                    referencedClassIndex += count;
                 }
 
                 parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1;
             }
 
             // Also look at the return value.
-            String type = internalTypeEnumeration.returnType();
-            int count = new DescriptorClassEnumeration(type).classCount();
+            type  = internalTypeEnumeration.returnType();
+            count = new DescriptorClassEnumeration(type).classCount();
             for (int counter = 0; counter < count; counter++)
             {
                 referencedClasses[newReferencedClassIndex++] =
diff --git a/src/proguard/optimize/MethodStaticizer.java b/src/proguard/optimize/MethodStaticizer.java
index fbc97b3..15518a3 100644
--- a/src/proguard/optimize/MethodStaticizer.java
+++ b/src/proguard/optimize/MethodStaticizer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/OptimizationInfoMemberFilter.java b/src/proguard/optimize/OptimizationInfoMemberFilter.java
index 329d195..f91f6bf 100644
--- a/src/proguard/optimize/OptimizationInfoMemberFilter.java
+++ b/src/proguard/optimize/OptimizationInfoMemberFilter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/optimize/Optimizer.java b/src/proguard/optimize/Optimizer.java
index aac86eb..8d61e10 100644
--- a/src/proguard/optimize/Optimizer.java
+++ b/src/proguard/optimize/Optimizer.java
@@ -2,14 +2,13 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- *
  * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
@@ -29,7 +28,7 @@ import proguard.classfile.editor.*;
 import proguard.classfile.instruction.visitor.*;
 import proguard.classfile.util.MethodLinker;
 import proguard.classfile.visitor.*;
-import proguard.evaluation.value.SpecificValueFactory;
+import proguard.evaluation.value.*;
 import proguard.optimize.evaluation.*;
 import proguard.optimize.info.*;
 import proguard.optimize.peephole.*;
@@ -70,27 +69,28 @@ public class Optimizer
         }
 
         // Create counters to count the numbers of optimizations.
-        ClassCounter       singleImplementationCounter = new ClassCounter();
-        ClassCounter       finalClassCounter           = new ClassCounter();
-        MemberCounter      finalMethodCounter          = new MemberCounter();
-        MemberCounter      privateFieldCounter         = new MemberCounter();
-        MemberCounter      privateMethodCounter        = new MemberCounter();
-        MemberCounter      staticMethodCounter         = new MemberCounter();
-        MemberCounter      writeOnlyFieldCounter       = new MemberCounter();
-        MemberCounter      constantFieldCounter        = new MemberCounter();
-        MemberCounter      constantMethodCounter       = new MemberCounter();
-        MemberCounter      descriptorShrinkCounter     = new MemberCounter();
-        MemberCounter      initializerFixCounter       = new MemberCounter();
-        MemberCounter      parameterShrinkCounter      = new MemberCounter();
-        MemberCounter      variableShrinkCounter       = new MemberCounter();
-        ExceptionCounter   exceptionCounter            = new ExceptionCounter();
-        InstructionCounter inliningCounter             = new InstructionCounter();
-        InstructionCounter commonCodeCounter           = new InstructionCounter();
-        InstructionCounter pushCounter                 = new InstructionCounter();
-        InstructionCounter branchCounter               = new InstructionCounter();
-        InstructionCounter deletedCounter              = new InstructionCounter();
-        InstructionCounter addedCounter                = new InstructionCounter();
-        InstructionCounter peepholeCounter             = new InstructionCounter();
+        ClassCounter       classMergeCounter       = new ClassCounter();
+        ClassCounter       finalClassCounter       = new ClassCounter();
+        MemberCounter      finalMethodCounter      = new MemberCounter();
+        MemberCounter      privateFieldCounter     = new MemberCounter();
+        MemberCounter      privateMethodCounter    = new MemberCounter();
+        MemberCounter      staticMethodCounter     = new MemberCounter();
+        MemberCounter      writeOnlyFieldCounter   = new MemberCounter();
+        MemberCounter      constantFieldCounter    = new MemberCounter();
+        MemberCounter      constantMethodCounter   = new MemberCounter();
+        MemberCounter      descriptorShrinkCounter = new MemberCounter();
+        MemberCounter      initializerFixCounter   = new MemberCounter();
+        MemberCounter      parameterShrinkCounter  = new MemberCounter();
+        MemberCounter      variableShrinkCounter   = new MemberCounter();
+        ExceptionCounter   exceptionCounter        = new ExceptionCounter();
+        InstructionCounter inliningCounter         = new InstructionCounter();
+        InstructionCounter tailRecursionCounter    = new InstructionCounter();
+        InstructionCounter commonCodeCounter       = new InstructionCounter();
+        InstructionCounter pushCounter             = new InstructionCounter();
+        InstructionCounter branchCounter           = new InstructionCounter();
+        InstructionCounter deletedCounter          = new InstructionCounter();
+        InstructionCounter addedCounter            = new InstructionCounter();
+        InstructionCounter peepholeCounter         = new InstructionCounter();
 
         // Clean up any old visitor info.
         programClassPool.classesAccept(new ClassCleaner());
@@ -129,8 +129,10 @@ public class Optimizer
         programClassPool.classesAccept(new AllConstantVisitor(
                                        new ClassForNameClassVisitor(keepMarker)));
 
-        // Attach some optimization info to all class members, so it can be
-        // filled out later.
+        // 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()));
 
@@ -148,9 +150,6 @@ public class Optimizer
             libraryClassPool.accept(noClassPoolvisitor);
         }
 
-        // Mark all interfaces that have single implementations.
-        programClassPool.classesAccept(new SingleImplementationMarker(configuration.allowAccessModification, singleImplementationCounter));
-
         // Make classes and methods final, as far as possible.
         programClassPool.classesAccept(new ClassFinalizer(finalClassCounter, finalMethodCounter));
 
@@ -158,11 +157,7 @@ public class Optimizer
         programClassPool.classesAccept(new AllMethodVisitor(
                                        new AllAttributeVisitor(
                                        new AllInstructionVisitor(
-                                       new MultiInstructionVisitor(
-                                       new InstructionVisitor[]
-                                       {
-                                           new ReadWriteFieldMarker(),
-                                       })))));
+                                       new ReadWriteFieldMarker()))));
 
         // Mark all used parameters, including the 'this' parameters.
         programClassPool.classesAccept(new AllMethodVisitor(
@@ -177,9 +172,11 @@ public class Optimizer
 
         // Perform partial evaluation for filling out fields, method parameters,
         // and method return values.
+        ValueFactory valueFactory = new IdentifiedValueFactory();
+
         programClassPool.classesAccept(new AllMethodVisitor(
                                        new AllAttributeVisitor(
-                                       new PartialEvaluator(new SpecificValueFactory(), new StoringInvocationUnit(), false))));
+                                       new PartialEvaluator(valueFactory, new StoringInvocationUnit(valueFactory), false))));
 
         // Simplify based on partial evaluation.
         // Also remove unused parameters from the stack before method invocations,
@@ -188,7 +185,7 @@ public class Optimizer
         programClassPool.classesAccept(new AllMethodVisitor(
                                        new AllAttributeVisitor(
                                        new EvaluationSimplifier(
-                                       new PartialEvaluator(new SpecificValueFactory(), new LoadingInvocationUnit(), false),
+                                       new PartialEvaluator(valueFactory, new LoadingInvocationUnit(valueFactory), false),
                                        pushCounter, branchCounter, deletedCounter, addedCounter))));
 
         // Shrink the parameters in the method descriptors.
@@ -237,12 +234,6 @@ public class Optimizer
 //                                       new OptimizationInfoMemberFilter(
 //                                       new ClassReferenceFixer(true))));
 
-        // Inline interfaces with single implementations.
-        programClassPool.classesAccept(new SingleImplementationInliner());
-
-        // Restore the interface references from these single implementations.
-        programClassPool.classesAccept(new SingleImplementationFixer());
-
         if (configuration.allowAccessModification)
         {
             // Fix the access flags of referenced classes and class members,
@@ -251,31 +242,81 @@ public class Optimizer
                                            new AccessFixer()));
         }
 
-        // Fix all references to classes, for SingleImplementationInliner.
-        programClassPool.classesAccept(new ClassReferenceFixer(true));
-
-        // Fix all references to class members, for SingleImplementationInliner.
-        programClassPool.classesAccept(new MemberReferenceFixer());
-
+        // 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.
-        // Mark all exception catches of methods.
-        programClassPool.classesAccept(new AllMethodVisitor(
-                                       new AllAttributeVisitor(
-                                       new MultiAttributeVisitor(
-                                       new AttributeVisitor[]
+        programClassPool.classesAccept(new MultiClassVisitor(
+                                       new ClassVisitor[]
                                        {
-                                           new AllInstructionVisitor(
-                                           new MultiInstructionVisitor(
-                                           new InstructionVisitor[]
+                                           new AllConstantVisitor(
+                                           new PackageVisibleMemberInvokingClassMarker()),
+                                           new AllMethodVisitor(
+                                           new MultiMemberVisitor(
+                                           new MemberVisitor[]
                                            {
-                                               new MethodInvocationMarker(),
-                                               new SuperInvocationMarker(),
-                                               new BackwardBranchMarker(),
-                                               new AccessMethodMarker(),
+                                               new PackageVisibleMemberContainingClassMarker(),
+                                               new AllAttributeVisitor(
+                                               new MultiAttributeVisitor(
+                                               new AttributeVisitor[]
+                                               {
+                                                   new CatchExceptionMarker(),
+                                                   new AllInstructionVisitor(
+                                                   new MultiInstructionVisitor(
+                                                   new InstructionVisitor[]
+                                                   {
+                                                       new InstantiationClassMarker(),
+                                                       new InstanceofClassMarker(),
+                                                       new DotClassMarker(),
+                                                       new MethodInvocationMarker(),
+                                                       new SuperInvocationMarker(),
+                                                       new BackwardBranchMarker(),
+                                                       new AccessMethodMarker(),
+                                                   })),
+                                               })),
                                            })),
-                                           new CatchExceptionMarker(),
-                                       }))));
+                                       }));
+
+        // Tweak the descriptors of duplicate initializers.
+        programClassPool.classesAccept(new AllMethodVisitor(
+                                       new DuplicateInitializerFixer(initializerFixCounter)));
+
+        if (initializerFixCounter.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());
+        }
+
+        // Merge classes into their superclasses or interfaces.
+        programClassPool.classesAccept(new VerticalClassMerger(configuration.allowAccessModification,
+                                                               configuration.mergeInterfacesAggressively,
+                                                               classMergeCounter));
+
+        // Merge classes into their sibling classes.
+        programClassPool.classesAccept(new HorizontalClassMerger(configuration.allowAccessModification,
+                                                                 configuration.mergeInterfacesAggressively,
+                                                                 classMergeCounter));
+
+        // Clean up inner class attributes to avoid loops.
+        programClassPool.classesAccept(new RetargetedInnerClassAttributeRemover());
+
+        // Update references to merged classes.
+        programClassPool.classesAccept(new TargetClassChanger());
+        programClassPool.classesAccept(new ClassReferenceFixer(true));
+        programClassPool.classesAccept(new MemberReferenceFixer());
+
+        if (configuration.allowAccessModification)
+        {
+            // Fix the access flags of referenced merged classes and their class
+            // members.
+            programClassPool.classesAccept(new AllConstantVisitor(
+                                           new AccessFixer()));
+        }
 
         // Inline methods that are only invoked once.
         programClassPool.classesAccept(new AllMethodVisitor(
@@ -287,6 +328,11 @@ public class Optimizer
                                        new AllAttributeVisitor(
                                        new MethodInliner(configuration.microEdition, configuration.allowAccessModification, false, inliningCounter))));
 
+        // Simplify tail recursion calls.
+        programClassPool.classesAccept(new AllMethodVisitor(
+                                       new AllAttributeVisitor(
+                                       new TailRecursionSimplifier(tailRecursionCounter))));
+
         // Mark all class members that can not be made private.
         programClassPool.classesAccept(new NonPrivateMemberMarker());
 
@@ -306,7 +352,7 @@ public class Optimizer
         }
 
         // Fix invocations of methods that have become non-abstract or private,
-        // for SingleImplementationInliner, MemberPrivatizer, AccessFixer.
+        // for ClassMerger, MemberPrivatizer, AccessFixer.
         programClassPool.classesAccept(new AllMemberVisitor(
                                        new AllAttributeVisitor(
                                        new MethodInvocationFixer())));
@@ -335,24 +381,6 @@ public class Optimizer
                                            new GotoReturnReplacer(                              codeAttributeEditor, peepholeCounter),
                                        })))));
 
-        // Tweak the descriptors of duplicate initializers.
-        DuplicateInitializerFixer duplicateInitializerFixer =
-            new DuplicateInitializerFixer(initializerFixCounter);
-
-        programClassPool.classesAccept(new AllMethodVisitor(
-                                       duplicateInitializerFixer));
-
-        if (initializerFixCounter.getCount() > 0)
-        {
-            // Fix all invocations of tweaked initializers.
-            programClassPool.classesAccept(new AllMethodVisitor(
-                                           new AllAttributeVisitor(
-                                           new DuplicateInitializerInvocationFixer())));
-
-            // Fix all references to tweaked initializers.
-            programClassPool.classesAccept(new MemberReferenceFixer());
-        }
-
         // Remove unnecessary exception handlers.
         programClassPool.classesAccept(new AllMethodVisitor(
                                        new AllAttributeVisitor(
@@ -373,67 +401,70 @@ public class Optimizer
                                        new AllAttributeVisitor(
                                        new VariableOptimizer(!configuration.microEdition))));
 
-        int singleImplementationCount = singleImplementationCounter.getCount();
-        int finalClassCount           = finalClassCounter          .getCount();
-        int privateFieldCount         = privateFieldCounter        .getCount();
-        int privateMethodCount        = privateMethodCounter       .getCount();
-        int staticMethodCount         = staticMethodCounter        .getCount();
-        int finalMethodCount          = finalMethodCounter         .getCount();
-        int writeOnlyFieldCount       = writeOnlyFieldCounter      .getCount();
-        int constantFieldCount        = constantFieldCounter       .getCount();
-        int constantMethodCount       = constantMethodCounter      .getCount();
-        int descriptorShrinkCount     = descriptorShrinkCounter    .getCount() - initializerFixCounter.getCount();
-        int parameterShrinkCount      = parameterShrinkCounter     .getCount() - initializerFixCounter.getCount();
-        int variableShrinkCount       = variableShrinkCounter      .getCount();
-        int exceptionCount            = exceptionCounter           .getCount();
-        int inliningCount             = inliningCounter            .getCount();
-        int commonCodeCount           = commonCodeCounter          .getCount();
-        int pushCount                 = pushCounter                .getCount();
-        int branchCount               = branchCounter              .getCount();
-        int removedCount              = deletedCounter             .getCount() - addedCounter.getCount();
-        int peepholeCount             = peepholeCounter            .getCount();
+        int classMergeCound       = classMergeCounter      .getCount();
+        int finalClassCount       = finalClassCounter      .getCount();
+        int privateFieldCount     = privateFieldCounter    .getCount();
+        int privateMethodCount    = privateMethodCounter   .getCount();
+        int staticMethodCount     = staticMethodCounter    .getCount();
+        int finalMethodCount      = finalMethodCounter     .getCount();
+        int writeOnlyFieldCount   = writeOnlyFieldCounter  .getCount();
+        int constantFieldCount    = constantFieldCounter   .getCount();
+        int constantMethodCount   = constantMethodCounter  .getCount();
+        int descriptorShrinkCount = descriptorShrinkCounter.getCount() - initializerFixCounter.getCount();
+        int parameterShrinkCount  = parameterShrinkCounter .getCount() - initializerFixCounter.getCount();
+        int variableShrinkCount   = variableShrinkCounter  .getCount();
+        int exceptionCount        = exceptionCounter       .getCount();
+        int tailRecursionCount    = tailRecursionCounter   .getCount();
+        int inliningCount         = inliningCounter        .getCount();
+        int commonCodeCount       = commonCodeCounter      .getCount();
+        int pushCount             = pushCounter            .getCount();
+        int branchCount           = branchCounter          .getCount();
+        int removedCount          = deletedCounter         .getCount() - addedCounter.getCount();
+        int peepholeCount         = peepholeCounter        .getCount();
 
         if (configuration.verbose)
         {
-            System.out.println("  Number of inlined interfaces:             "+singleImplementationCount);
-            System.out.println("  Number of finalized classes:              "+finalClassCount);
-            System.out.println("  Number of privatized fields:              "+privateFieldCount);
-            System.out.println("  Number of privatized methods:             "+privateMethodCount);
-            System.out.println("  Number of staticized methods:             "+staticMethodCount);
-            System.out.println("  Number of finalized methods:              "+finalMethodCount);
-            System.out.println("  Number of removed write-only fields:      "+writeOnlyFieldCount);
-            System.out.println("  Number of inlined constant fields:        "+constantFieldCount);
-            System.out.println("  Number of inlined constant methods:       "+constantMethodCount);
-            System.out.println("  Number of simplified method declarations: "+descriptorShrinkCount);
-            System.out.println("  Number of removed parameters:             "+parameterShrinkCount);
-            System.out.println("  Number of removed local variables:        "+variableShrinkCount);
-            System.out.println("  Number of inlined method calls:           "+inliningCount);
-            System.out.println("  Number of removed exception blocks:       "+exceptionCount);
-            System.out.println("  Number of merged code blocks:             "+commonCodeCount);
-            System.out.println("  Number of simplified push instructions:   "+pushCount);
-            System.out.println("  Number of simplified branches:            "+branchCount);
-            System.out.println("  Number of removed instructions:           "+removedCount);
-            System.out.println("  Number of peephole optimizations:         "+peepholeCount);
+            System.out.println("  Number of merged classes:                  "+classMergeCound);
+            System.out.println("  Number of finalized classes:               "+finalClassCount);
+            System.out.println("  Number of privatized fields:               "+privateFieldCount);
+            System.out.println("  Number of privatized methods:              "+privateMethodCount);
+            System.out.println("  Number of staticized methods:              "+staticMethodCount);
+            System.out.println("  Number of finalized methods:               "+finalMethodCount);
+            System.out.println("  Number of removed write-only fields:       "+writeOnlyFieldCount);
+            System.out.println("  Number of inlined constant fields:         "+constantFieldCount);
+            System.out.println("  Number of inlined constant methods:        "+constantMethodCount);
+            System.out.println("  Number of simplified method declarations:  "+descriptorShrinkCount);
+            System.out.println("  Number of removed parameters:              "+parameterShrinkCount);
+            System.out.println("  Number of removed local variables:         "+variableShrinkCount);
+            System.out.println("  Number of inlined method calls:            "+inliningCount);
+            System.out.println("  Number of simplified tail recursion calls: "+tailRecursionCount);
+            System.out.println("  Number of removed exception blocks:        "+exceptionCount);
+            System.out.println("  Number of merged code blocks:              "+commonCodeCount);
+            System.out.println("  Number of simplified push instructions:    "+pushCount);
+            System.out.println("  Number of simplified branches:             "+branchCount);
+            System.out.println("  Number of removed instructions:            "+removedCount);
+            System.out.println("  Number of peephole optimizations:          "+peepholeCount);
         }
 
-        return singleImplementationCount > 0 ||
-               finalClassCount           > 0 ||
-               privateFieldCount         > 0 ||
-               privateMethodCount        > 0 ||
-               staticMethodCount         > 0 ||
-               finalMethodCount          > 0 ||
-               writeOnlyFieldCount       > 0 ||
-               constantFieldCount        > 0 ||
-               constantMethodCount       > 0 ||
-               descriptorShrinkCount     > 0 ||
-               parameterShrinkCount      > 0 ||
-               variableShrinkCount       > 0 ||
-               inliningCount             > 0 ||
-               exceptionCount            > 0 ||
-               commonCodeCount           > 0 ||
-               pushCount                 > 0 ||
-               branchCount               > 0 ||
-               removedCount              > 0 ||
-               peepholeCount             > 0;
+        return classMergeCound       > 0 ||
+               finalClassCount       > 0 ||
+               privateFieldCount     > 0 ||
+               privateMethodCount    > 0 ||
+               staticMethodCount     > 0 ||
+               finalMethodCount      > 0 ||
+               writeOnlyFieldCount   > 0 ||
+               constantFieldCount    > 0 ||
+               constantMethodCount   > 0 ||
+               descriptorShrinkCount > 0 ||
+               parameterShrinkCount  > 0 ||
+               variableShrinkCount   > 0 ||
+               inliningCount         > 0 ||
+               tailRecursionCount    > 0 ||
+               exceptionCount        > 0 ||
+               commonCodeCount       > 0 ||
+               pushCount             > 0 ||
+               branchCount           > 0 ||
+               removedCount          > 0 ||
+               peepholeCount         > 0;
     }
 }
diff --git a/src/proguard/optimize/ParameterShrinker.java b/src/proguard/optimize/ParameterShrinker.java
index 8c6ba27..9e94985 100644
--- a/src/proguard/optimize/ParameterShrinker.java
+++ b/src/proguard/optimize/ParameterShrinker.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/optimize/TailRecursionSimplifier.java b/src/proguard/optimize/TailRecursionSimplifier.java
new file mode 100644
index 0000000..c571cf7
--- /dev/null
+++ b/src/proguard/optimize/TailRecursionSimplifier.java
@@ -0,0 +1,335 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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.MethodrefConstant;
+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 int MAXIMUM_CODE_EXPANSION    =   2;
+    private static final int MAXIMUM_EXTRA_CODE_LENGTH = 128;
+
+    //*
+    private static final boolean DEBUG = false;
+    /*/
+    private static       boolean DEBUG = true;
+    //*/
+
+
+    private final InstructionVisitor extraTailRecursionVisitor;
+
+
+    private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
+
+    private Method  targetMethod;
+    private boolean recursive;
+    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.INTERNAL_ACC_PRIVATE |
+                            ClassConstants.INTERNAL_ACC_STATIC  |
+                            ClassConstants.INTERNAL_ACC_FINAL)) != 0 &&
+
+            // Only check the method if it is not synchronized, etc.
+            (accessFlags & (ClassConstants.INTERNAL_ACC_SYNCHRONIZED |
+                            ClassConstants.INTERNAL_ACC_NATIVE       |
+                            ClassConstants.INTERNAL_ACC_INTERFACE    |
+                            ClassConstants.INTERNAL_ACC_ABSTRACT)) == 0)
+        {
+//            codeAttributeComposer.DEBUG = DEBUG =
+//                clazz.getName().equals("abc/Def") &&
+//                method.getName(clazz).equals("abc");
+
+            targetMethod    = method;
+            inlinedAny      = false;
+            codeAttributeComposer.reset();
+
+            // Append the body of the code.
+            copyCode(clazz, method, codeAttribute);
+
+            // Update the code attribute if any code has been inlined.
+            if (inlinedAny)
+            {
+                codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
+            }
+        }
+    }
+
+
+    /**
+     * 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 * MAXIMUM_CODE_EXPANSION +
+                                                MAXIMUM_EXTRA_CODE_LENGTH);
+
+        // Copy the instructions.
+        codeAttribute.instructionsAccept(clazz, method, this);
+
+        // Append a label just after the code.
+        codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
+
+        codeAttributeComposer.endCodeFragment();
+    }
+
+
+    // Implementations for InstructionVisitor.
+
+    public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+    {
+        // Copy the instruction.
+        codeAttributeComposer.appendInstruction(offset, instruction.shrink());
+    }
+
+
+    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, this);
+
+                if (recursive)
+                {
+                    // 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, this);
+
+                            if (recursive)
+                            {
+                                if (DEBUG)
+                                {
+                                    System.out.println("TailRecursionSimplifier.visitConstantInstruction: ["+
+                                                       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.shrink());
+    }
+
+
+    // Implementations for ConstantVisitor.
+
+    public void visitMethodrefConstant(Clazz clazz, MethodrefConstant 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.INTERNAL_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((parameterOffset + parameterCount) * 4);
+
+        // 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.INTERNAL_TYPE_BOOLEAN:
+                    case ClassConstants.INTERNAL_TYPE_BYTE:
+                    case ClassConstants.INTERNAL_TYPE_CHAR:
+                    case ClassConstants.INTERNAL_TYPE_SHORT:
+                    case ClassConstants.INTERNAL_TYPE_INT:
+                        opcode = InstructionConstants.OP_ISTORE;
+                        break;
+
+                    case ClassConstants.INTERNAL_TYPE_LONG:
+                        opcode = InstructionConstants.OP_LSTORE;
+                        break;
+
+                    case ClassConstants.INTERNAL_TYPE_FLOAT:
+                        opcode = InstructionConstants.OP_FSTORE;
+                        break;
+
+                    case ClassConstants.INTERNAL_TYPE_DOUBLE:
+                        opcode = InstructionConstants.OP_DSTORE;
+                        break;
+
+                    default:
+                        opcode = InstructionConstants.OP_ASTORE;
+                        break;
+                }
+
+                codeAttributeComposer.appendInstruction(parameterSize-parameterIndex-1,
+                                                        new VariableInstruction(opcode, parameterOffset + parameterIndex).shrink());
+            }
+        }
+
+        // Put the 'this' reference in variable 0.
+        if (!isStatic)
+        {
+            codeAttributeComposer.appendInstruction(parameterSize,
+                                                    new VariableInstruction(InstructionConstants.OP_ASTORE, 0).shrink());
+        }
+
+        codeAttributeComposer.endCodeFragment();
+    }
+}
\ No newline at end of file
diff --git a/src/proguard/optimize/UnusedParameterInvocationUnit.java b/src/proguard/optimize/UnusedParameterInvocationUnit.java
deleted file mode 100644
index cfe8a2e..0000000
--- a/src/proguard/optimize/UnusedParameterInvocationUnit.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- *             of Java bytecode.
- *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; 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.CodeAttribute;
-import proguard.classfile.constant.*;
-import proguard.classfile.constant.visitor.ConstantVisitor;
-import proguard.classfile.instruction.ConstantInstruction;
-import proguard.classfile.util.SimplifiedVisitor;
-import proguard.classfile.visitor.MemberVisitor;
-import proguard.evaluation.*;
-import proguard.evaluation.value.Value;
-import proguard.optimize.info.ParameterUsageMarker;
-
-/**
- * This InvocationUnit removes unused parameters from the stack before invoking
- * a method, and then delegates to another given InvocationUnit.
- *
- * @see ParameterUsageMarker
- * @author Eric Lafortune
- */
-public class UnusedParameterInvocationUnit
-extends      SimplifiedVisitor
-implements   InvocationUnit,
-             ConstantVisitor,
-             MemberVisitor
-{
-    private static final boolean DEBUG = false;
-
-
-    private final InvocationUnit invocationUnit;
-
-    private Stack stack;
-
-
-    public UnusedParameterInvocationUnit(InvocationUnit invocationUnit)
-    {
-        this.invocationUnit = invocationUnit;
-    }
-
-
-    // Implementations for InvocationUnit.
-
-
-    public void enterMethod(Clazz clazz, Method method, Variables variables)
-    {
-        invocationUnit.enterMethod(clazz, method, variables);
-    }
-
-
-    public void exitMethod(Clazz clazz, Method method, Value returnValue)
-    {
-        invocationUnit.exitMethod(clazz, method, returnValue);
-    }
-
-
-    public void invokeMember(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction, Stack stack)
-    {
-        // Fix the stack if this is a method invocation of which some
-        // parameters are marked as unused.
-        this.stack = stack;
-        clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
-
-        invocationUnit.invokeMember(clazz,
-                                    method,
-                                    codeAttribute,
-                                    offset,
-                                    constantInstruction,
-                                    stack);
-    }
-
-
-    // Implementations for ConstantVisitor.
-
-    public void visitAnyConstant(Clazz clazz, Constant constant) {}
-
-
-    public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
-    {
-        refConstant.referencedMemberAccept(this);
-    }
-
-
-    // Implementations for MemberVisitor.
-
-    public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
-    {
-        if (DEBUG)
-        {
-            System.out.println("UnusedParameterInvocationUnit: "+programMethod.getName(programClass)+programMethod.getDescriptor(programClass));
-        }
-
-        // Get the total size of the parameters.
-        int parameterSize = ParameterUsageMarker.getParameterSize(programMethod);
-
-        // Remove unused parameters.
-        for (int index = 0; index < parameterSize; index++)
-        {
-            if (!ParameterUsageMarker.isParameterUsed(programMethod, index))
-            {
-                if (DEBUG)
-                {
-                    System.out.println("  removing stack entry #"+(parameterSize - index - 1)+" ("+stack.getTop(parameterSize - index - 1)+")");
-                }
-
-                stack.removeTop(parameterSize - index - 1);
-            }
-        }
-    }
-
-
-    public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) {}
-}
diff --git a/src/proguard/optimize/WriteOnlyFieldFilter.java b/src/proguard/optimize/WriteOnlyFieldFilter.java
index a0f2ec1..8a1985d 100644
--- a/src/proguard/optimize/WriteOnlyFieldFilter.java
+++ b/src/proguard/optimize/WriteOnlyFieldFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/evaluation/EvaluationSimplifier.java b/src/proguard/optimize/evaluation/EvaluationSimplifier.java
index a542976..95abf42 100644
--- a/src/proguard/optimize/evaluation/EvaluationSimplifier.java
+++ b/src/proguard/optimize/evaluation/EvaluationSimplifier.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -40,8 +40,7 @@ import proguard.optimize.info.*;
  */
 public class EvaluationSimplifier
 extends      SimplifiedVisitor
-implements   AttributeVisitor,
-             InstructionVisitor
+implements   AttributeVisitor
 {
     //*
     private static final boolean DEBUG_RESULTS  = false;
@@ -59,7 +58,9 @@ implements   AttributeVisitor,
     private final InstructionVisitor extraAddedInstructionVisitor;
 
     private final PartialEvaluator             partialEvaluator;
+    private final PartialEvaluator             simplePartialEvaluator       = new PartialEvaluator();
     private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true);
+    private final MyInstructionSimplifier      instructionSimplifier        = new MyInstructionSimplifier();
     private final MyProducerMarker             producerMarker               = new MyProducerMarker();
     private final MyStackConsistencyFixer      stackConsistencyFixer        = new MyStackConsistencyFixer();
     private final CodeAttributeEditor          codeAttributeEditor          = new CodeAttributeEditor(false);
@@ -69,6 +70,7 @@ implements   AttributeVisitor,
     private boolean[][] stacksSimplifiedBefore  = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
     private boolean[]   instructionsNecessary   = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
     private boolean[]   instructionsSimplified  = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
+    private int[]       aliasingVariables       = new int[ClassConstants.TYPICAL_CODE_LENGTH];
 
     private int maxMarkedOffset;
 
@@ -121,7 +123,7 @@ implements   AttributeVisitor,
 //            clazz.getName().equals("abc/Def") &&
 //            method.getName(clazz).equals("abc");
 
-        // TODO: Remove this when the partial evaluator has stabilized.
+        // TODO: Remove this when the evaluation simplifier has stabilized.
         // Catch any unexpected exceptions from the actual visiting method.
         try
         {
@@ -172,8 +174,16 @@ implements   AttributeVisitor,
         // Replace any instructions that can be simplified.
         if (DEBUG_ANALYSIS) System.out.println("Instruction simplification:");
 
-        codeAttribute.instructionsAccept(clazz, method, this);
+        for (int offset = 0; offset < codeLength; offset++)
+        {
+            if (partialEvaluator.isTraced(offset))
+            {
+                Instruction instruction = InstructionFactory.create(codeAttribute.code,
+                                                                    offset);
 
+                instruction.accept(clazz, method, codeAttribute, offset, instructionSimplifier);
+            }
+        }
 
         // Mark all essential instructions that have been encountered as used.
         if (DEBUG_ANALYSIS) System.out.println("Usage initialization: ");
@@ -235,13 +245,24 @@ implements   AttributeVisitor,
 
             if (partialEvaluator.isTraced(offset))
             {
-                if (isInstructionNecessary(offset) &&
-                    !isInstructionSimplified(offset))
+                if (isInstructionNecessary(offset))
                 {
-                    Instruction instruction = InstructionFactory.create(codeAttribute.code,
-                                                                        offset);
+                    if (isInstructionSimplified(offset))
+                    {
+                        int variableIndex = getAliasingVariable(offset);
+
+                        if (variableIndex >= 0)
+                        {
+                            markVariableProducers(offset, variableIndex);
+                        }
+                    }
+                    else
+                    {
+                        Instruction instruction = InstructionFactory.create(codeAttribute.code,
+                                                                            offset);
 
-                    instruction.accept(clazz, method, codeAttribute, offset, producerMarker);
+                        instruction.accept(clazz, method, codeAttribute, offset, producerMarker);
+                    }
                 }
 
                 // Check if this instruction is a branch origin from a branch
@@ -275,14 +296,19 @@ implements   AttributeVisitor,
 
         for (int offset = 0; offset < codeLength; offset++)
         {
-            // Is it an initialization that hasn't been marked yet, and whose
-            // corresponding variable is necessary?
+            // Is it a variable initialization that hasn't been marked yet?
             if (partialEvaluator.isTraced(offset) &&
                 !isInstructionNecessary(offset))
             {
+                // Is the corresponding variable necessary anywhere in the code,
+                // accoriding to a simple partial evaluation?
                 int variableIndex = partialEvaluator.initializedVariable(offset);
                 if (variableIndex >= 0 &&
-                    isVariableNecessaryAfter(offset, codeAttribute.u4codeLength, variableIndex))
+                    isVariableInitializationNecessary(clazz,
+                                                      method,
+                                                      codeAttribute,
+                                                      offset,
+                                                      variableIndex))
                 {
                     markInstruction(offset);
                 }
@@ -438,6 +464,285 @@ implements   AttributeVisitor,
 
 
     /**
+     * This InstructionVisitor simplifies the instructions that it visits,
+     * whenever possible, and marks them as such.
+     */
+    private class MyInstructionSimplifier
+    extends       SimplifiedVisitor
+    implements    InstructionVisitor
+    {
+        // 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:
+                    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:
+                    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:
+                    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:
+                    replaceDoublePushInstruction(clazz, offset, simpleInstruction);
+                    break;
+
+                case InstructionConstants.OP_AALOAD:
+                    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;
+
+            }
+        }
+
+
+        public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+        {
+            switch (constantInstruction.opcode)
+            {
+                case InstructionConstants.OP_GETSTATIC:
+                case InstructionConstants.OP_GETFIELD:
+                    replaceAnyPushInstruction(clazz, offset, constantInstruction);
+                    break;
+
+                case InstructionConstants.OP_INVOKEVIRTUAL:
+                case InstructionConstants.OP_INVOKESPECIAL:
+                case InstructionConstants.OP_INVOKESTATIC:
+                case InstructionConstants.OP_INVOKEINTERFACE:
+                    clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
+                                                  new ReferencedMemberVisitor(
+                                                  new MyUnusedParameterSimplifier(offset,
+                                                                                  constantInstruction)));
+
+                    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 visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+        {
+            // First try to simplify it to a simple branch.
+            replaceBranchInstruction(clazz, offset, switchInstruction);
+
+            // Otherwise make sure all branch targets are valid.
+            if (!isInstructionSimplified(offset))
+            {
+                replaceSwitchInstruction(clazz, offset, switchInstruction);
+            }
+        }
+    }
+
+
+    /**
+     * 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    MemberVisitor
+    {
+        private int                 invocationOffset;
+        private ConstantInstruction invocationInstruction;
+
+
+        /**
+         * Creates a new MyUnusedParameterSimplifier for the given invocation
+         * at the given offset.
+         */
+        private MyUnusedParameterSimplifier(int                 invocationOffset,
+                                            ConstantInstruction invocationInstruction)
+        {
+            this.invocationOffset      = invocationOffset;
+            this.invocationInstruction = invocationInstruction;
+        }
+
+
+        // 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.INTERNAL_ACC_STATIC) == 0 &&
+                !ParameterUsageMarker.isParameterUsed(programMethod, 0))
+            {
+                replaceInvocationInstruction(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.
@@ -594,6 +899,11 @@ implements   AttributeVisitor,
                     {
                         if (DEBUG_ANALYSIS) System.out.print("  Inserting before marked consumer "+instruction.toString(offset));
 
+                        if (requiredPushCount > (instruction.isCategory2() ? 2 : 1))
+                        {
+                            throw new IllegalArgumentException("Unsupported stack size increment ["+requiredPushCount+"]");
+                        }
+
                         increaseStackSize(offset, tracedStack.getTop(0).computationalType(), false);
                     }
                 }
@@ -1262,346 +1572,72 @@ implements   AttributeVisitor,
 
             if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
 
-            // Insert the pop instruction.
-            codeAttributeEditor.replaceInstruction(offset,
-                                                   replacementInstruction);
-
-            remainingPopCount -= count;
-
-            // We may insert other pop instructions before and after this one.
-            before = true;
-            after  = true;
-        }
-
-        if (before && remainingPopCount > 0)
-        {
-            // Insert before the original instruction.
-            int count = remainingPopCount == 1 ? 1 : 2;
-
-            // Create a simple pop instrucion.
-            byte replacementOpcode = count == 1 ?
-                InstructionConstants.OP_POP :
-                InstructionConstants.OP_POP2;
-
-            Instruction replacementInstruction = new SimpleInstruction(replacementOpcode);
-
-            if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
-
-            // Insert the pop instruction.
-            codeAttributeEditor.insertBeforeInstruction(offset,
-                                                        replacementInstruction);
-
-            remainingPopCount -= count;
-
-            if (extraAddedInstructionVisitor != null)
-            {
-                replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
-            }
-        }
-
-        if (after && remainingPopCount > 0)
-        {
-            // Insert after the original instruction.
-            int count = remainingPopCount == 1 ? 1 : 2;
-
-            // Create a simple pop instrucion.
-            byte replacementOpcode = count == 1 ?
-                InstructionConstants.OP_POP :
-                InstructionConstants.OP_POP2;
-
-            Instruction replacementInstruction = new SimpleInstruction(replacementOpcode);
-
-            if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
-
-            // Insert the pop instruction.
-            codeAttributeEditor.insertAfterInstruction(offset,
-                                                       replacementInstruction);
-
-            remainingPopCount -= count;
-
-            if (extraAddedInstructionVisitor != null)
-            {
-                replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
-            }
-        }
-
-        if (remainingPopCount > 0)
-        {
-            throw new UnsupportedOperationException("Unsupported stack size reduction ["+popCount+"]");
-        }
-    }
-
-
-    // Implementations for InstructionVisitor.
-
-    public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
-    {
-        if (partialEvaluator.isTraced(offset))
-        {
-            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:
-                    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:
-                    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:
-                    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:
-                    replaceDoublePushInstruction(clazz, offset, simpleInstruction);
-                    break;
-
-                case InstructionConstants.OP_AALOAD:
-                    replaceReferencePushInstruction(clazz, offset, simpleInstruction    );
-                    break;
-            }
-        }
-    }
-
-
-    public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
-    {
-        if (partialEvaluator.isTraced(offset))
-        {
-            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);
-                    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);
-                    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);
-                    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);
-                    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;
-
-            }
-        }
-    }
-
-
-    public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
-    {
-        if (partialEvaluator.isTraced(offset))
-        {
-            switch (constantInstruction.opcode)
-            {
-                case InstructionConstants.OP_GETSTATIC:
-                case InstructionConstants.OP_GETFIELD:
-                    replaceAnyPushInstruction(clazz, offset, constantInstruction);
-                    break;
-
-                case InstructionConstants.OP_INVOKEVIRTUAL:
-                case InstructionConstants.OP_INVOKESPECIAL:
-                case InstructionConstants.OP_INVOKESTATIC:
-                case InstructionConstants.OP_INVOKEINTERFACE:
-                    clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
-                                                  new ReferencedMemberVisitor(
-                                                  new MyUnusedParameterSimplifier(offset,
-                                                                                  constantInstruction)));
-
-                    if (constantInstruction.stackPushCount(clazz) > 0 &&
-                        !sideEffectInstructionChecker.hasSideEffects(clazz,
-                                                                     method,
-                                                                     codeAttribute,
-                                                                     offset,
-                                                                     constantInstruction))
-                    {
-                        replaceAnyPushInstruction(clazz, offset, constantInstruction);
-                    }
+            // Insert the pop instruction.
+            codeAttributeEditor.replaceInstruction(offset,
+                                                   replacementInstruction);
 
-                    break;
+            remainingPopCount -= count;
 
-                case InstructionConstants.OP_CHECKCAST:
-                    replaceReferencePushInstruction(clazz, offset, constantInstruction);
-                    break;
-            }
+            // We may insert other pop instructions before and after this one.
+            before = true;
+            after  = true;
         }
-    }
 
-
-    public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
-    {
-        if (partialEvaluator.isTraced(offset))
+        if (before && remainingPopCount > 0)
         {
-            switch (branchInstruction.opcode)
-            {
-                case InstructionConstants.OP_GOTO:
-                case InstructionConstants.OP_GOTO_W:
-                    // Don't replace unconditional branches.
-                    break;
+            // Insert before the original instruction.
+            int count = remainingPopCount == 1 ? 1 : 2;
 
-                case InstructionConstants.OP_JSR:
-                case InstructionConstants.OP_JSR_W:
-                    replaceJsrInstruction(clazz, offset, branchInstruction);
-                    break;
+            // Create a simple pop instrucion.
+            byte replacementOpcode = count == 1 ?
+                InstructionConstants.OP_POP :
+                InstructionConstants.OP_POP2;
 
-                default:
-                    replaceBranchInstruction(clazz, offset, branchInstruction);
-                    break;
-            }
-        }
-    }
+            Instruction replacementInstruction = new SimpleInstruction(replacementOpcode);
 
+            if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
 
-    public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
-    {
-        if (partialEvaluator.isTraced(offset))
-        {
-            // First try to simplify it to a simple branch.
-            replaceBranchInstruction(clazz, offset, switchInstruction);
+            // Insert the pop instruction.
+            codeAttributeEditor.insertBeforeInstruction(offset,
+                                                        replacementInstruction);
 
-            // Otherwise make sure all branch targets are valid.
-            if (!isInstructionSimplified(offset))
+            remainingPopCount -= count;
+
+            if (extraAddedInstructionVisitor != null)
             {
-                replaceSwitchInstruction(clazz, offset, switchInstruction);
+                replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
             }
         }
-    }
 
-
-    private class MyUnusedParameterSimplifier
-    extends       SimplifiedVisitor
-    implements    MemberVisitor
-    {
-        private int                 invocationOffset;
-        private ConstantInstruction invocationInstruction;
-
-
-        private MyUnusedParameterSimplifier(int                 invocationOffset,
-                                            ConstantInstruction invocationInstruction)
+        if (after && remainingPopCount > 0)
         {
-            this.invocationOffset      = invocationOffset;
-            this.invocationInstruction = invocationInstruction;
-        }
+            // Insert after the original instruction.
+            int count = remainingPopCount == 1 ? 1 : 2;
 
+            // Create a simple pop instrucion.
+            byte replacementOpcode = count == 1 ?
+                InstructionConstants.OP_POP :
+                InstructionConstants.OP_POP2;
 
-        // Implementations for MemberVisitor.
+            Instruction replacementInstruction = new SimpleInstruction(replacementOpcode);
 
-        public void visitAnyMember(Clazz clazz, Member member) {}
+            if (DEBUG_ANALYSIS) System.out.println(": "+replacementInstruction.toString(offset));
 
+            // Insert the pop instruction.
+            codeAttributeEditor.insertAfterInstruction(offset,
+                                                       replacementInstruction);
 
-        public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
-        {
-            // Get the total size of the parameters.
-            int parameterSize = ParameterUsageMarker.getParameterSize(programMethod);
+            remainingPopCount -= count;
 
-            // Make the method invocation static, if possible.
-            if (!ParameterUsageMarker.isParameterUsed(programMethod, 0))
+            if (extraAddedInstructionVisitor != null)
             {
-                replaceInvocationInstruction(programClass,
-                                             invocationOffset,
-                                             invocationInstruction);
+                replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
             }
+        }
 
-            // 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.getDescriptor(programClass)+"] (stack entry #"+stackIndex+" ["+stack.getBottom(stackIndex)+"])");
-                        System.out.println("    Full stack: "+stack);
-                    }
-
-                    markStackSimplificationBefore(invocationOffset, stackIndex);
-                }
-            }
+        if (remainingPopCount > 0)
+        {
+            throw new UnsupportedOperationException("Unsupported stack size reduction ["+popCount+"]");
         }
     }
 
@@ -1617,7 +1653,7 @@ implements   AttributeVisitor,
                                            Instruction instruction)
     {
         Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
-        if (pushedValue.isSpecific())
+        if (pushedValue.isParticular())
         {
             switch (pushedValue.computationalType())
             {
@@ -1649,19 +1685,50 @@ implements   AttributeVisitor,
                                                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.isSpecific())
+        if (pushedValue.isParticular())
         {
             int value = pushedValue.integerValue().value();
             if (value << 16 >> 16 == value)
             {
-                replacePushInstruction(clazz,
+                replaceConstantPushInstruction(clazz,
                                        offset,
                                        instruction,
                                        InstructionConstants.OP_SIPUSH,
                                        value);
             }
         }
+        else if (pushedValue.isSpecific())
+        {
+            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);
+                }
+            }
+        }
     }
 
 
@@ -1673,20 +1740,51 @@ implements   AttributeVisitor,
                                             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.isSpecific())
+        if (pushedValue.isParticular())
         {
             long value = pushedValue.longValue().value();
             if (value == 0L ||
                 value == 1L)
             {
-                replacePushInstruction(clazz,
+                replaceConstantPushInstruction(clazz,
                                        offset,
                                        instruction,
                                        InstructionConstants.OP_LCONST_0,
                                        (int)value);
             }
         }
+        else if (pushedValue.isSpecific())
+        {
+            TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
+            for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
+            {
+                if (pushedValue.equals(variables.load(variableIndex)))
+                {
+                    replaceVariablePushInstruction(clazz,
+                                                   offset,
+                                                   instruction,
+                                                   InstructionConstants.OP_LLOAD,
+                                                   variableIndex);
+                }
+            }
+        }
     }
 
 
@@ -1698,21 +1796,52 @@ implements   AttributeVisitor,
                                              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.isSpecific())
+        if (pushedValue.isParticular())
         {
             float value = pushedValue.floatValue().value();
             if (value == 0f ||
                 value == 1f ||
                 value == 2f)
             {
-                replacePushInstruction(clazz,
+                replaceConstantPushInstruction(clazz,
                                        offset,
                                        instruction,
                                        InstructionConstants.OP_FCONST_0,
                                        (int)value);
             }
         }
+        else if (pushedValue.isSpecific())
+        {
+            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);
+                }
+            }
+        }
     }
 
 
@@ -1724,20 +1853,51 @@ implements   AttributeVisitor,
                                               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.isSpecific())
+        if (pushedValue.isParticular())
         {
             double value = pushedValue.doubleValue().value();
             if (value == 0.0 ||
                 value == 1.0)
             {
-                replacePushInstruction(clazz,
+                replaceConstantPushInstruction(clazz,
                                        offset,
                                        instruction,
                                        InstructionConstants.OP_DCONST_0,
                                        (int)value);
             }
         }
+        else if (pushedValue.isSpecific())
+        {
+            TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
+            for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
+            {
+                if (pushedValue.equals(variables.load(variableIndex)))
+                {
+                    replaceVariablePushInstruction(clazz,
+                                                   offset,
+                                                   instruction,
+                                                   InstructionConstants.OP_DLOAD,
+                                                   variableIndex);
+                }
+            }
+        }
     }
 
 
@@ -1750,10 +1910,10 @@ implements   AttributeVisitor,
                                                  Instruction instruction)
     {
         Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
-        if (pushedValue.isSpecific())
+        if (pushedValue.isParticular())
         {
             // A reference value can only be specific if it is null.
-            replacePushInstruction(clazz,
+            replaceConstantPushInstruction(clazz,
                                    offset,
                                    instruction,
                                    InstructionConstants.OP_ACONST_NULL,
@@ -1763,18 +1923,51 @@ implements   AttributeVisitor,
 
 
     /**
+     * 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)
+    {
+        replacePushInstruction(clazz,
+                               offset,
+                               instruction,
+                               new SimpleInstruction(replacementOpcode, value).shrink());
+    }
+
+
+    /**
+     * 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)
+    {
+        replacePushInstruction(clazz,
+                               offset,
+                               instruction,
+                               new VariableInstruction(replacementOpcode, variableIndex).shrink());
+
+        // Mark that the instruction has been simplified by loading an aliasing
+        // variable.
+        setAliasingVariable(offset, variableIndex);
+    }
+
+
+    /**
      * Replaces the instruction at a given offset by a given push instruction.
      */
     private void replacePushInstruction(Clazz       clazz,
                                         int         offset,
                                         Instruction instruction,
-                                        byte        replacementOpcode,
-                                        int         value)
+                                        Instruction replacementInstruction)
     {
-        // Remember the replacement instruction.
-        Instruction replacementInstruction =
-             new SimpleInstruction(replacementOpcode, value).shrink();
-
         if (DEBUG_ANALYSIS) System.out.println("  Replacing instruction at ["+offset+"] by "+replacementInstruction.toString());
 
         codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
@@ -2138,6 +2331,7 @@ implements   AttributeVisitor,
         {
             instructionsNecessary  = new boolean[codeLength];
             instructionsSimplified = new boolean[codeLength];
+            aliasingVariables      = new int[codeLength];
         }
         else
         {
@@ -2147,6 +2341,11 @@ implements   AttributeVisitor,
                 instructionsSimplified[index] = false;
             }
         }
+
+        for (int index = 0; index < codeLength; index++)
+        {
+            aliasingVariables[index] = -1;
+        }
     }
 
 
@@ -2170,6 +2369,67 @@ implements   AttributeVisitor,
     }
 
 
+    /**
+     * Returns whether the specified variable must be initialized at the
+     * specified offset, according to the verifier of the JVM.
+     */
+    private boolean isVariableInitializationNecessary(Clazz         clazz,
+                                                      Method        method,
+                                                      CodeAttribute codeAttribute,
+                                                      int           initializationOffset,
+                                                      int           variableIndex)
+    {
+        int codeLength = codeAttribute.u4codeLength;
+
+        // Is the variable necessary anywhere at all?
+        if (isVariableNecessaryAfterAny(0, codeLength, variableIndex))
+        {
+            if (DEBUG_ANALYSIS) System.out.println("Simple partial evalutation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
+
+            // Lazily compute perform simple partial evaluation, the way the
+            // JVM preverifier would do it.
+            simplePartialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
+            if (DEBUG_ANALYSIS) System.out.println("End of simple partial evalutation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
+
+            // Check if the variable is necessary elsewhere.
+            for (int offset = 0; offset < codeLength; offset++)
+            {
+                if (isInstructionNecessary(offset))
+                {
+                    Value producer = partialEvaluator.getVariablesBefore(offset).getProducerValue(variableIndex);
+                    if (producer != null)
+                    {
+                        Value simpleProducer = simplePartialEvaluator.getVariablesBefore(offset).getProducerValue(variableIndex);
+                        if (simpleProducer != null)
+                        {
+                            InstructionOffsetValue producerOffsets =
+                                producer.instructionOffsetValue();
+                            InstructionOffsetValue simpleProducerOffsets =
+                                simpleProducer.instructionOffsetValue();
+
+                            // Does the sophisticated partial evaluation have fewer
+                            // producers than the simple one?
+                            // And does the simple partial evaluation point to an
+                            // initialization of the variable?
+                            if (producerOffsets.instructionOffsetCount() <
+                                simpleProducerOffsets.instructionOffsetCount() &&
+                                isVariableNecessaryAfterAny(producerOffsets, variableIndex) &&
+                                simpleProducerOffsets.contains(initializationOffset))
+                            {
+                                // Then the initialization is necessary.
+                                return true;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+
     private void markVariableAfter(int instructionOffset,
                                    int variableIndex)
     {
@@ -2188,12 +2448,12 @@ implements   AttributeVisitor,
 
 
     /**
-     * Returns whether the specified variable is ever necessary after an
+     * Returns whether the specified variable is ever necessary after any
      * instruction in the specified block.
      */
-    private boolean isVariableNecessaryAfter(int startOffset,
-                                             int endOffset,
-                                             int variableIndex)
+    private boolean isVariableNecessaryAfterAny(int startOffset,
+                                                int endOffset,
+                                                int variableIndex)
     {
         for (int offset = startOffset; offset < endOffset; offset++)
         {
@@ -2207,6 +2467,28 @@ implements   AttributeVisitor,
     }
 
 
+    /**
+     * Returns whether the specified variable is ever necessary after any
+     * instruction in the specified set of instructions offsets.
+     */
+    private boolean isVariableNecessaryAfterAny(InstructionOffsetValue instructionOffsetValue,
+                                                int                    variableIndex)
+    {
+        int count = instructionOffsetValue.instructionOffsetCount();
+
+        for (int index = 0; index < count; index++)
+        {
+            if (isVariableNecessaryAfter(instructionOffsetValue.instructionOffset(index),
+                                         variableIndex))
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+
     private boolean isVariableNecessaryAfter(int instructionOffset,
                                              int variableIndex)
     {
@@ -2298,6 +2580,19 @@ implements   AttributeVisitor,
     }
 
 
+    private void setAliasingVariable(int instructionOffset,
+                                     int variableIndex)
+    {
+        aliasingVariables[instructionOffset] = variableIndex;
+    }
+
+
+    private int getAliasingVariable(int instructionOffset)
+    {
+        return aliasingVariables[instructionOffset];
+    }
+
+
     private void markInstruction(int instructionOffset)
     {
         if (!isInstructionNecessary(instructionOffset))
diff --git a/src/proguard/optimize/evaluation/LivenessAnalyzer.java b/src/proguard/optimize/evaluation/LivenessAnalyzer.java
index 41efe7c..e45842d 100644
--- a/src/proguard/optimize/evaluation/LivenessAnalyzer.java
+++ b/src/proguard/optimize/evaluation/LivenessAnalyzer.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/optimize/evaluation/LoadingInvocationUnit.java b/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
index 54991c9..61de720 100644
--- a/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
+++ b/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
@@ -35,19 +35,33 @@ import proguard.evaluation.value.*;
 public class LoadingInvocationUnit
 extends      BasicInvocationUnit
 {
+    /**
+     * Creates a new LoadingInvocationUnit with the given value factory.
+     */
+    public LoadingInvocationUnit(ValueFactory valueFactory)
+    {
+        super(valueFactory);
+    }
+
+
     // Implementations for BasicInvocationUnit.
 
     protected Value getFieldClassValue(Clazz       clazz,
                                        RefConstant refConstant,
                                        String      type)
     {
+        // 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)
+            if (value != null &&
+                value.isParticular())
             {
                 return value;
+//                // Make sure the value is refreshed.
+//                return refresh(value);
             }
         }
 
@@ -59,13 +73,18 @@ extends      BasicInvocationUnit
                                   RefConstant refConstant,
                                   String      type)
     {
+        // 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)
+            if (value != null &&
+                value.isParticular())
             {
                 return value;
+//                // Make sure the value is refreshed.
+//                return refresh(value);
             }
         }
 
@@ -79,10 +98,14 @@ extends      BasicInvocationUnit
                                             String type,
                                             Clazz  referencedClass)
     {
+        // Retrieve the stored method parameter value.
         Value value = StoringInvocationUnit.getMethodParameterValue(method, parameterIndex);
-        if (value != null)
-        {
-            return value;
+            if (value != null &&
+                value.isParticular())
+            {
+                return value;
+//            // Make sure the value is refreshed.
+//            return refresh(value);
         }
 
         return super.getMethodParameterValue(clazz,
@@ -97,13 +120,18 @@ extends      BasicInvocationUnit
                                          RefConstant refConstant,
                                          String      type)
     {
+        // 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)
+            if (value != null &&
+                value.isParticular())
             {
                 return value;
+//                // Make sure the value is refreshed.
+//                return refresh(value);
             }
         }
 
@@ -111,4 +139,31 @@ extends      BasicInvocationUnit
                                           refConstant,
                                           type);
     }
+//
+//
+//    // Small utility methods.
+//
+//    private Value refresh(Value value)
+//    {
+//        if (value.isParticular())
+//        {
+//            return value;
+//        }
+//
+//        switch (value.computationalType())
+//        {
+//            case Value.TYPE_INTEGER: return valueFactory.createIntegerValue();
+//            case Value.TYPE_LONG:    return valueFactory.createLongValue();
+//            case Value.TYPE_FLOAT:   return valueFactory.createFloatValue();
+//            case Value.TYPE_DOUBLE:  return valueFactory.createDoubleValue();
+//            default:
+//            {
+//                ReferenceValue referenceValue = value.referenceValue();
+//
+//                return valueFactory.createReferenceValue(referenceValue.getType(),
+//                                                         referenceValue.getReferencedClass(),
+//                                                         referenceValue.isNull() != Value.NEVER);
+//            }
+//        }
+//    }
 }
diff --git a/src/proguard/optimize/evaluation/PartialEvaluator.java b/src/proguard/optimize/evaluation/PartialEvaluator.java
index d6fe397..12d4cc0 100644
--- a/src/proguard/optimize/evaluation/PartialEvaluator.java
+++ b/src/proguard/optimize/evaluation/PartialEvaluator.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -77,11 +77,11 @@ implements   AttributeVisitor,
 
 
     /**
-     * Creates a new PartialEvaluator.
+     * Creates a simple PartialEvaluator.
      */
     public PartialEvaluator()
     {
-        this(new ValueFactory(), new BasicInvocationUnit(), true);
+        this(new ValueFactory(), new BasicInvocationUnit(new ValueFactory()), true);
     }
 
 
@@ -208,6 +208,12 @@ implements   AttributeVisitor,
 
                 if (isTraced(offset))
                 {
+                    int variableIndex = initializedVariable(offset);
+                    if (variableIndex >= 0)
+                    {
+                        System.out.println("     is initializing variable v"+variableIndex);
+                    }
+
                     int initializationOffset = branchTargetFinder.initializationOffset(offset);
                     if (initializationOffset != NONE)
                     {
@@ -545,6 +551,8 @@ implements   AttributeVisitor,
         // 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();
 
@@ -629,6 +637,9 @@ implements   AttributeVisitor,
                 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     &&
@@ -795,7 +806,7 @@ implements   AttributeVisitor,
                     // Push them on the execution stack and exit from this block.
                     for (int index = 0; index < branchTargetCount; index++)
                     {
-                        if (DEBUG) System.out.println("Alternative branch #"+index+" out of "+branchTargetCount+", from ["+instructionOffset+"] to ["+branchTargets.instructionOffset(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),
diff --git a/src/proguard/optimize/evaluation/StoringInvocationUnit.java b/src/proguard/optimize/evaluation/StoringInvocationUnit.java
index 4219d59..1511a60 100644
--- a/src/proguard/optimize/evaluation/StoringInvocationUnit.java
+++ b/src/proguard/optimize/evaluation/StoringInvocationUnit.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
@@ -36,6 +36,15 @@ import proguard.optimize.info.*;
 public class StoringInvocationUnit
 extends      BasicInvocationUnit
 {
+    /**
+     * Creates a new StoringInvocationUnit with the given value factory.
+     */
+    public StoringInvocationUnit(ValueFactory valueFactory)
+    {
+        super(valueFactory);
+    }
+
+
     // Implementations for BasicInvocationUnit.
 
     protected void setFieldClassValue(Clazz          clazz,
diff --git a/src/proguard/optimize/evaluation/TracedBranchUnit.java b/src/proguard/optimize/evaluation/TracedBranchUnit.java
index 118b30e..422ce11 100644
--- a/src/proguard/optimize/evaluation/TracedBranchUnit.java
+++ b/src/proguard/optimize/evaluation/TracedBranchUnit.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/evaluation/VariableOptimizer.java b/src/proguard/optimize/evaluation/VariableOptimizer.java
index 893e9aa..c500bdc 100644
--- a/src/proguard/optimize/evaluation/VariableOptimizer.java
+++ b/src/proguard/optimize/evaluation/VariableOptimizer.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/optimize/info/AccessMethodMarker.java b/src/proguard/optimize/info/AccessMethodMarker.java
index a3dd89d..16319a0 100644
--- a/src/proguard/optimize/info/AccessMethodMarker.java
+++ b/src/proguard/optimize/info/AccessMethodMarker.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/optimize/info/BackwardBranchMarker.java b/src/proguard/optimize/info/BackwardBranchMarker.java
index f96281b..d988f8d 100644
--- a/src/proguard/optimize/info/BackwardBranchMarker.java
+++ b/src/proguard/optimize/info/BackwardBranchMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/CatchExceptionMarker.java b/src/proguard/optimize/info/CatchExceptionMarker.java
index c747201..8830722 100644
--- a/src/proguard/optimize/info/CatchExceptionMarker.java
+++ b/src/proguard/optimize/info/CatchExceptionMarker.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/optimize/info/ClassOptimizationInfo.java b/src/proguard/optimize/info/ClassOptimizationInfo.java
index 115266d..e848a6e 100644
--- a/src/proguard/optimize/info/ClassOptimizationInfo.java
+++ b/src/proguard/optimize/info/ClassOptimizationInfo.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
@@ -30,9 +30,12 @@ import proguard.classfile.Clazz;
  */
 public class ClassOptimizationInfo
 {
-    private boolean isInstantiated = false;
-    private boolean isInstanceofed = false;
-    private boolean isDotClassed   = false;
+    private boolean isInstantiated                = false;
+    private boolean isInstanceofed                = false;
+    private boolean isDotClassed                  = false;
+    private boolean containsPackageVisibleMembers = false;
+    private boolean invokesPackageVisibleMembers  = false;
+    private Clazz   targetClass;
 
 
     public void setInstantiated()
@@ -71,13 +74,49 @@ public class ClassOptimizationInfo
     }
 
 
+    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 static void setClassOptimizationInfo(Clazz clazz)
     {
         clazz.setVisitorInfo(new ClassOptimizationInfo());
     }
 
 
-    public static ClassOptimizationInfo getClazzOptimizationInfo(Clazz clazz)
+    public static ClassOptimizationInfo getClassOptimizationInfo(Clazz clazz)
     {
         Object visitorInfo = clazz.getVisitorInfo();
 
diff --git a/src/proguard/obfuscate/MapCleaner.java b/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
similarity index 66%
copy from src/proguard/obfuscate/MapCleaner.java
copy to src/proguard/optimize/info/ClassOptimizationInfoSetter.java
index ae81a28..5f5cc5b 100644
--- a/src/proguard/obfuscate/MapCleaner.java
+++ b/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,40 +18,30 @@
  * 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;
+package proguard.optimize.info;
 
 import proguard.classfile.*;
 import proguard.classfile.util.SimplifiedVisitor;
 import proguard.classfile.visitor.ClassVisitor;
-
-import java.util.Map;
+import proguard.optimize.KeepMarker;
 
 /**
- * This ClassVisitor clears a given map whenever it visits a class.
+ * This ClassVisitor attaches a ClassOptimizationInfo instance to every class
+ * that is not being kept that it visits.
  *
  * @author Eric Lafortune
  */
-public class MapCleaner
+public class ClassOptimizationInfoSetter
 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.
+    // Implementations for MemberVisitor.
 
-    public void visitAnyClass(Clazz clazz)
+    public void visitProgramClass(ProgramClass programClass)
     {
-        map.clear();
+        if (!KeepMarker.isKept(programClass))
+        {
+            ClassOptimizationInfo.setClassOptimizationInfo(programClass);
+        }
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/SubclassedClassFilter.java b/src/proguard/optimize/info/DotClassFilter.java
similarity index 78%
copy from src/proguard/SubclassedClassFilter.java
copy to src/proguard/optimize/info/DotClassFilter.java
index 5ee9b1c..08aa6e5 100644
--- a/src/proguard/SubclassedClassFilter.java
+++ b/src/proguard/optimize/info/DotClassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,24 +18,25 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-package proguard;
+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 being subclassed.
+ * but only for Clazz objects that are used in a .class construct.
  *
+ * @see DotClassMarker
  * @author Eric Lafortune
  */
-final class SubclassedClassFilter
-implements ClassVisitor
+public class DotClassFilter
+implements   ClassVisitor
 {
     private final ClassVisitor classVisitor;
 
 
-    public SubclassedClassFilter(ClassVisitor classVisitor)
+    public DotClassFilter(ClassVisitor classVisitor)
     {
         this.classVisitor = classVisitor;
     }
@@ -45,7 +46,7 @@ implements ClassVisitor
 
     public void visitProgramClass(ProgramClass programClass)
     {
-        if (programClass.subClasses != null)
+        if (DotClassMarker.isDotClassed(programClass))
         {
             classVisitor.visitProgramClass(programClass);
         }
@@ -54,9 +55,9 @@ implements ClassVisitor
 
     public void visitLibraryClass(LibraryClass libraryClass)
     {
-        if (libraryClass.subClasses != null)
+        if (DotClassMarker.isDotClassed(libraryClass))
         {
             classVisitor.visitLibraryClass(libraryClass);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/visitor/DotClassClassVisitor.java b/src/proguard/optimize/info/DotClassMarker.java
similarity index 60%
copy from src/proguard/classfile/visitor/DotClassClassVisitor.java
copy to src/proguard/optimize/info/DotClassMarker.java
index cd1cbf9..a5c9395 100644
--- a/src/proguard/classfile/visitor/DotClassClassVisitor.java
+++ b/src/proguard/optimize/info/DotClassMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,7 +18,7 @@
  * with 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;
+package proguard.optimize.info;
 
 import proguard.classfile.*;
 import proguard.classfile.attribute.CodeAttribute;
@@ -27,38 +27,20 @@ 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 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.
- *
- * @see ClassForNameClassVisitor
+ * 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 DotClassClassVisitor
+public class DotClassMarker
 extends      SimplifiedVisitor
 implements   InstructionVisitor,
-             ConstantVisitor
+             ConstantVisitor,
+             ClassVisitor
 {
-    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) {}
@@ -66,14 +48,10 @@ implements   InstructionVisitor,
 
     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)
+        if (constantInstruction.opcode == InstructionConstants.OP_LDC ||
+            constantInstruction.opcode == InstructionConstants.OP_LDC_W)
         {
-            clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
-                                          this);
+            clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
         }
     }
 
@@ -82,10 +60,37 @@ implements   InstructionVisitor,
 
     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);
+        classConstant.referencedClassAccept(this);
+    }
+
+
+    // Implementations for ClassVisitor.
+
+    public void visitLibraryClass(LibraryClass libraryClass) {}
+
+    public void visitProgramClass(ProgramClass programClass)
+    {
+        setDotClassed(programClass);
+    }
+
+
+    // Small utility methods.
+
+    public 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/src/proguard/optimize/info/ExceptionInstructionChecker.java b/src/proguard/optimize/info/ExceptionInstructionChecker.java
index 6b49796..1e7e500 100644
--- a/src/proguard/optimize/info/ExceptionInstructionChecker.java
+++ b/src/proguard/optimize/info/ExceptionInstructionChecker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -36,9 +36,9 @@ import proguard.classfile.visitor.MemberVisitor;
  */
 public class ExceptionInstructionChecker
 extends      SimplifiedVisitor
-implements   InstructionVisitor,
-             ConstantVisitor,
-             MemberVisitor
+implements   InstructionVisitor
+//             ConstantVisitor,
+//             MemberVisitor
 {
     // A return value for the visitor methods.
     private boolean mayThrowExceptions;
@@ -133,52 +133,55 @@ implements   InstructionVisitor,
     }
 
 
-    // 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,
-                                                            this);
-            }
-        }
-    }
-
-
-    // Implementations for MemberVisitor.
-
-    public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
-    {
+//    // 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)
-    {
+//    }
+//
+//
+//    public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+//    {
 //        mayThrowExceptions = mayThrowExceptions ||
 //                             !NoExceptionMethodMarker.doesntThrowExceptions(libraryMethod);
-    }
+//    }
 }
diff --git a/src/proguard/optimize/info/FieldOptimizationInfo.java b/src/proguard/optimize/info/FieldOptimizationInfo.java
index f5f0e84..706ca0a 100644
--- a/src/proguard/optimize/info/FieldOptimizationInfo.java
+++ b/src/proguard/optimize/info/FieldOptimizationInfo.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/SubclassedClassFilter.java b/src/proguard/optimize/info/InstanceofClassFilter.java
similarity index 76%
copy from src/proguard/SubclassedClassFilter.java
copy to src/proguard/optimize/info/InstanceofClassFilter.java
index 5ee9b1c..68d114c 100644
--- a/src/proguard/SubclassedClassFilter.java
+++ b/src/proguard/optimize/info/InstanceofClassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,24 +18,25 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-package proguard;
+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 being subclassed.
+ * but only for Clazz objects that are used in an 'instanceof' test.
  *
+ * @see InstanceofClassMarker
  * @author Eric Lafortune
  */
-final class SubclassedClassFilter
-implements ClassVisitor
+public class InstanceofClassFilter
+implements   ClassVisitor
 {
     private final ClassVisitor classVisitor;
 
 
-    public SubclassedClassFilter(ClassVisitor classVisitor)
+    public InstanceofClassFilter(ClassVisitor classVisitor)
     {
         this.classVisitor = classVisitor;
     }
@@ -45,7 +46,7 @@ implements ClassVisitor
 
     public void visitProgramClass(ProgramClass programClass)
     {
-        if (programClass.subClasses != null)
+        if (InstanceofClassMarker.isInstanceofed(programClass))
         {
             classVisitor.visitProgramClass(programClass);
         }
@@ -54,9 +55,9 @@ implements ClassVisitor
 
     public void visitLibraryClass(LibraryClass libraryClass)
     {
-        if (libraryClass.subClasses != null)
+        if (InstanceofClassMarker.isInstanceofed(libraryClass))
         {
             classVisitor.visitLibraryClass(libraryClass);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/visitor/DotClassClassVisitor.java b/src/proguard/optimize/info/InstanceofClassMarker.java
similarity index 57%
copy from src/proguard/classfile/visitor/DotClassClassVisitor.java
copy to src/proguard/optimize/info/InstanceofClassMarker.java
index cd1cbf9..75be332 100644
--- a/src/proguard/classfile/visitor/DotClassClassVisitor.java
+++ b/src/proguard/optimize/info/InstanceofClassMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,47 +18,29 @@
  * with 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;
+package proguard.optimize.info;
 
 import proguard.classfile.*;
 import proguard.classfile.attribute.CodeAttribute;
-import proguard.classfile.constant.*;
+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 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.
- *
- * @see ClassForNameClassVisitor
+ * 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 DotClassClassVisitor
+public class InstanceofClassMarker
 extends      SimplifiedVisitor
 implements   InstructionVisitor,
-             ConstantVisitor
+             ConstantVisitor,
+             ClassVisitor
 {
-    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) {}
@@ -66,26 +48,46 @@ implements   InstructionVisitor,
 
     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)
+        if (constantInstruction.opcode == InstructionConstants.OP_INSTANCEOF)
         {
-            clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
-                                          this);
+            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);
+    }
 
 
-    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+    // Implementations for ClassVisitor.
+
+    public void visitLibraryClass(LibraryClass libraryClass) {}
+
+    public void visitProgramClass(ProgramClass programClass)
+    {
+        setInstanceofed(programClass);
+    }
+
+
+    // Small utility methods.
+
+    public static void setInstanceofed(Clazz clazz)
+    {
+        ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+        if (info != null)
+        {
+            info.setInstanceofed();
+        }
+    }
+
+
+    public static boolean isInstanceofed(Clazz clazz)
     {
-        // Visit the referenced class from the .class construct.
-        classConstant.referencedClassAccept(classVisitor);
+        ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+        return info == null || info.isInstanceofed();
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/SubclassedClassFilter.java b/src/proguard/optimize/info/InstantiationClassFilter.java
similarity index 78%
copy from src/proguard/SubclassedClassFilter.java
copy to src/proguard/optimize/info/InstantiationClassFilter.java
index 5ee9b1c..e2dbb53 100644
--- a/src/proguard/SubclassedClassFilter.java
+++ b/src/proguard/optimize/info/InstantiationClassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,24 +18,24 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-package proguard;
+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 being subclassed.
+ * but only for Clazz objects that are instantiated.
  *
  * @author Eric Lafortune
  */
-final class SubclassedClassFilter
-implements ClassVisitor
+public class InstantiationClassFilter
+implements   ClassVisitor
 {
     private final ClassVisitor classVisitor;
 
 
-    public SubclassedClassFilter(ClassVisitor classVisitor)
+    public InstantiationClassFilter(ClassVisitor classVisitor)
     {
         this.classVisitor = classVisitor;
     }
@@ -45,7 +45,7 @@ implements ClassVisitor
 
     public void visitProgramClass(ProgramClass programClass)
     {
-        if (programClass.subClasses != null)
+        if (InstantiationClassMarker.isInstantiated(programClass))
         {
             classVisitor.visitProgramClass(programClass);
         }
@@ -54,9 +54,9 @@ implements ClassVisitor
 
     public void visitLibraryClass(LibraryClass libraryClass)
     {
-        if (libraryClass.subClasses != null)
+        if (InstantiationClassMarker.isInstantiated(libraryClass))
         {
             classVisitor.visitLibraryClass(libraryClass);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/classfile/visitor/DotClassClassVisitor.java b/src/proguard/optimize/info/InstantiationClassMarker.java
similarity index 57%
copy from src/proguard/classfile/visitor/DotClassClassVisitor.java
copy to src/proguard/optimize/info/InstantiationClassMarker.java
index cd1cbf9..caf89ad 100644
--- a/src/proguard/classfile/visitor/DotClassClassVisitor.java
+++ b/src/proguard/optimize/info/InstantiationClassMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -18,47 +18,29 @@
  * with 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;
+package proguard.optimize.info;
 
 import proguard.classfile.*;
 import proguard.classfile.attribute.CodeAttribute;
-import proguard.classfile.constant.*;
+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 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.
- *
- * @see ClassForNameClassVisitor
+ * This InstructionVisitor marks all classes that are instantiated by any of
+ * the instructions that it visits.
  *
  * @author Eric Lafortune
  */
-public class DotClassClassVisitor
+public class InstantiationClassMarker
 extends      SimplifiedVisitor
 implements   InstructionVisitor,
-             ConstantVisitor
+             ConstantVisitor,
+             ClassVisitor
 {
-    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) {}
@@ -66,26 +48,46 @@ implements   InstructionVisitor,
 
     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)
+        if (constantInstruction.opcode == InstructionConstants.OP_NEW)
         {
-            clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
-                                          this);
+            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);
+    }
 
 
-    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+    // Implementations for ClassVisitor.
+
+    public void visitLibraryClass(LibraryClass libraryClass) {}
+
+    public void visitProgramClass(ProgramClass programClass)
+    {
+        setInstantiated(programClass);
+    }
+
+
+    // Small utility methods.
+
+    public static void setInstantiated(Clazz clazz)
+    {
+        ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+        if (info != null)
+        {
+            info.setInstantiated();
+        }
+    }
+
+
+    public static boolean isInstantiated(Clazz clazz)
     {
-        // Visit the referenced class from the .class construct.
-        classConstant.referencedClassAccept(classVisitor);
+        ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+        return info == null || info.isInstantiated();
     }
-}
+}
\ No newline at end of file
diff --git a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java b/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
index d9c9772..5c1a1fe 100644
--- a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
+++ b/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/MethodInvocationMarker.java b/src/proguard/optimize/info/MethodInvocationMarker.java
index a5151c8..40a2abe 100644
--- a/src/proguard/optimize/info/MethodInvocationMarker.java
+++ b/src/proguard/optimize/info/MethodInvocationMarker.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/optimize/info/MethodOptimizationInfo.java b/src/proguard/optimize/info/MethodOptimizationInfo.java
index e8af8b3..e48f5aa 100644
--- a/src/proguard/optimize/info/MethodOptimizationInfo.java
+++ b/src/proguard/optimize/info/MethodOptimizationInfo.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/NoSideEffectMethodMarker.java b/src/proguard/optimize/info/NoSideEffectMethodMarker.java
index 48b00fc..4840354 100644
--- a/src/proguard/optimize/info/NoSideEffectMethodMarker.java
+++ b/src/proguard/optimize/info/NoSideEffectMethodMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/NonPrivateMemberMarker.java b/src/proguard/optimize/info/NonPrivateMemberMarker.java
index eb5f26f..57dcf72 100644
--- a/src/proguard/optimize/info/NonPrivateMemberMarker.java
+++ b/src/proguard/optimize/info/NonPrivateMemberMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
similarity index 55%
copy from src/proguard/optimize/info/MemberOptimizationInfoSetter.java
copy to src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
index d9c9772..9753812 100644
--- a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
+++ b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -23,37 +23,45 @@ 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.
+ * This MemberVisitor marks all classes that contain visited package visible
+ * members.
  *
  * @author Eric Lafortune
  */
-public class MemberOptimizationInfoSetter
+public class PackageVisibleMemberContainingClassMarker
 extends      SimplifiedVisitor
 implements   MemberVisitor
 {
     // Implementations for MemberVisitor.
 
-    public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+    public void visitAnyMember(Clazz clazz, Member member)
     {
-        if (!KeepMarker.isKept(programMethod))
+        if ((member.getAccessFlags() &
+             (ClassConstants.INTERNAL_ACC_PRIVATE |
+              ClassConstants.INTERNAL_ACC_PUBLIC)) == 0)
         {
-            MethodOptimizationInfo.setMethodOptimizationInfo(programClass,
-                                                             programMethod);
+            setPackageVisibleMembers(clazz);
         }
     }
 
 
-    public void visitProgramField(ProgramClass programClass, ProgramField programField)
+    // Small utility methods.
+
+    public static void setPackageVisibleMembers(Clazz clazz)
     {
-        if (!KeepMarker.isKept(programField))
+        ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+        if (info != null)
         {
-            FieldOptimizationInfo.setFieldOptimizationInfo(programClass,
-                                                           programField);
+            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/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
new file mode 100644
index 0000000..4dde955
--- /dev/null
+++ b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
@@ -0,0 +1,81 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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.visitor.ConstantVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This ConstantVisitor marks all classes that invoke package visible members
+ * in other classes.
+ *
+ * @author Eric Lafortune
+ */
+public class PackageVisibleMemberInvokingClassMarker
+extends      SimplifiedVisitor
+implements   ConstantVisitor
+{
+    // Implementations for ConstantVisitor.
+
+    public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+    public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+    {
+        Clazz referencedClass = refConstant.referencedClass;
+        if (referencedClass != null &&
+            (referencedClass.getAccessFlags() &
+             ClassConstants.INTERNAL_ACC_PUBLIC) == 0)
+        {
+            setInvokesPackageVisibleMembers(clazz);
+        }
+
+        Member referencedMember = refConstant.referencedMember;
+        if (referencedMember != null &&
+            (referencedMember.getAccessFlags() &
+             (ClassConstants.INTERNAL_ACC_PUBLIC |
+              ClassConstants.INTERNAL_ACC_PRIVATE)) == 0)
+        {
+            setInvokesPackageVisibleMembers(clazz);
+        }
+    }
+
+
+    // Small utility methods.
+
+    public 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/src/proguard/optimize/info/ParameterUsageMarker.java b/src/proguard/optimize/info/ParameterUsageMarker.java
index 5a795aa..828f190 100644
--- a/src/proguard/optimize/info/ParameterUsageMarker.java
+++ b/src/proguard/optimize/info/ParameterUsageMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -91,6 +91,34 @@ implements   MemberVisitor
                         markParameterUsed(programMethod, index);
                     }
                 }
+
+                // Mark the category 2 parameters that are half-used.
+                InternalTypeEnumeration internalTypeEnumeration =
+                    new InternalTypeEnumeration(programMethod.getDescriptor(programClass));
+
+                // All parameters of non-static methods are shifted by one in
+                // the local variable frame.
+                int index =
+                    (accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0 ?
+                        0 : 1;
+
+                while (internalTypeEnumeration.hasMoreTypes())
+                {
+                    String type = internalTypeEnumeration.nextType();
+                    if (ClassUtil.isInternalCategory2Type(type))
+                    {
+                        if (variableUsageMarker.isVariableUsed(index) ||
+                            variableUsageMarker.isVariableUsed(index+1))
+                        {
+                            markParameterUsed(programMethod, index);
+                            markParameterUsed(programMethod, index+1);
+                        }
+
+                        index++;
+                    }
+
+                    index++;
+                }
             }
 
             if (DEBUG)
diff --git a/src/proguard/optimize/info/ReadWriteFieldMarker.java b/src/proguard/optimize/info/ReadWriteFieldMarker.java
index 6d312c4..f082cb1 100644
--- a/src/proguard/optimize/info/ReadWriteFieldMarker.java
+++ b/src/proguard/optimize/info/ReadWriteFieldMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/SideEffectInstructionChecker.java b/src/proguard/optimize/info/SideEffectInstructionChecker.java
index fae64c8..da69924 100644
--- a/src/proguard/optimize/info/SideEffectInstructionChecker.java
+++ b/src/proguard/optimize/info/SideEffectInstructionChecker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -27,7 +27,7 @@ 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;
+import proguard.classfile.visitor.*;
 
 /**
  * This class can tell whether an instruction has any side effects. Return
@@ -181,11 +181,15 @@ implements   InstructionVisitor,
                 Clazz  referencedClass  = refConstant.referencedClass;
                 Method referencedMethod = (Method)referencedMember;
 
-                // Check all other implementations of the method in the class
+                // Check all other implementations of the method down the class
                 // hierarchy.
-                referencedClass.methodImplementationsAccept(referencedMethod,
-                                                            false,
-                                                            this);
+                if ((referencedMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_PRIVATE) == 0)
+                {
+                    clazz.hierarchyAccept(false, false, false, true,
+                                          new NamedMethodVisitor(referencedMethod.getName(referencedClass),
+                                                                 referencedMethod.getDescriptor(referencedClass),
+                                          this));
+                }
             }
         }
     }
diff --git a/src/proguard/optimize/info/SideEffectMethodMarker.java b/src/proguard/optimize/info/SideEffectMethodMarker.java
index a7a2ad4..221c9df 100644
--- a/src/proguard/optimize/info/SideEffectMethodMarker.java
+++ b/src/proguard/optimize/info/SideEffectMethodMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/info/SingleImplementationMarker.java b/src/proguard/optimize/info/SingleImplementationMarker.java
deleted file mode 100644
index 87f6f14..0000000
--- a/src/proguard/optimize/info/SingleImplementationMarker.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- *             of Java bytecode.
- *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * 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.ClassVisitor;
-import proguard.optimize.KeepMarker;
-
-/**
- * This ClassVisitor investigates all classes that it visits to see whether
- * they have/are the sole (non-abstract) implementation of an interface.
- * It may already modify the access of the single implementing class to match
- * the access of the interface.
- *
- * @author Eric Lafortune
- */
-public class SingleImplementationMarker
-extends      SimplifiedVisitor
-implements   ClassVisitor
-{
-    private static final boolean DEBUG = false;
-
-
-    private final boolean      allowAccessModification;
-    private final ClassVisitor extraClassVisitor;
-
-
-    /**
-     * Creates a new SingleImplementationMarker.
-     * @param allowAccessModification indicates whether the access modifiers of
-     *                                a class can be changed in order to inline
-     *                                it.
-     */
-    public SingleImplementationMarker(boolean allowAccessModification)
-    {
-        this(allowAccessModification, null);
-    }
-
-
-    /**
-     * Creates a new SingleImplementationMarker.
-     * @param allowAccessModification indicates whether the access modifiers of
-     *                                a class can be changed in order to inline
-     *                                it.
-     * @param extraClassVisitor       an optional extra visitor for all inlinable
-     *                                interfaces.
-     */
-    public SingleImplementationMarker(boolean      allowAccessModification,
-                                      ClassVisitor extraClassVisitor)
-    {
-        this.allowAccessModification = allowAccessModification;
-        this.extraClassVisitor       = extraClassVisitor;
-    }
-
-
-    // Implementations for ClassVisitor.
-
-    public void visitProgramClass(ProgramClass programClass)
-    {
-        // The program class must be an interface class that cannot be
-        // implemented again.
-        if ((programClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE) == 0 ||
-            KeepMarker.isKept(programClass))
-        {
-            return;
-        }
-
-        // The interface class must have a single implementation.
-        Clazz[] subClasses = programClass.subClasses;
-        if (subClasses == null ||
-            subClasses.length != 1)
-        {
-            return;
-        }
-
-        // If the single implementation is an interface, check it recursively.
-        Clazz singleImplementationClass = subClasses[0];
-        int singleImplementationAccessFlags = singleImplementationClass.getAccessFlags();
-        if ((singleImplementationAccessFlags & ClassConstants.INTERNAL_ACC_INTERFACE) != 0)
-        {
-            singleImplementationClass.accept(this);
-
-            // See if the subinterface has a single implementation.
-            singleImplementationClass = singleImplementation(singleImplementationClass);
-            if (singleImplementationClass == null)
-            {
-                return;
-            }
-
-            singleImplementationAccessFlags = singleImplementationClass.getAccessFlags();
-        }
-
-        // The single implementation must contain all non-static methods of this
-        // interface, so invocations can easily be diverted.
-        for (int index = 0; index < programClass.u2methodsCount; index++)
-        {
-            Method method = programClass.methods[index];
-            if ((method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) == 0 &&
-                singleImplementationClass.findMethod(method.getName(programClass),
-                                                     method.getDescriptor(programClass)) == null)
-            {
-                return;
-            }
-        }
-
-        // Doesn't the implementation have at least the same access as the
-        // interface?
-        if (AccessUtil.accessLevel(singleImplementationAccessFlags) <
-            AccessUtil.accessLevel(programClass.getAccessFlags()))
-        {
-            // Are we allowed to fix the access?
-            if (allowAccessModification)
-            {
-                // Fix the access.
-                ((ProgramClass)singleImplementationClass).u2accessFlags =
-                    AccessUtil.replaceAccessFlags(singleImplementationAccessFlags,
-                                                  programClass.getAccessFlags());
-            }
-            else
-            {
-                // We can't give the implementation the access of the interface.
-                // Forget about inlining it after all.
-                return;
-            }
-        }
-
-        if (DEBUG)
-        {
-            System.out.println("Single implementation of ["+programClass.getName()+"]: ["+singleImplementationClass.getName()+"]");
-        }
-
-        // Mark the interface and its single implementation.
-        markSingleImplementation(programClass, singleImplementationClass);
-
-        // Visit the interface, if required.
-        if (extraClassVisitor != null)
-        {
-            singleImplementationClass.accept(extraClassVisitor);
-        }
-    }
-
-
-    // Small utility methods.
-
-    public static void markSingleImplementation(VisitorAccepter visitorAccepter,
-                                                Clazz           singleImplementation)
-    {
-        // The interface has a single implementation.
-        visitorAccepter.setVisitorInfo(singleImplementation);
-    }
-
-
-    public static Clazz singleImplementation(VisitorAccepter visitorAccepter)
-    {
-        return visitorAccepter != null &&
-               visitorAccepter.getVisitorInfo() instanceof Clazz ?
-                   (Clazz)visitorAccepter.getVisitorInfo() :
-                   null;
-    }
-}
diff --git a/src/proguard/optimize/info/SuperInvocationMarker.java b/src/proguard/optimize/info/SuperInvocationMarker.java
index ba5e07c..2125f68 100644
--- a/src/proguard/optimize/info/SuperInvocationMarker.java
+++ b/src/proguard/optimize/info/SuperInvocationMarker.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/optimize/info/VariableUsageMarker.java b/src/proguard/optimize/info/VariableUsageMarker.java
index 8c9b214..db0e206 100644
--- a/src/proguard/optimize/info/VariableUsageMarker.java
+++ b/src/proguard/optimize/info/VariableUsageMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/BranchTargetFinder.java b/src/proguard/optimize/peephole/BranchTargetFinder.java
index 80f9149..5279b49 100644
--- a/src/proguard/optimize/peephole/BranchTargetFinder.java
+++ b/src/proguard/optimize/peephole/BranchTargetFinder.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -73,7 +73,7 @@ implements   AttributeVisitor,
 
     private int     currentSubroutineStart;
     private int     currentSubroutineEnd;
-    private final int[]   recentCreationOffsets = new int[MAXIMUM_CREATION_OFFSETS];
+    private int[]   recentCreationOffsets = new int[MAXIMUM_CREATION_OFFSETS];
     private int     recentCreationOffsetIndex;
     private boolean isInitializer;
 
@@ -337,6 +337,7 @@ implements   AttributeVisitor,
 
         superInitializationOffset = NONE;
 
+        // We're assuming all subroutines are contiguous blocks of code.
         // We're not starting in a subroutine.
         currentSubroutineStart = NONE;
         currentSubroutineEnd   = NONE;
@@ -426,14 +427,16 @@ implements   AttributeVisitor,
                 {
                     System.out.println("" +
                                        (isBranchOrigin(index)         ? 'B' : '-') +
+                                       (isAfterBranch(index)          ? 'b' : '-') +
                                        (isBranchTarget(index)         ? 'T' : '-') +
                                        (isExceptionStart(index)       ? 'E' : '-') +
-                                       (isExceptionEnd(index)         ? 'E' : '-') +
+                                       (isExceptionEnd(index)         ? 'e' : '-') +
                                        (isExceptionHandler(index)     ? 'H' : '-') +
                                        (isSubroutineInvocation(index) ? 'J' : '-') +
                                        (isSubroutineStart(index)      ? 'S' : '-') +
                                        (isSubroutineReturning(index)  ? 'r' : '-') +
-                                       (isSubroutine(index)           ? " ["+subroutineStart(index)+" -> "+subroutineEnd(index)+"] " : " ") +
+                                       (isSubroutine(index)           ? " ["+subroutineStart(index)+" -> "+subroutineEnd(index)+"]" : "") +
+                                       (isNew(index)                  ? " ["+initializationOffset(index)+"] " : " ---- ") +
                                        InstructionFactory.create(codeAttribute.code, index).toString(index));
                 }
             }
diff --git a/src/proguard/optimize/peephole/ClassFinalizer.java b/src/proguard/optimize/peephole/ClassFinalizer.java
index 3f41efb..00654ee 100644
--- a/src/proguard/optimize/peephole/ClassFinalizer.java
+++ b/src/proguard/optimize/peephole/ClassFinalizer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2003 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/ClassMerger.java b/src/proguard/optimize/peephole/ClassMerger.java
new file mode 100644
index 0000000..edd95ec
--- /dev/null
+++ b/src/proguard/optimize/peephole/ClassMerger.java
@@ -0,0 +1,541 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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.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 TargetClassChanger
+ * @see ClassReferenceFixer
+ * @author Eric Lafortune
+ */
+public class ClassMerger
+extends      SimplifiedVisitor
+implements   ClassVisitor,
+             ConstantVisitor
+{
+    //*
+    private static final boolean DEBUG = false;
+    /*/
+    private static       boolean DEBUG = true;
+    //*/
+
+
+    private final ProgramClass targetClass;
+    private final boolean      allowAccessModification;
+    private final boolean      mergeInterfacesAggressively;
+    private final ClassVisitor extraClassVisitor;
+
+
+    /**
+     * 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.INTERNAL_ACC_ANNOTATTION) == 0 &&
+
+            // Only merge classes if we can change the access permissioms, 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.INTERNAL_ACC_PUBLIC) != 0 &&
+              !PackageVisibleMemberContainingClassMarker.containsPackageVisibleMembers(programClass) &&
+              !PackageVisibleMemberInvokingClassMarker.invokesPackageVisibleMembers(programClass)) ||
+             ClassUtil.internalPackageName(programClass.getName()).equals(
+             ClassUtil.internalPackageName(targetClass.getName()))) &&
+
+            // Only merge two classes or two interfaces or two abstract classes,
+            // or a class into an interface with a single implementation.
+            ((programClass.getAccessFlags() &
+              (ClassConstants.INTERNAL_ACC_INTERFACE |
+               ClassConstants.INTERNAL_ACC_ABSTRACT)) ==
+             (targetClass.getAccessFlags()  &
+              (ClassConstants.INTERNAL_ACC_INTERFACE |
+               ClassConstants.INTERNAL_ACC_ABSTRACT)) ||
+             (isOnlySubClass(programClass, targetClass) &&
+              (programClass.getSuperClass().equals(targetClass) ||
+               programClass.getSuperClass().equals(targetClass.getSuperClass())))) &&
+
+            // One class must not implement the other class indirectly.
+            !indirectlyImplementedInterfaces(programClass).contains(targetClass) &&
+            !targetClass.extendsOrImplements(programClass) &&
+
+            // The two classes must have the same superclasses and interfaces
+            // with static initializers.
+            initializedSuperClasses(programClass).equals(initializedSuperClasses(targetClass))   &&
+
+            // The two classes must have the same superclasses and interfaces
+            // that are tested with 'instanceof'.
+            instanceofedSuperClasses(programClass).equals(instanceofedSuperClasses(targetClass)) &&
+
+            // The two classes must not both be part of a .class construct.
+            !(DotClassMarker.isDotClassed(programClass) &&
+              DotClassMarker.isDotClassed(targetClass)) &&
+
+            // The two classes must not introduce any unwanted fields.
+            !introducesUnwantedFields(programClass, targetClass) &&
+            !introducesUnwantedFields(targetClass, programClass) &&
+
+            // The classes must not have clashing constructors.
+            !haveAnyIdenticalInitializers(programClass, targetClass) &&
+
+            // The classes must not introduce abstract methods, unless
+            // explicitly allowed.
+            (mergeInterfacesAggressively ||
+             (!introducesUnwantedAbstractMethods(programClass, targetClass) &&
+              !introducesUnwantedAbstractMethods(targetClass, programClass))) &&
+
+            // The classes must not override each others concrete methods.
+            !overridesAnyMethods(programClass, targetClass) &&
+            !overridesAnyMethods(targetClass, programClass) &&
+
+            // The classes must not shadow each others non-private methods.
+            !shadowsAnyMethods(programClass, targetClass) &&
+            !shadowsAnyMethods(targetClass, programClass))
+        {
+            if (DEBUG)
+            {
+                System.out.println("ClassMerger ["+programClass.getName()+"] -> ["+targetClass.getName()+"]");
+                System.out.println("  Source interface? ["+((programClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE)!=0)+"]");
+                System.out.println("  Target interface? ["+((targetClass.getAccessFlags() & ClassConstants.INTERNAL_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()+"]");
+            }
+
+            // Combine the access flags.
+            int targetAccessFlags = targetClass.getAccessFlags();
+            int sourceAccessFlags = programClass.getAccessFlags();
+
+            targetClass.u2accessFlags =
+                ((targetAccessFlags &
+                  sourceAccessFlags) &
+                 (ClassConstants.INTERNAL_ACC_INTERFACE  |
+                  ClassConstants.INTERNAL_ACC_ABSTRACT)) |
+                ((targetAccessFlags |
+                  sourceAccessFlags) &
+                 (ClassConstants.INTERNAL_ACC_PUBLIC     |
+                  ClassConstants.INTERNAL_ACC_ANNOTATTION |
+                  ClassConstants.INTERNAL_ACC_ENUM));
+
+            // Copy over the superclass, unless it's the target class itself.
+            //if (!targetClass.getName().equals(programClass.getSuperName()))
+            //{
+            //    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.
+            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);
+
+            programClass.fieldsAccept(memberAdder);
+            programClass.methodsAccept(memberAdder);
+
+//            // Delete any inner classes and enclosing method attributes in
+//            // both classes.
+//            programClass.attributesAccept(
+//                new AttributeNameFilter(new FixedStringMatcher(ClassConstants.ATTR_InnerClasses),
+//                new ReferencedClassVisitor(
+//                new NamedAttributeDeleter())));
+//            AttributesEditor attributesEditor =
+//                new AttributesEditor(programClass, false);
+//            attributesEditor.deleteAttribute(ClassConstants.ATTR_InnerClasses);
+//            attributesEditor.deleteAttribute(ClassConstants.ATTR_EnclosingMethod);
+//
+//            attributesEditor =
+//                new AttributesEditor((ProgramClass)targetClass, false);
+//            attributesEditor.deleteAttribute(ClassConstants.ATTR_InnerClasses);
+//            attributesEditor.deleteAttribute(ClassConstants.ATTR_EnclosingMethod);
+
+            // Copy over the other attributes.
+            programClass.attributesAccept(
+                new AttributeAdder(targetClass, true));
+
+            // Update the optimization information of the target class.
+            if (InstantiationClassMarker.isInstantiated(programClass))
+            {
+                InstantiationClassMarker.setInstantiated(targetClass);
+            }
+
+            if (InstanceofClassMarker.isInstanceofed(programClass))
+            {
+                InstanceofClassMarker.setInstanceofed(targetClass);
+            }
+
+            if (DotClassMarker.isDotClassed(programClass))
+            {
+                DotClassMarker.setDotClassed(targetClass);
+            }
+
+            // Remember to replace the inlined class by the target class.
+            setTargetClass(programClass, targetClass);
+
+            // Visit the merged class, if required.
+            if (extraClassVisitor != null)
+            {
+                extraClassVisitor.visitProgramClass(programClass);
+            }
+        }
+    }
+
+
+    // 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 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 NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
+                                                     ClassConstants.INTERNAL_METHOD_TYPE_INIT,
+                              new MemberToClassVisitor(
+                              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 whether the given class would introduce any unwanted fields
+     * in the target class.
+     */
+    private boolean introducesUnwantedFields(ProgramClass programClass,
+                                             ProgramClass targetClass)
+    {
+        // The class must not have any fields, or it must not be instantiated,
+        // without any other subclasses.
+        return
+            programClass.u2fieldsCount != 0 &&
+            (InstantiationClassMarker.isInstantiated(targetClass) ||
+             (targetClass.subClasses != null &&
+              !isOnlySubClass(programClass, targetClass)));
+    }
+
+
+    /**
+     * Returns whether the two given classes have initializers with the same
+     * descriptors.
+     */
+    private boolean haveAnyIdenticalInitializers(Clazz clazz, Clazz targetClass)
+    {
+        MemberCounter counter = new MemberCounter();
+
+        // TODO: Currently checking shared methods, not just initializers.
+        // Visit all methods, counting the ones that are also present in the
+        // target class.
+        clazz.methodsAccept(//new MemberNameFilter(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_INIT),
+                            new SimilarMemberVisitor(targetClass, true, false, false, false,
+                            new MemberAccessFilter(0, ClassConstants.INTERNAL_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.INTERNAL_ACC_ABSTRACT |
+              ClassConstants.INTERNAL_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.INTERNAL_ACC_ABSTRACT, 0,
+                            new MultiMemberVisitor(new MemberVisitor[]
+                            {
+                                counter,
+                                new SimilarMemberVisitor(targetClass, true, true, true, false,
+                                                         new MemberAccessFilter(ClassConstants.INTERNAL_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.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC | ClassConstants.INTERNAL_ACC_ABSTRACT,
+                            new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_CLINIT)),
+                            new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_INIT)),
+                            new SimilarMemberVisitor(targetClass, true, true, false, false,
+                            new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC | ClassConstants.INTERNAL_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 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.INTERNAL_ACC_PRIVATE, 0,
+                              new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_INIT)),
+                              new SimilarMemberVisitor(targetClass, true, true, true, false,
+                              new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
+                              counter))))));
+
+        // 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.INTERNAL_ACC_STATIC, 0,
+                              new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_CLINIT)),
+                              new SimilarMemberVisitor(targetClass, true, true, true, false,
+                              new MemberAccessFilter(0, ClassConstants.INTERNAL_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;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java b/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
index d699c4e..3b367c0 100644
--- a/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
+++ b/src/proguard/optimize/peephole/GotoCommonCodeReplacer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/GotoGotoReplacer.java b/src/proguard/optimize/peephole/GotoGotoReplacer.java
index d2de2d0..4e9f8ed 100644
--- a/src/proguard/optimize/peephole/GotoGotoReplacer.java
+++ b/src/proguard/optimize/peephole/GotoGotoReplacer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/GotoReturnReplacer.java b/src/proguard/optimize/peephole/GotoReturnReplacer.java
index cdae3e8..71d59a7 100644
--- a/src/proguard/optimize/peephole/GotoReturnReplacer.java
+++ b/src/proguard/optimize/peephole/GotoReturnReplacer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/HorizontalClassMerger.java b/src/proguard/optimize/peephole/HorizontalClassMerger.java
new file mode 100644
index 0000000..b1c52cb
--- /dev/null
+++ b/src/proguard/optimize/peephole/HorizontalClassMerger.java
@@ -0,0 +1,90 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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.*;
+
+/**
+ * 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 ProgramClassFilter(
+                                              new ClassMerger(programClass,
+                                                              allowAccessModification,
+                                                              mergeInterfacesAggressively,
+                                                              extraClassVisitor)))));
+    }
+}
\ No newline at end of file
diff --git a/src/proguard/optimize/peephole/InstructionSequenceConstants.java b/src/proguard/optimize/peephole/InstructionSequenceConstants.java
index b8705fa..70dbf99 100644
--- a/src/proguard/optimize/peephole/InstructionSequenceConstants.java
+++ b/src/proguard/optimize/peephole/InstructionSequenceConstants.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -1087,6 +1087,7 @@ public class InstructionSequenceConstants
                 // Nothing.
             },
         },
+        // Not valid for negative values.
 //        {   // ... / 2 = ... >> 1
 //            {
 //                new SimpleInstruction(InstructionConstants.OP_ICONST_2),
@@ -1256,6 +1257,7 @@ public class InstructionSequenceConstants
                 // Nothing.
             },
         },
+        // Not valid for negative values.
 //        {   // ... / 2L = ... >> 1
 //            {
 //                new ConstantInstruction(InstructionConstants.OP_LDC2_W, L_2),
@@ -2315,6 +2317,14 @@ public class InstructionSequenceConstants
                 // 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[...]
 //            {
@@ -2499,6 +2509,38 @@ public class InstructionSequenceConstants
                 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) = aload/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),
@@ -2507,6 +2549,38 @@ public class InstructionSequenceConstants
                 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) = iload/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) = iload/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),
@@ -2515,6 +2589,38 @@ public class InstructionSequenceConstants
                 new BranchInstruction(InstructionConstants.OP_IFLT, 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 (0 > i) = iload/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 (0 > i) = iload/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 (... >= 0) = ifge
             {
                 new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -2523,6 +2629,38 @@ public class InstructionSequenceConstants
                 new BranchInstruction(InstructionConstants.OP_IFGE, 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 (0 <= i) = iload/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 (0 <= i) = iload/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 (... > 0) = ifgt
             {
                 new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -2531,6 +2669,38 @@ public class InstructionSequenceConstants
                 new BranchInstruction(InstructionConstants.OP_IFGT, 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 (0 < i) = iload/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 (0 < i) = iload/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 (... <= 0) = ifle
             {
                 new SimpleInstruction(InstructionConstants.OP_ICONST_0),
@@ -2539,6 +2709,38 @@ public class InstructionSequenceConstants
                 new BranchInstruction(InstructionConstants.OP_IFLE, 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 (0 >= i) = iload/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 (0 >= i) = iload/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 (... == null) = ifnull
             {
                 new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
@@ -2547,6 +2749,38 @@ public class InstructionSequenceConstants
                 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) = aload/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) = aload/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),
@@ -2555,6 +2789,38 @@ public class InstructionSequenceConstants
                 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) = aload/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) = aload/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),
diff --git a/src/proguard/optimize/peephole/InstructionSequenceReplacer.java b/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
index f69d4c9..eae441e 100644
--- a/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
+++ b/src/proguard/optimize/peephole/InstructionSequenceReplacer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/InstructionSequencesReplacer.java b/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
index d68d914..6aab0a4 100644
--- a/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
+++ b/src/proguard/optimize/peephole/InstructionSequencesReplacer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/LoadStoreRemover.java b/src/proguard/optimize/peephole/LoadStoreRemover.java
index e9286cb..e1d5d69 100644
--- a/src/proguard/optimize/peephole/LoadStoreRemover.java
+++ b/src/proguard/optimize/peephole/LoadStoreRemover.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/MemberPrivatizer.java b/src/proguard/optimize/peephole/MemberPrivatizer.java
index 5d4db27..ac2185c 100644
--- a/src/proguard/optimize/peephole/MemberPrivatizer.java
+++ b/src/proguard/optimize/peephole/MemberPrivatizer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/MethodInliner.java b/src/proguard/optimize/peephole/MethodInliner.java
index f116f40..ebb588c 100644
--- a/src/proguard/optimize/peephole/MethodInliner.java
+++ b/src/proguard/optimize/peephole/MethodInliner.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
@@ -44,7 +44,6 @@ public class MethodInliner
 extends      SimplifiedVisitor
 implements   AttributeVisitor,
              InstructionVisitor,
-             ExceptionInfoVisitor,
              ConstantVisitor,
              MemberVisitor
 {
@@ -69,19 +68,20 @@ implements   AttributeVisitor,
     private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
     private final AccessMethodMarker    accessMethodMarker    = new AccessMethodMarker();
     private final CatchExceptionMarker  catchExceptionMarker  = new CatchExceptionMarker();
-    private final ConstantAdder         constantAdder         = new ConstantAdder();
     private final StackSizeComputer     stackSizeComputer     = new StackSizeComputer();
 
-    private ProgramClass  targetClass;
-    private ProgramMethod targetMethod;
-    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 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;
 
 
     /**
@@ -146,20 +146,21 @@ implements   AttributeVisitor,
 
             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.INTERNAL_METHOD_NAME_INIT) ? 1 : 0;
             inlinedAny                   = false;
             codeAttributeComposer.reset();
-            constantAdder.setTargetClass(targetClass);
             stackSizeComputer.visitCodeAttribute(clazz, method, codeAttribute);
 
             // Append the body of the code.
             copyCode(clazz, method, codeAttribute);
 
-            targetClass  = null;
-            targetMethod = null;
-            constantAdder.setTargetClass(null);
+            targetClass   = null;
+            targetMethod  = null;
+            constantAdder = null;
 
             // Update the code attribute if any code has been inlined.
             if (inlinedAny)
@@ -213,7 +214,6 @@ implements   AttributeVisitor,
      */
     private void storeParameters(Clazz clazz, Method method)
     {
-
         String descriptor = method.getDescriptor(clazz);
 
         boolean isStatic =
@@ -307,7 +307,7 @@ implements   AttributeVisitor,
         codeAttribute.instructionsAccept(clazz, method, this);
 
         // Copy the exceptions.
-        codeAttribute.exceptionsAccept(clazz, method, this);
+        codeAttribute.exceptionsAccept(clazz, method, exceptionInfoAdder);
 
         // Append a label just after the code.
         codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
@@ -427,39 +427,14 @@ implements   AttributeVisitor,
         {
             // Make sure the constant is present in the constant pool of the
             // target class.
-            clazz.constantPoolEntryAccept(constantInstruction.constantIndex, constantAdder);
-
-            // Let the instruction point to this constant.
-            constantInstruction.constantIndex = constantAdder.getConstantIndex();
+            constantInstruction.constantIndex =
+                constantAdder.addConstant(clazz, constantInstruction.constantIndex);
         }
 
         codeAttributeComposer.appendInstruction(offset, constantInstruction.shrink());
     }
 
 
-    // Implementations for ExceptionInfoVisitor.
-
-    public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
-    {
-        int catchType = exceptionInfo.u2catchType;
-
-        if (inlining && catchType != 0)
-        {
-            // Make sure the constant is present in the constant pool of the
-            // target class.
-            clazz.constantPoolEntryAccept(catchType, constantAdder);
-
-            // Let the exception point to this constant.
-            catchType = constantAdder.getConstantIndex();
-        }
-
-        codeAttributeComposer.appendException(new ExceptionInfo(exceptionInfo.u2startPC,
-                                                                exceptionInfo.u2endPC,
-                                                                exceptionInfo.u2handlerPC,
-                                                                catchType));
-    }
-
-
     // Implementations for ConstantVisitor.
 
     public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant) {}
diff --git a/src/proguard/optimize/peephole/NopRemover.java b/src/proguard/optimize/peephole/NopRemover.java
index 0beebc8..7d5b12d 100644
--- a/src/proguard/optimize/peephole/NopRemover.java
+++ b/src/proguard/optimize/peephole/NopRemover.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/PeepholeOptimizer.java b/src/proguard/optimize/peephole/PeepholeOptimizer.java
index 968a69a..9580862 100644
--- a/src/proguard/optimize/peephole/PeepholeOptimizer.java
+++ b/src/proguard/optimize/peephole/PeepholeOptimizer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/PushPopRemover.java b/src/proguard/optimize/peephole/PushPopRemover.java
index a5e454d..b3d322a 100644
--- a/src/proguard/optimize/peephole/PushPopRemover.java
+++ b/src/proguard/optimize/peephole/PushPopRemover.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/ReachableCodeMarker.java b/src/proguard/optimize/peephole/ReachableCodeMarker.java
index ad66b3f..d9d9048 100644
--- a/src/proguard/optimize/peephole/ReachableCodeMarker.java
+++ b/src/proguard/optimize/peephole/ReachableCodeMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java b/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java
new file mode 100644
index 0000000..efb9551
--- /dev/null
+++ b/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java
@@ -0,0 +1,140 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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;
+
+/**
+ * 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.
+        for (int index = newAtributesCount; index < attributesCount; index++)
+        {
+            attributes[index] = null;
+        }
+
+        // Update the number of attribuets.
+        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);
+
+        // Check whether the referenced classes are retargeted.
+        innerClassesAttribute.innerClassEntriesAccept(clazz, this);
+    }
+
+
+    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/src/proguard/optimize/peephole/SingleImplementationFixer.java b/src/proguard/optimize/peephole/SingleImplementationFixer.java
deleted file mode 100644
index 680f290..0000000
--- a/src/proguard/optimize/peephole/SingleImplementationFixer.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- *             of Java bytecode.
- *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * 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.constant.visitor.ConstantVisitor;
-import proguard.classfile.editor.*;
-import proguard.classfile.util.SimplifiedVisitor;
-import proguard.classfile.visitor.ClassVisitor;
-import proguard.optimize.info.SingleImplementationMarker;
-
-/**
- * This ClassVisitor cleans up after the SingleImplementationInliner.
- * It fixes the names of interfaces that have single implementations, lets
- * the implementations and fields references point to them again. This is
- * necessary after the SingleImplementationInliner has overzealously renamed
- * the interfaces to the single implementations, let the single implementations
- * point to themselves as interfaces, and let the field references point to the
- * single implementations.
- *
- * @see SingleImplementationInliner
- * @see ClassReferenceFixer
- * @author Eric Lafortune
- */
-public class SingleImplementationFixer
-extends      SimplifiedVisitor
-implements   ClassVisitor,
-             ConstantVisitor
-{
-    private final ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor();
-
-
-    // Implementations for ClassVisitor.
-
-    public void visitProgramClass(ProgramClass programClass)
-    {
-        // Is this an interface with a single implementation?
-        Clazz singleImplementationClass =
-            SingleImplementationMarker.singleImplementation(programClass);
-
-        if (singleImplementationClass != null)
-        {
-            // Fix the reference to its own name.
-            fixThisClassReference(programClass);
-
-            // Fix the reference from its single interface or implementation.
-            fixInterfaceReference((ProgramClass)programClass.subClasses[0],
-                                  programClass);
-        }
-
-        // Fix the field references in the constant pool.
-        programClass.constantPoolEntriesAccept(this);
-    }
-
-
-    // Implementations for ConstantVisitor.
-
-    public void visitAnyConstant(Clazz clazz, Constant constant) {}
-
-
-    public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
-    {
-        // Update the referenced class if it is an interface with a single
-        // implementation.
-        Clazz singleImplementationClass =
-            SingleImplementationMarker.singleImplementation(fieldrefConstant.referencedClass);
-
-        if (singleImplementationClass != null)
-        {
-            // Fix the reference to the interface.
-            fixFieldrefClassReference((ProgramClass)clazz,
-                                      fieldrefConstant);
-        }
-    }
-
-
-    // Small utility methods.
-
-    /**
-     * Fixes the given class, so its name points to itself again.
-     */
-    private void fixThisClassReference(ProgramClass programClass)
-    {
-        // 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.
-        int nameIndex =
-            constantPoolEditor.addUtf8Constant(programClass,
-                                               programClass.getName());
-        programClass.u2thisClass =
-            constantPoolEditor.addConstant(programClass,
-                                           new ClassConstant(nameIndex,
-                                                             programClass));
-    }
-
-
-    /**
-     * Fixes the given class, so it points to the given interface again.
-     */
-    private void fixInterfaceReference(ProgramClass programClass,
-                                       ProgramClass interfaceClass)
-    {
-        // Make sure the class refers to the given interface again.
-        String interfaceName = interfaceClass.getName();
-
-        int interfacesCount = programClass.u2interfacesCount;
-        for (int index = 0; index < interfacesCount; index++)
-        {
-            if (interfaceName.equals(programClass.getInterfaceName(index)))
-            {
-                // Update the class index.
-                // 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.
-                int nameIndex =
-                    constantPoolEditor.addUtf8Constant(programClass,
-                                                       interfaceName);
-                programClass.u2interfaces[index]       =
-                    constantPoolEditor.addConstant(programClass,
-                                                   new ClassConstant(nameIndex,
-                                                                     interfaceClass));
-                break;
-
-            }
-        }
-    }
-
-
-    /**
-     * Fixes the given field reference, so its class index points to its
-     * class again. Note that this could be a different class than the one
-     * in the original class.
-     */
-    private void fixFieldrefClassReference(ProgramClass     programClass,
-                                           FieldrefConstant fieldrefConstant)
-    {
-        Clazz referencedClass = fieldrefConstant.referencedClass;
-
-        // 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.
-        int nameIndex =
-            constantPoolEditor.addUtf8Constant(programClass,
-                                               fieldrefConstant.getClassName(programClass));
-        fieldrefConstant.u2classIndex =
-            constantPoolEditor.addConstant(programClass,
-                                           new ClassConstant(nameIndex,
-                                                             referencedClass));
-    }
-}
diff --git a/src/proguard/optimize/peephole/SingleImplementationInliner.java b/src/proguard/optimize/peephole/SingleImplementationInliner.java
deleted file mode 100644
index 3e05a3d..0000000
--- a/src/proguard/optimize/peephole/SingleImplementationInliner.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- *             of Java bytecode.
- *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * 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.ClassReferenceFixer;
-import proguard.classfile.util.SimplifiedVisitor;
-import proguard.classfile.visitor.*;
-import proguard.optimize.info.SingleImplementationMarker;
-
-/**
- * This ClassVisitor replaces all references to interfaces that have single
- * implementations by references to those implementations. The names will then
- * have to be fixed, based on the new references.
- *
- * @see SingleImplementationMarker
- * @see SingleImplementationFixer
- * @see ClassReferenceFixer
- * @author Eric Lafortune
- */
-public class SingleImplementationInliner
-extends      SimplifiedVisitor
-implements   ClassVisitor,
-             ConstantVisitor,
-             MemberVisitor,
-             AttributeVisitor,
-             LocalVariableInfoVisitor,
-             LocalVariableTypeInfoVisitor,
-             AnnotationVisitor,
-             ElementValueVisitor
-{
-    // Implementations for ClassVisitor.
-
-    public void visitProgramClass(ProgramClass programClass)
-    {
-        // Update the constant pool.
-        programClass.constantPoolEntriesAccept(this);
-
-        // Update the class members.
-        programClass.fieldsAccept(this);
-        programClass.methodsAccept(this);
-
-        // Update the attributes.
-        programClass.attributesAccept(this);
-    }
-
-
-    // Implementations for ConstantVisitor.
-
-    public void visitAnyConstant(Clazz clazz, Constant constant) {}
-
-
-    public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
-    {
-        if (stringConstant.referencedMember == null)
-        {
-            // Update the referenced class if it is an interface with a single
-            // implementation.
-            Clazz singleImplementationClass =
-                SingleImplementationMarker.singleImplementation(stringConstant.referencedClass);
-
-            if (singleImplementationClass != null)
-            {
-                stringConstant.referencedClass = singleImplementationClass;
-            }
-        }
-    }
-
-
-    public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
-    {
-        // Update the referenced interface if it has a single implementation.
-        Clazz singleImplementationClass =
-            SingleImplementationMarker.singleImplementation(interfaceMethodrefConstant.referencedClass);
-
-        if (singleImplementationClass != null)
-        {
-            // We know the single implementation contains the method.
-            String name = interfaceMethodrefConstant.getName(clazz);
-            String type = interfaceMethodrefConstant.getType(clazz);
-
-            interfaceMethodrefConstant.referencedClass  = singleImplementationClass;
-            interfaceMethodrefConstant.referencedMember = singleImplementationClass.findMethod(name, type);
-        }
-    }
-
-
-    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
-    {
-        // Update the referenced class if it is an interface with a single
-        // implementation.
-        Clazz singleImplementationClass =
-            SingleImplementationMarker.singleImplementation(classConstant.referencedClass);
-
-        if (singleImplementationClass != null)
-        {
-            classConstant.referencedClass = singleImplementationClass;
-        }
-    }
-
-
-    // Implementations for MemberVisitor.
-
-    public void visitProgramField(ProgramClass programClass, ProgramField programField)
-    {
-        // Update the referenced class if the type is an interface with a
-        // single implementation.
-        Clazz singleImplementationClass =
-            SingleImplementationMarker.singleImplementation(programField.referencedClass);
-
-        if (singleImplementationClass != null)
-        {
-            programField.referencedClass = singleImplementationClass;
-        }
-
-        // Update the attributes.
-        programField.attributesAccept(programClass, this);
-    }
-
-
-    public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
-    {
-        // Update the referenced classes if the descriptor contains
-        // interfaces with single implementations.
-        updateReferencedClasses(programMethod.referencedClasses);
-
-        // Update the attributes.
-        programMethod.attributesAccept(programClass, this);
-    }
-
-
-    // Implementations for AttributeVisitor.
-
-    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
-
-
-    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
-    {
-        // Update the referenced classes of the local variables.
-        codeAttribute.attributesAccept(clazz, method, this);
-    }
-
-
-    public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
-    {
-        // Update the referenced classes of the local variables.
-        localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-    }
-
-
-    public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
-    {
-        // Update the referenced classes of the local variable types.
-        localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-    }
-
-
-    public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
-    {
-        // Update the referenced classes.
-        updateReferencedClasses(signatureAttribute.referencedClasses);
-    }
-
-
-    public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
-    {
-        // Update the annotations.
-        annotationsAttribute.annotationsAccept(clazz, this);
-    }
-
-
-    public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
-    {
-        // Update the annotations.
-        parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
-    }
-
-
-    public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
-    {
-        // Update the annotation.
-        annotationDefaultAttribute.defaultValueAccept(clazz, this);
-    }
-
-
-    // Implementations for LocalVariableInfoVisitor.
-
-    public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
-    {
-        // Update the referenced class if it is an interface with a single
-        // implementation.
-        Clazz singleImplementationClass =
-            SingleImplementationMarker.singleImplementation(localVariableInfo.referencedClass);
-
-        if (singleImplementationClass != null)
-        {
-            localVariableInfo.referencedClass = singleImplementationClass;
-        }
-    }
-
-
-    // Implementations for LocalVariableTypeInfoVisitor.
-
-    public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
-    {
-        // Update the referenced classes.
-        updateReferencedClasses(localVariableTypeInfo.referencedClasses);
-    }
-
-
-    // Implementations for AnnotationVisitor.
-
-    public void visitAnnotation(Clazz clazz, Annotation annotation)
-    {
-        // Update the referenced classes.
-        updateReferencedClasses(annotation.referencedClasses);
-
-        // Update 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)
-    {
-        // Update the referenced classes.
-        updateReferencedClasses(enumConstantElementValue.referencedClasses);
-    }
-
-
-    public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
-    {
-        // Update the referenced classes.
-        updateReferencedClasses(classElementValue.referencedClasses);
-    }
-
-
-    public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
-    {
-        // Update the annotation.
-        annotationElementValue.annotationAccept(clazz, this);
-    }
-
-
-    public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
-    {
-        // Update the element values.
-        arrayElementValue.elementValuesAccept(clazz, annotation, this);
-    }
-
-
-    // Small utility methods.
-
-    /**
-     * Updates the given array of referenced classes, replacing references
-     * to a interfaces with single implementations by these implementations.
-     */
-    private void updateReferencedClasses(Clazz[] referencedClasses)
-    {
-        // Update all referenced classes.
-        if (referencedClasses != null)
-        {
-            for (int index = 0; index < referencedClasses.length; index++)
-            {
-                // See if we have is an interface with a single implementation.
-                Clazz singleImplementationClass =
-                    SingleImplementationMarker.singleImplementation(referencedClasses[index]);
-
-                // Update or copy the referenced class.
-                if (singleImplementationClass != null)
-                {
-                    referencedClasses[index] = singleImplementationClass;
-                }
-            }
-        }
-    }
-}
diff --git a/src/proguard/optimize/peephole/StoreLoadReplacer.java b/src/proguard/optimize/peephole/StoreLoadReplacer.java
index 4b96fe6..9cf58d6 100644
--- a/src/proguard/optimize/peephole/StoreLoadReplacer.java
+++ b/src/proguard/optimize/peephole/StoreLoadReplacer.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/TargetClassChanger.java b/src/proguard/optimize/peephole/TargetClassChanger.java
new file mode 100644
index 0000000..7d590c5
--- /dev/null
+++ b/src/proguard/optimize/peephole/TargetClassChanger.java
@@ -0,0 +1,439 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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.*;
+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 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
+{
+    // Implementations for ClassVisitor.
+
+    public void visitProgramClass(ProgramClass programClass)
+    {
+        Clazz   superClass       = null;
+        Clazz[] interfaceClasses = null;
+
+        // 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);
+
+        // Is the class itself being retargeted?
+        Clazz targetClass = ClassMerger.getTargetClass(programClass);
+        if (targetClass != null)
+        {
+            // 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 loose all its subclasses.
+            programClass.subClasses = null;
+        }
+
+        // Remove interface classes that are pointing to this class.
+        int newInterfacesCount = 0;
+        for (int index = 0; index < programClass.u2interfacesCount; index++)
+        {
+            Clazz interfaceClass = programClass.getInterface(index);
+            if (!programClass.equals(interfaceClass))
+            {
+                programClass.u2interfaces[newInterfacesCount++] =
+                    programClass.u2interfaces[index];
+            }
+        }
+        programClass.u2interfacesCount = newInterfacesCount;
+
+        // Update the subclasses of the superclass and interfaces of the
+        // target class.
+        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 visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+    {
+        Clazz referencedClass    = refConstant.referencedClass;
+        Clazz newReferencedClass = updateReferencedClass(referencedClass);
+        if (referencedClass != newReferencedClass)
+        {
+            // Change the referenced class.
+            refConstant.referencedClass  = newReferencedClass;
+
+            // Change the referenced class member.
+            refConstant.referencedMember =
+                updateReferencedMember(refConstant.referencedMember,
+                                       refConstant.getName(clazz),
+                                       refConstant.getType(clazz),
+                                       newReferencedClass);
+        }
+    }
+
+
+    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+    {
+        // Change the referenced class.
+        classConstant.referencedClass =
+            updateReferencedClass(classConstant.referencedClass);
+    }
+
+
+    // 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.
+
+    /**
+     * 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/src/proguard/optimize/peephole/UnreachableCodeRemover.java b/src/proguard/optimize/peephole/UnreachableCodeRemover.java
index 529d3c0..72ff728 100644
--- a/src/proguard/optimize/peephole/UnreachableCodeRemover.java
+++ b/src/proguard/optimize/peephole/UnreachableCodeRemover.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/UnreachableExceptionRemover.java b/src/proguard/optimize/peephole/UnreachableExceptionRemover.java
index 03c4b83..8cf2576 100644
--- a/src/proguard/optimize/peephole/UnreachableExceptionRemover.java
+++ b/src/proguard/optimize/peephole/UnreachableExceptionRemover.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/optimize/peephole/VariableShrinker.java b/src/proguard/optimize/peephole/VariableShrinker.java
index 4440227..8ec1998 100644
--- a/src/proguard/optimize/peephole/VariableShrinker.java
+++ b/src/proguard/optimize/peephole/VariableShrinker.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/optimize/peephole/VerticalClassMerger.java b/src/proguard/optimize/peephole/VerticalClassMerger.java
new file mode 100644
index 0000000..b0054f8
--- /dev/null
+++ b/src/proguard/optimize/peephole/VerticalClassMerger.java
@@ -0,0 +1,88 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ *             of Java bytecode.
+ *
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * 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.constant.visitor.ConstantVisitor;
+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)
+    {
+        programClass.subclassesAccept(new ClassMerger(programClass,
+                                                      allowAccessModification,
+                                                      mergeInterfacesAggressively,
+                                                      extraClassVisitor));
+    }
+}
\ No newline at end of file
diff --git a/src/proguard/preverify/CodePreverifier.java b/src/proguard/preverify/CodePreverifier.java
index bb2a85e..b6ca1ac 100644
--- a/src/proguard/preverify/CodePreverifier.java
+++ b/src/proguard/preverify/CodePreverifier.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
@@ -25,7 +25,7 @@ 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.instruction.*;
 import proguard.classfile.util.SimplifiedVisitor;
 import proguard.classfile.visitor.*;
 import proguard.evaluation.*;
@@ -54,10 +54,8 @@ implements   MemberVisitor,
 
     private final boolean microEdition;
 
-    private final PartialEvaluator   partialEvaluator   = new PartialEvaluator();
-    private final LivenessAnalyzer   livenessAnalyzer   = new LivenessAnalyzer(partialEvaluator);
-    private final ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor();
-    private final AttributesEditor   attributesEditor   = new AttributesEditor();
+    private final PartialEvaluator partialEvaluator = new PartialEvaluator();
+    private final LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer(partialEvaluator);
 
 
     /**
@@ -198,10 +196,7 @@ implements   MemberVisitor,
         if (frameCount == 0)
         {
             // Remove any stack map (table) attribute from the code attribute.
-            attributesEditor.deleteAttribute(programClass,
-                                             programMethod,
-                                             codeAttribute,
-                                             stackMapAttributeName);
+            new AttributesEditor(programClass, programMethod, codeAttribute, true).deleteAttribute(stackMapAttributeName);
         }
         else
         {
@@ -229,13 +224,10 @@ implements   MemberVisitor,
 
             // Fill out the name of the stack map attribute.
             stackMapAttribute.u2attributeNameIndex =
-                constantPoolEditor.addUtf8Constant(programClass, stackMapAttributeName);
+                new ConstantPoolEditor(programClass).addUtf8Constant(stackMapAttributeName);
 
             // Add the new stack map (table) attribute to the code attribute.
-            attributesEditor.addAttribute(programClass,
-                                          programMethod,
-                                          codeAttribute,
-                                          stackMapAttribute);
+            new AttributesEditor(programClass, programMethod, codeAttribute, true).addAttribute(stackMapAttribute);
 
             if (DEBUG)
             {
@@ -425,7 +417,7 @@ implements   MemberVisitor,
                     return VerificationTypeFactory.createNullType();
                 }
 
-                // Is the reference type newly created?
+                // Does the reference type have a single producer?
                 if (offset != PartialEvaluator.AT_METHOD_ENTRY)
                 {
                     InstructionOffsetValue producers = producerValue.instructionOffsetValue();
@@ -433,9 +425,17 @@ implements   MemberVisitor,
                     {
                         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.instructionOffset(0);
+                        }
+
                         // Special case: in an instance initialization method,
                         // before the super initialization, loading "this"
-                        // produces an unitinitialized stack entry.
+                        // produces an uninitialized stack entry.
                         if (partialEvaluator.isInitializer()                       &&
                             offset <= partialEvaluator.superInitializationOffset() &&
                             producerOffset > PartialEvaluator.AT_METHOD_ENTRY      &&
@@ -444,9 +444,11 @@ implements   MemberVisitor,
                             producerOffset = PartialEvaluator.AT_METHOD_ENTRY;
                         }
 
+                        // Is the reference type newly created?
                         int initializationOffset = producerOffset == PartialEvaluator.AT_METHOD_ENTRY ?
                             partialEvaluator.superInitializationOffset() :
                             partialEvaluator.initializationOffset(producerOffset);
+
                         if (initializationOffset != PartialEvaluator.NONE)
                         {
                             // Is the reference type still uninitialized?
@@ -476,9 +478,8 @@ implements   MemberVisitor,
     private int createClassConstant(ProgramClass   programClass,
                                     ReferenceValue referenceValue)
     {
-        return constantPoolEditor.addClassConstant(programClass,
-                                                   referenceValue.getType(),
-                                                   referenceValue.getReferencedClass());
+        return new ConstantPoolEditor(programClass).addClassConstant(referenceValue.getType(),
+                                                                     referenceValue.getReferencedClass());
     }
 
 
@@ -600,4 +601,15 @@ implements   MemberVisitor,
 
         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/src/proguard/preverify/CodeSubroutineInliner.java b/src/proguard/preverify/CodeSubroutineInliner.java
index d3d3eb7..cfc2c25 100644
--- a/src/proguard/preverify/CodeSubroutineInliner.java
+++ b/src/proguard/preverify/CodeSubroutineInliner.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/preverify/Preverifier.java b/src/proguard/preverify/Preverifier.java
index 3a2cc2b..55e005f 100644
--- a/src/proguard/preverify/Preverifier.java
+++ b/src/proguard/preverify/Preverifier.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/preverify/SubroutineInliner.java b/src/proguard/preverify/SubroutineInliner.java
index 8e46fca..65d5803 100644
--- a/src/proguard/preverify/SubroutineInliner.java
+++ b/src/proguard/preverify/SubroutineInliner.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/retrace/MANIFEST.MF b/src/proguard/retrace/MANIFEST.MF
new file mode 100644
index 0000000..42c9800
--- /dev/null
+++ b/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/src/proguard/retrace/ReTrace.java b/src/proguard/retrace/ReTrace.java
index f19c995..81b0832 100644
--- a/src/proguard/retrace/ReTrace.java
+++ b/src/proguard/retrace/ReTrace.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/retrace/StackTrace.java b/src/proguard/retrace/StackTrace.java
index 91332ae..791f21a 100644
--- a/src/proguard/retrace/StackTrace.java
+++ b/src/proguard/retrace/StackTrace.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/retrace/StackTraceItem.java b/src/proguard/retrace/StackTraceItem.java
index 0153b98..16d13ae 100644
--- a/src/proguard/retrace/StackTraceItem.java
+++ b/src/proguard/retrace/StackTraceItem.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/AnnotationUsageMarker.java b/src/proguard/shrink/AnnotationUsageMarker.java
index bdd7568..e4222d2 100644
--- a/src/proguard/shrink/AnnotationUsageMarker.java
+++ b/src/proguard/shrink/AnnotationUsageMarker.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/shrink/ClassShrinker.java b/src/proguard/shrink/ClassShrinker.java
index 5c50b8b..024a091 100644
--- a/src/proguard/shrink/ClassShrinker.java
+++ b/src/proguard/shrink/ClassShrinker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -231,54 +231,57 @@ implements   ClassVisitor,
 
         public void visitSignatureAttribute(Clazz clazz, SignatureAttribute  signatureAttribute)
         {
-            String  signature         = clazz.getString(signatureAttribute.u2signatureIndex);
             Clazz[] referencedClasses = signatureAttribute.referencedClasses;
+            if (referencedClasses != null)
+            {
+                // Go over the generic definitions, superclass and implemented interfaces.
+                String signature = clazz.getString(signatureAttribute.u2signatureIndex);
 
-            // Go over the generic definitions, superclass and implemented interfaces.
-            InternalTypeEnumeration internalTypeEnumeration =
-                new InternalTypeEnumeration(signature);
-
-            StringBuffer newSignatureBuffer = new StringBuffer();
+                InternalTypeEnumeration internalTypeEnumeration =
+                    new InternalTypeEnumeration(signature);
 
-            int referencedClassIndex    = 0;
-            int newReferencedClassIndex = 0;
+                StringBuffer newSignatureBuffer = new StringBuffer();
 
-            while (internalTypeEnumeration.hasMoreTypes())
-            {
-                // Consider the classes referenced by this signature.
-                String type       = internalTypeEnumeration.nextType();
-                int    classCount = new DescriptorClassEnumeration(type).classCount();
+                int referencedClassIndex    = 0;
+                int newReferencedClassIndex = 0;
 
-                Clazz referencedClass = referencedClasses[referencedClassIndex];
-                if (referencedClass == null ||
-                    usageMarker.isUsed(referencedClass))
+                while (internalTypeEnumeration.hasMoreTypes())
                 {
-                    // Append the superclass or interface.
-                    newSignatureBuffer.append(type);
+                    // Consider the classes referenced by this signature.
+                    String type       = internalTypeEnumeration.nextType();
+                    int    classCount = new DescriptorClassEnumeration(type).classCount();
 
-                    // Copy the referenced classes.
-                    for (int counter = 0; counter < classCount; counter++)
+                    Clazz referencedClass = referencedClasses[referencedClassIndex];
+                    if (referencedClass == null ||
+                        usageMarker.isUsed(referencedClass))
                     {
-                        referencedClasses[newReferencedClassIndex++] =
-                            referencedClasses[referencedClassIndex++];
+                        // Append the superclass or interface.
+                        newSignatureBuffer.append(type);
+
+                        // Copy the referenced classes.
+                        for (int counter = 0; counter < classCount; counter++)
+                        {
+                            referencedClasses[newReferencedClassIndex++] =
+                                referencedClasses[referencedClassIndex++];
+                        }
+                    }
+                    else
+                    {
+                        // Skip the referenced classes.
+                        referencedClassIndex += classCount;
                     }
                 }
-                else
-                {
-                    // Skip the referenced classes.
-                    referencedClassIndex += classCount;
-                }
-            }
-
-            if (newReferencedClassIndex < referencedClassIndex)
-            {
-                // Update the signature.
-                ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString());
 
-                // Clear the unused entries.
-                while (newReferencedClassIndex < referencedClassIndex)
+                if (newReferencedClassIndex < referencedClassIndex)
                 {
-                    referencedClasses[newReferencedClassIndex++] = null;
+                    // Update the signature.
+                    ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString());
+
+                    // Clear the unused entries.
+                    while (newReferencedClassIndex < referencedClassIndex)
+                    {
+                        referencedClasses[newReferencedClassIndex++] = null;
+                    }
                 }
             }
         }
diff --git a/src/proguard/shrink/InnerUsageMarker.java b/src/proguard/shrink/InnerUsageMarker.java
index 60a1615..2448ad3 100644
--- a/src/proguard/shrink/InnerUsageMarker.java
+++ b/src/proguard/shrink/InnerUsageMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -91,25 +91,15 @@ implements   AttributeVisitor,
 
         if (!innerClassesInfoUsed)
         {
-            int u2innerClassIndex = innerClassesInfo.u2innerClassIndex;
-            int u2outerClassIndex = innerClassesInfo.u2outerClassIndex;
-            int u2innerNameIndex  = innerClassesInfo.u2innerNameIndex;
-
-            innerClassesInfoUsed = true;
-
-            if (u2innerClassIndex != 0)
-            {
-                // Check if the inner class is marked as being used.
-                markConstant(clazz, u2innerClassIndex);
-                innerClassesInfoUsed = classUsed;
-            }
+            // Check if the inner class (if any) is marked as being used.
+            classUsed = true;
+            innerClassesInfo.innerClassConstantAccept(clazz, this);
+            innerClassesInfoUsed = classUsed;
 
-            if (u2outerClassIndex != 0)
-            {
-                // Check if the outer class is marked as being used.
-                markConstant(clazz, u2outerClassIndex);
-                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.
@@ -117,10 +107,7 @@ implements   AttributeVisitor,
             {
                 usageMarker.markAsUsed(innerClassesInfo);
 
-                if (u2innerNameIndex != 0)
-                {
-                    markConstant(clazz, u2innerNameIndex);
-                }
+                innerClassesInfo.innerNameConstantAccept(clazz, this);
             }
         }
 
diff --git a/src/proguard/shrink/InterfaceUsageMarker.java b/src/proguard/shrink/InterfaceUsageMarker.java
index d7afe82..921e974 100644
--- a/src/proguard/shrink/InterfaceUsageMarker.java
+++ b/src/proguard/shrink/InterfaceUsageMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -42,8 +42,9 @@ implements   ClassVisitor,
 {
     private final UsageMarker usageMarker;
 
-    // A field acting as a return parameter for several methods.
+    // Fields acting as a return parameters for several methods.
     private boolean used;
+    private boolean anyUsed;
 
 
     /**
@@ -66,14 +67,14 @@ implements   ClassVisitor,
 
         if (classUsed || classPossiblyUsed)
         {
-            // Mark the references to interfaces that are being used.
-            for (int index = 0; index < programClass.u2interfacesCount; index++)
-            {
-                // Check if the interface is used. Mark the constant pool entry
-                // if so.
-                markConstant(programClass, programClass.u2interfaces[index]);
-                classUsed |= used;
-            }
+            // 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)
@@ -86,13 +87,10 @@ implements   ClassVisitor,
                     usageMarker.markAsUsed(programClass);
 
                     // Mark this interface's name.
-                    markConstant(programClass, programClass.u2thisClass);
+                    programClass.thisClassConstantAccept(this);
 
                     // Mark the superclass (java/lang/Object).
-                    if (programClass.u2superClass != 0)
-                    {
-                        markConstant(programClass, programClass.u2superClass);
-                    }
+                    programClass.superClassConstantAccept(this);
                 }
                 else
                 {
@@ -109,8 +107,9 @@ implements   ClassVisitor,
 
     public void visitLibraryClass(LibraryClass libraryClass)
     {
-        // The return value.
-        used = true;
+        // The return values.
+        used    = true;
+        anyUsed = true;
     }
 
 
@@ -122,10 +121,10 @@ implements   ClassVisitor,
 
         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.
+            // 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;
+            classUsed = used;
 
             if (classUsed)
             {
@@ -133,12 +132,13 @@ implements   ClassVisitor,
                 // as well.
                 usageMarker.markAsUsed(classConstant);
 
-                markConstant(clazz, classConstant.u2nameIndex);
+                clazz.constantPoolEntryAccept(classConstant.u2nameIndex, this);
             }
         }
 
-        // The return value.
-        used = classUsed;
+        // The return values.
+        used    =  classUsed;
+        anyUsed |= classUsed;
     }
 
 
@@ -149,16 +149,4 @@ implements   ClassVisitor,
             usageMarker.markAsUsed(utf8Constant);
         }
     }
-
-
-    // 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);
-    }
 }
diff --git a/src/proguard/shrink/ShortestUsageMark.java b/src/proguard/shrink/ShortestUsageMark.java
index 16aac32..bbac60b 100644
--- a/src/proguard/shrink/ShortestUsageMark.java
+++ b/src/proguard/shrink/ShortestUsageMark.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -38,8 +38,8 @@ final class ShortestUsageMark
     private final boolean certain;
     private final String  reason;
     private final int     depth;
-    private Clazz   clazz;
-    private Method  method;
+    private       Clazz   clazz;
+    private       Member  member;
 
 
     /**
@@ -74,20 +74,20 @@ final class 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 method            the method in the above 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,
-                             Method            method)
+                             Member            member)
     {
         this.certain = true;
         this.reason  = reason;
         this.depth   = previousUsageMark.depth + cost;
         this.clazz   = clazz;
-        this.method  = method;
+        this.member  = member;
     }
 
 
@@ -103,7 +103,7 @@ final class ShortestUsageMark
         this.reason  = otherUsageMark.reason;
         this.depth   = otherUsageMark.depth;
         this.clazz   = otherUsageMark.clazz;
-        this.method  = otherUsageMark.method;
+        this.member  = otherUsageMark.member;
     }
 
 
@@ -146,12 +146,12 @@ final class ShortestUsageMark
 
     /**
      * Applies the given class visitor to this mark's class, if any,
-     * and if this mark doesn't have a method.
+     * and if this mark doesn't have a member.
      */
     public void acceptClassVisitor(ClassVisitor classVisitor)
     {
         if (clazz  != null &&
-            method == null)
+            member == null)
         {
             clazz.accept(classVisitor);
         }
@@ -159,14 +159,14 @@ final class ShortestUsageMark
 
 
     /**
-     * Applies the given class visitor to this mark's method, if any.
+     * Applies the given class visitor to this mark's member, if any.
      */
-    public void acceptMethodVisitor(MemberVisitor memberVisitor)
+    public void acceptMemberVisitor(MemberVisitor memberVisitor)
     {
         if (clazz  != null &&
-            method != null)
+            member != null)
         {
-            method.accept(clazz, memberVisitor);
+            member.accept(clazz, memberVisitor);
         }
     }
 
@@ -178,6 +178,6 @@ final class ShortestUsageMark
         return "certain=" + certain + ", depth="+depth+": " +
                reason +
                (clazz      != null ? clazz.getName() : "(none)") + ": " +
-               (method     != null ? method.getName(clazz) : "(none)");
+               (member     != null ? member.getName(clazz) : "(none)");
     }
 }
diff --git a/src/proguard/shrink/ShortestUsageMarker.java b/src/proguard/shrink/ShortestUsageMarker.java
index 9a3c524..f1855ff 100644
--- a/src/proguard/shrink/ShortestUsageMarker.java
+++ b/src/proguard/shrink/ShortestUsageMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -53,7 +53,7 @@ public class ShortestUsageMarker extends UsageMarker
         ShortestUsageMark previousUsageMark = currentUsageMark;
 
         currentUsageMark = new ShortestUsageMark(getShortestUsageMark(programClass),
-                                                 "is extended by ",
+                                                 "is extended by   ",
                                                  10000,
                                                  programClass);
 
@@ -63,12 +63,28 @@ public class ShortestUsageMarker extends UsageMarker
     }
 
 
+    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  ",
+                                                 "is invoked by    ",
                                                  1,
                                                  programClass,
                                                  programMethod);
@@ -84,7 +100,7 @@ public class ShortestUsageMarker extends UsageMarker
         ShortestUsageMark previousUsageMark = currentUsageMark;
 
         currentUsageMark = new ShortestUsageMark(getShortestUsageMark(method),
-                                                 "implements     ",
+                                                 "implements       ",
                                                  100,
                                                  clazz,
                                                  method);
@@ -193,7 +209,7 @@ public class ShortestUsageMarker extends UsageMarker
             isRecursing = false;
 
             shortestUsageMark.acceptClassVisitor(this);
-            shortestUsageMark.acceptMethodVisitor(this);
+            shortestUsageMark.acceptMemberVisitor(this);
 
             return isRecursing;
         }
@@ -253,7 +269,7 @@ public class ShortestUsageMarker extends UsageMarker
                 if (!isRecursing)
                 {
                     shortestUsageMark.acceptClassVisitor(this);
-                    shortestUsageMark.acceptMethodVisitor(this);
+                    shortestUsageMark.acceptMemberVisitor(this);
                 }
             }
         }
diff --git a/src/proguard/shrink/ShortestUsagePrinter.java b/src/proguard/shrink/ShortestUsagePrinter.java
index ecec10c..4045f12 100644
--- a/src/proguard/shrink/ShortestUsagePrinter.java
+++ b/src/proguard/shrink/ShortestUsagePrinter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -187,7 +187,7 @@ implements   ClassVisitor,
 
             // Print the class or method that is responsible, with its reasons.
             shortestUsageMark.acceptClassVisitor(this);
-            shortestUsageMark.acceptMethodVisitor(this);
+            shortestUsageMark.acceptMemberVisitor(this);
         }
         else
         {
diff --git a/src/proguard/shrink/Shrinker.java b/src/proguard/shrink/Shrinker.java
index a1b318e..2d35059 100644
--- a/src/proguard/shrink/Shrinker.java
+++ b/src/proguard/shrink/Shrinker.java
@@ -2,14 +2,13 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- *
  * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
diff --git a/src/proguard/shrink/UsageMarker.java b/src/proguard/shrink/UsageMarker.java
index 3585cc4..b2bed5f 100644
--- a/src/proguard/shrink/UsageMarker.java
+++ b/src/proguard/shrink/UsageMarker.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -66,7 +66,7 @@ implements ClassVisitor,
 
 
     private final MyInterfaceUsageMarker          interfaceUsageMarker          = new MyInterfaceUsageMarker();
-    private final MyPossiblyUsedMethodUsageMarker possiblyUsedMethodUsageMarker = new MyPossiblyUsedMethodUsageMarker();
+    private final MyPossiblyUsedMemberUsageMarker possiblyUsedMemberUsageMarker = new MyPossiblyUsedMemberUsageMarker();
 //    private ClassVisitor       dynamicClassMarker   =
 //        new MultiClassVisitor(
 //        new ClassVisitor[]
@@ -117,8 +117,9 @@ implements ClassVisitor,
                                   ClassConstants.INTERNAL_METHOD_TYPE_INIT,
                                   this);
 
-        // Process all methods that have already been marked as possibly used.
-        programClass.methodsAccept(possiblyUsedMethodUsageMarker);
+        // Process all class members that have already been marked as possibly used.
+        programClass.fieldsAccept(possiblyUsedMemberUsageMarker);
+        programClass.methodsAccept(possiblyUsedMemberUsageMarker);
 
         // Mark the attributes.
         programClass.attributesAccept(this);
@@ -186,12 +187,32 @@ implements ClassVisitor,
     }
 
 
-    private class MyPossiblyUsedMethodUsageMarker
+    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?
@@ -206,8 +227,6 @@ implements ClassVisitor,
                 // the method hierarchy has already been marked (cfr. below).
             }
         }
-
-
     }
 
 
@@ -217,17 +236,22 @@ implements ClassVisitor,
     {
         if (shouldBeMarkedAsUsed(programField))
         {
-            markAsUsed(programField);
-
-            // Mark the name and descriptor.
-            markConstant(programClass, programField.u2nameIndex);
-            markConstant(programClass, programField.u2descriptorIndex);
+            // Is the field's class used?
+            if (isUsed(programClass))
+            {
+                markAsUsed(programField);
 
-            // Mark the attributes.
-            programField.attributesAccept(programClass, this);
+                // Mark the field body.
+                markProgramFieldBody(programClass, programField);
+            }
 
-            // Mark the classes referenced in the descriptor string.
-            programField.referencedClassesAccept(this);
+            // 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);
+            }
         }
     }
 
@@ -277,6 +301,20 @@ implements ClassVisitor,
     }
 
 
+    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.
@@ -297,7 +335,17 @@ implements ClassVisitor,
      */
     protected void markMethodHierarchy(Clazz clazz, Method method)
     {
-        clazz.methodImplementationsAccept(method, false, this);
+        if ((method.getAccessFlags() &
+             (ClassConstants.INTERNAL_ACC_PRIVATE |
+              ClassConstants.INTERNAL_ACC_STATIC)) == 0)
+        {
+            clazz.accept(new ConcreteClassDownTraveler(
+                         new ClassHierarchyTraveler(true, true, false, true,
+                         new NamedMethodVisitor(method.getName(clazz),
+                                                method.getDescriptor(clazz),
+                         new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC | ClassConstants.INTERNAL_ACC_ABSTRACT,
+                         this)))));
+        }
     }
 
 
@@ -367,41 +415,23 @@ implements ClassVisitor,
     }
 
 
-    public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
-    {
-        visitRefConstant(clazz, fieldrefConstant);
-    }
-
-
-    public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
-    {
-        visitRefConstant(clazz, interfaceMethodrefConstant);
-    }
-
-
-    public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+    public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
     {
-        visitRefConstant(clazz, methodrefConstant);
-    }
-
-
-    private void visitRefConstant(Clazz clazz, RefConstant methodrefConstant)
-    {
-        if (shouldBeMarkedAsUsed(methodrefConstant))
+        if (shouldBeMarkedAsUsed(refConstant))
         {
-            markAsUsed(methodrefConstant);
+            markAsUsed(refConstant);
 
-            markConstant(clazz, methodrefConstant.u2classIndex);
-            markConstant(clazz, methodrefConstant.u2nameAndTypeIndex);
+            markConstant(clazz, refConstant.u2classIndex);
+            markConstant(clazz, refConstant.u2nameAndTypeIndex);
 
             // When compiled with "-target 1.2" or higher, the class or
-            // interface actually containing the referenced method may be
-            // higher up the hierarchy. Make sure it's marked, in case it
+            // 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.
-            methodrefConstant.referencedClassAccept(this);
+            refConstant.referencedClassAccept(this);
 
-            // Mark the referenced method itself.
-            methodrefConstant.referencedMemberAccept(this);
+            // Mark the referenced class member itself.
+            refConstant.referencedMemberAccept(this);
         }
     }
 
@@ -659,25 +689,14 @@ implements ClassVisitor,
     {
         // At this point, we only mark outer classes of this class.
         // Inner class can be marked later, by InnerUsageMarker.
-        if (innerClassesInfo.u2innerClassIndex == 0 &&
+        if (innerClassesInfo.u2innerClassIndex != 0 &&
             clazz.getName().equals(clazz.getClassName(innerClassesInfo.u2innerClassIndex)))
         {
             markAsUsed(innerClassesInfo);
 
-            if (innerClassesInfo.u2innerClassIndex != 0)
-            {
-                markConstant(clazz, innerClassesInfo.u2innerClassIndex);
-            }
-
-            if (innerClassesInfo.u2outerClassIndex != 0)
-            {
-                markConstant(clazz, innerClassesInfo.u2outerClassIndex);
-            }
-
-            if (innerClassesInfo.u2innerNameIndex != 0)
-            {
-                markConstant(clazz, innerClassesInfo.u2innerNameIndex);
-            }
+            innerClassesInfo.innerClassConstantAccept(clazz, this);
+            innerClassesInfo.outerClassConstantAccept(clazz, this);
+            innerClassesInfo.innerNameConstantAccept(clazz, this);
         }
     }
 
diff --git a/src/proguard/shrink/UsagePrinter.java b/src/proguard/shrink/UsagePrinter.java
index cff528b..35cd1df 100644
--- a/src/proguard/shrink/UsagePrinter.java
+++ b/src/proguard/shrink/UsagePrinter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/UsedClassFilter.java b/src/proguard/shrink/UsedClassFilter.java
index 54f94c7..563eecc 100644
--- a/src/proguard/shrink/UsedClassFilter.java
+++ b/src/proguard/shrink/UsedClassFilter.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/shrink/UsedMemberFilter.java b/src/proguard/shrink/UsedMemberFilter.java
index c4373ec..9738415 100644
--- a/src/proguard/shrink/UsedMemberFilter.java
+++ b/src/proguard/shrink/UsedMemberFilter.java
@@ -2,21 +2,21 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
- * This library is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * 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;
 
diff --git a/src/proguard/util/AndMatcher.java b/src/proguard/util/AndMatcher.java
index f3be5d5..6f645fa 100644
--- a/src/proguard/util/AndMatcher.java
+++ b/src/proguard/util/AndMatcher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ClassNameParser.java b/src/proguard/util/ClassNameParser.java
index 16020a0..4ae3f1b 100644
--- a/src/proguard/util/ClassNameParser.java
+++ b/src/proguard/util/ClassNameParser.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/EmptyStringMatcher.java b/src/proguard/util/EmptyStringMatcher.java
index cfa0a73..3ff5dfc 100644
--- a/src/proguard/util/EmptyStringMatcher.java
+++ b/src/proguard/util/EmptyStringMatcher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ExtensionMatcher.java b/src/proguard/util/ExtensionMatcher.java
index 9e5b795..e12da2b 100644
--- a/src/proguard/util/ExtensionMatcher.java
+++ b/src/proguard/util/ExtensionMatcher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/FileNameParser.java b/src/proguard/util/FileNameParser.java
index 5f67387..2c34fa0 100644
--- a/src/proguard/util/FileNameParser.java
+++ b/src/proguard/util/FileNameParser.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/FixedStringMatcher.java b/src/proguard/util/FixedStringMatcher.java
index c4eb639..de94763 100644
--- a/src/proguard/util/FixedStringMatcher.java
+++ b/src/proguard/util/FixedStringMatcher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -22,7 +22,7 @@ package proguard.util;
 
 /**
  * This StringMatcher tests whether strings start with a given fixed string
- * and then match another given StringMatcher.
+ * and then match another optional given StringMatcher.
  *
  * @author Eric Lafortune
  */
@@ -50,6 +50,7 @@ public class FixedStringMatcher implements StringMatcher
     public boolean matches(String string)
     {
         return string.startsWith(fixedString) &&
-               nextMatcher.matches(string.substring(fixedString.length()));
+               (nextMatcher == null ||
+                nextMatcher.matches(string.substring(fixedString.length())));
     }
 }
diff --git a/src/proguard/util/ListMatcher.java b/src/proguard/util/ListMatcher.java
index ec170a2..c573fe3 100644
--- a/src/proguard/util/ListMatcher.java
+++ b/src/proguard/util/ListMatcher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ListParser.java b/src/proguard/util/ListParser.java
index d93c053..f411319 100644
--- a/src/proguard/util/ListParser.java
+++ b/src/proguard/util/ListParser.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/ListUtil.java b/src/proguard/util/ListUtil.java
index 03fbdd0..37aae61 100644
--- a/src/proguard/util/ListUtil.java
+++ b/src/proguard/util/ListUtil.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/NameParser.java b/src/proguard/util/NameParser.java
index 4fdad49..beda426 100644
--- a/src/proguard/util/NameParser.java
+++ b/src/proguard/util/NameParser.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/NotMatcher.java b/src/proguard/util/NotMatcher.java
index 19beb88..4c11c99 100644
--- a/src/proguard/util/NotMatcher.java
+++ b/src/proguard/util/NotMatcher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/OrMatcher.java b/src/proguard/util/OrMatcher.java
index dbd8119..2a8e625 100644
--- a/src/proguard/util/OrMatcher.java
+++ b/src/proguard/util/OrMatcher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/SettableMatcher.java b/src/proguard/util/SettableMatcher.java
index 8f0954e..c7ab5c2 100644
--- a/src/proguard/util/SettableMatcher.java
+++ b/src/proguard/util/SettableMatcher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -22,7 +22,7 @@ package proguard.util;
 
 /**
  * This StringMatcher delegates to a another StringMatcher that can be set
- * after this StringMatcher has been constructed.  
+ * after this StringMatcher has been constructed.
  *
  * @author Eric Lafortune
  */
diff --git a/src/proguard/util/StringMatcher.java b/src/proguard/util/StringMatcher.java
index 571ace6..57a9f10 100644
--- a/src/proguard/util/StringMatcher.java
+++ b/src/proguard/util/StringMatcher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/StringParser.java b/src/proguard/util/StringParser.java
index 9a81586..6d635ba 100644
--- a/src/proguard/util/StringParser.java
+++ b/src/proguard/util/StringParser.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/util/VariableStringMatcher.java b/src/proguard/util/VariableStringMatcher.java
index 3594156..526ab4f 100644
--- a/src/proguard/util/VariableStringMatcher.java
+++ b/src/proguard/util/VariableStringMatcher.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/wtk/ProGuardObfuscator.java b/src/proguard/wtk/ProGuardObfuscator.java
index 062a475..e8665b5 100644
--- a/src/proguard/wtk/ProGuardObfuscator.java
+++ b/src/proguard/wtk/ProGuardObfuscator.java
@@ -2,7 +2,7 @@
  * ProGuard -- shrinking, optimization, obfuscation, and preverification
  *             of Java bytecode.
  *
- * Copyright (c) 2002-2007 Eric Lafortune (eric at graphics.cornell.edu)
+ * Copyright (c) 2002-2008 Eric Lafortune (eric at graphics.cornell.edu)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
diff --git a/src/proguard/wtk/default.pro b/src/proguard/wtk/default.pro
index ca7535e..d31714f 100644
--- a/src/proguard/wtk/default.pro
+++ b/src/proguard/wtk/default.pro
@@ -1,5 +1,6 @@
 -dontnote
 -microedition
+-mergeinterfacesaggressively
 -overloadaggressively
 -repackageclasses ''
 -allowaccessmodification

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/proguard.git



More information about the pkg-java-commits mailing list