Compare commits

...

No commits in common. 'master' and 'generics' have entirely different histories.

  1. 14
      CVSROOT/checkoutlist
  2. 15
      CVSROOT/commitinfo
  3. 11
      CVSROOT/config
  4. 1
      CVSROOT/cvsignore
  5. 24
      CVSROOT/cvswrappers
  6. 21
      CVSROOT/editinfo
  7. 27
      CVSROOT/loginfo
  8. 1
      CVSROOT/modules
  9. 12
      CVSROOT/notify
  10. 13
      CVSROOT/rcsinfo
  11. 206
      CVSROOT/syncmail
  12. 20
      CVSROOT/taginfo
  13. 21
      CVSROOT/verifymsg
  14. 7
      jode/.classpath
  15. 2
      jode/.project
  16. 353
      jode/.settings/org.eclipse.jdt.core.prefs
  17. 4
      jode/.settings/org.eclipse.jdt.ui.prefs
  18. 3
      jode/.settings/org.eclipse.ltk.core.refactoring.prefs
  19. 4
      jode/build.xml
  20. 23
      jode/doc/download.htp
  21. BIN
      jode/doc/jode-2.png
  22. BIN
      jode/doc/jode-logo.png
  23. BIN
      jode/doc/w3c_ab.png
  24. 17
      jode/src/net/sf/jode/bytecode/BasicBlockReader.java
  25. 4
      jode/src/net/sf/jode/bytecode/BasicBlockWriter.java
  26. 1
      jode/src/net/sf/jode/bytecode/BasicBlocks.java
  27. 1
      jode/src/net/sf/jode/bytecode/Block.java
  28. 20
      jode/src/net/sf/jode/bytecode/ClassInfo.java
  29. 11
      jode/src/net/sf/jode/bytecode/FieldInfo.java
  30. 9
      jode/src/net/sf/jode/bytecode/GrowableConstantPool.java
  31. 11
      jode/src/net/sf/jode/bytecode/MethodInfo.java
  32. 450
      jode/src/net/sf/jode/bytecode/TypeSignature.java
  33. 3
      jode/src/net/sf/jode/decompiler/Applet.java
  34. 108
      jode/src/net/sf/jode/decompiler/ClassAnalyzer.java
  35. 16
      jode/src/net/sf/jode/decompiler/ClassDeclarer.java
  36. 11
      jode/src/net/sf/jode/decompiler/FieldAnalyzer.java
  37. 5
      jode/src/net/sf/jode/decompiler/ImportHandler.java
  38. 43
      jode/src/net/sf/jode/decompiler/Main.java
  39. 127
      jode/src/net/sf/jode/decompiler/MethodAnalyzer.java
  40. 14
      jode/src/net/sf/jode/decompiler/Opcodes.java
  41. 2
      jode/src/net/sf/jode/decompiler/Options.java
  42. 8
      jode/src/net/sf/jode/decompiler/OuterValues.java
  43. 171
      jode/src/net/sf/jode/decompiler/TabbedPrintWriter.java
  44. 5
      jode/src/net/sf/jode/decompiler/Window.java
  45. 2
      jode/src/net/sf/jode/expr/ArrayStoreOperator.java
  46. 5
      jode/src/net/sf/jode/expr/ClassFieldOperator.java
  47. 10
      jode/src/net/sf/jode/expr/ConstOperator.java
  48. 13
      jode/src/net/sf/jode/expr/Expression.java
  49. 142
      jode/src/net/sf/jode/expr/FieldOperator.java
  50. 1
      jode/src/net/sf/jode/expr/IIncOperator.java
  51. 8
      jode/src/net/sf/jode/expr/IfThenElseOperator.java
  52. 2
      jode/src/net/sf/jode/expr/InstanceOfOperator.java
  53. 61
      jode/src/net/sf/jode/expr/InvokeOperator.java
  54. 3
      jode/src/net/sf/jode/expr/LValueExpression.java
  55. 3
      jode/src/net/sf/jode/expr/LocalLoadOperator.java
  56. 2
      jode/src/net/sf/jode/expr/LocalStoreOperator.java
  57. 1
      jode/src/net/sf/jode/expr/NoArgOperator.java
  58. 4
      jode/src/net/sf/jode/expr/Operator.java
  59. 3
      jode/src/net/sf/jode/expr/OuterLocalOperator.java
  60. 1
      jode/src/net/sf/jode/expr/PrePostFixOperator.java
  61. 1
      jode/src/net/sf/jode/expr/PutFieldOperator.java
  62. 4
      jode/src/net/sf/jode/expr/StoreInstruction.java
  63. 7
      jode/src/net/sf/jode/expr/StringAddOperator.java
  64. 25
      jode/src/net/sf/jode/expr/ThisOperator.java
  65. 1
      jode/src/net/sf/jode/flow/BreakableBlock.java
  66. 4
      jode/src/net/sf/jode/flow/CatchBlock.java
  67. 1
      jode/src/net/sf/jode/flow/CombineIfGotoExpressions.java
  68. 5
      jode/src/net/sf/jode/flow/ConditionalBlock.java
  69. 6
      jode/src/net/sf/jode/flow/CreateAssignExpression.java
  70. 6
      jode/src/net/sf/jode/flow/CreateClassField.java
  71. 1
      jode/src/net/sf/jode/flow/CreateConstantArray.java
  72. 11
      jode/src/net/sf/jode/flow/CreateIfThenElseOperator.java
  73. 8
      jode/src/net/sf/jode/flow/CreatePrePostIncExpression.java
  74. 155
      jode/src/net/sf/jode/flow/FlowBlock.java
  75. 11
      jode/src/net/sf/jode/flow/IfThenElseBlock.java
  76. 9
      jode/src/net/sf/jode/flow/InstructionBlock.java
  77. 2
      jode/src/net/sf/jode/flow/InstructionContainer.java
  78. 2
      jode/src/net/sf/jode/flow/Jump.java
  79. 161
      jode/src/net/sf/jode/flow/LabelledBlock.java
  80. 15
      jode/src/net/sf/jode/flow/LoopBlock.java
  81. 4
      jode/src/net/sf/jode/flow/ReturnBlock.java
  82. 1
      jode/src/net/sf/jode/flow/SequentialBlock.java
  83. 3
      jode/src/net/sf/jode/flow/SlotSet.java
  84. 7
      jode/src/net/sf/jode/flow/StructuredBlock.java
  85. 2
      jode/src/net/sf/jode/flow/SynchronizedBlock.java
  86. 2
      jode/src/net/sf/jode/flow/ThrowBlock.java
  87. 9
      jode/src/net/sf/jode/flow/TransformConstructors.java
  88. 10
      jode/src/net/sf/jode/flow/TransformExceptionHandlers.java
  89. 3
      jode/src/net/sf/jode/flow/VariableSet.java
  90. 7
      jode/src/net/sf/jode/flow/VariableStack.java
  91. 6
      jode/src/net/sf/jode/jvm/CodeVerifier.java
  92. 1
      jode/src/net/sf/jode/jvm/Interpreter.java
  93. 16
      jode/src/net/sf/jode/jvm/SyntheticAnalyzer.java
  94. 1
      jode/src/net/sf/jode/jvm/Value.java
  95. 1
      jode/src/net/sf/jode/jvm/VerifyException.java
  96. 5
      jode/src/net/sf/jode/obfuscator/ClassBundle.java
  97. 4
      jode/src/net/sf/jode/obfuscator/ClassIdentifier.java
  98. 2
      jode/src/net/sf/jode/obfuscator/FieldIdentifier.java
  99. 1
      jode/src/net/sf/jode/obfuscator/Identifier.java
  100. 1
      jode/src/net/sf/jode/obfuscator/Main.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,14 +0,0 @@
# The "checkoutlist" file is used to support additional version controlled
# administrative files in $CVSROOT/CVSROOT, such as template files.
#
# The first entry on a line is a filename which will be checked out from
# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
# The remainder of the line is an error message to use if the file cannot
# be checked out.
#
# File format:
#
# [<whitespace>]<filename><whitespace><error message><end-of-line>
#
# comment lines begin with '#'
syncmail

@ -1,15 +0,0 @@
# The "commitinfo" file is used to control pre-commit checks.
# The filter on the right is invoked with the repository and a list
# of files to check. A non-zero exit of the filter program will
# cause the commit to be aborted.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being committed to, relative
# to the $CVSROOT. For the first match that is found, then the remainder
# of the line is the name of the filter to run.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".

@ -1,11 +0,0 @@
# Set this to "no" if pserver shouldn't check system users/passwords
#SystemAuth=no
# Set `PreservePermissions' to `yes' to save file status information
# in the repository.
#PreservePermissions=no
# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top
# level of the new working directory when using the `cvs checkout'
# command.
#TopLevelAdmin=no

@ -1,24 +0,0 @@
# This file affects handling of files based on their names.
#
# The -t/-f options allow one to treat directories of files
# as a single file, or to transform a file in other ways on
# its way in and out of CVS.
#
# The -m option specifies whether CVS attempts to merge files.
#
# The -k option specifies keyword expansion (e.g. -kb for binary).
#
# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
#
# wildcard [option value][option value]...
#
# where option is one of
# -f from cvs filter value: path to filter
# -t to cvs filter value: path to filter
# -m update methodology value: MERGE or COPY
# -k expansion mode value: b, o, kkv, &c
#
# and value is a single-quote delimited value.
# For example:
*.gif -k 'b'
*.xcf -k 'b'

@ -1,21 +0,0 @@
# The "editinfo" file is used to allow verification of logging
# information. It works best when a template (as specified in the
# rcsinfo file) is provided for the logging procedure. Given a
# template with locations for, a bug-id number, a list of people who
# reviewed the code before it can be checked in, and an external
# process to catalog the differences that were code reviewed, the
# following test can be applied to the code:
#
# Making sure that the entered bug-id number is correct.
# Validating that the code that was reviewed is indeed the code being
# checked in (using the bug-id number or a seperate review
# number to identify this particular code set.).
#
# If any of the above test failed, then the commit would be aborted.
#
# Actions such as mailing a copy of the report to each reviewer are
# better handled by an entry in the loginfo file.
#
# One thing that should be noted is the the ALL keyword is not
# supported. There can be only one entry that matches a given
# repository.

@ -1,27 +0,0 @@
# The "loginfo" file controls where "cvs commit" log information
# is sent. The first entry on a line is a regular expression which must match
# the directory that the change is being made to, relative to the
# $CVSROOT. If a match is found, then the remainder of the line is a filter
# program that should expect log information on its standard input.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name ALL appears as a regular expression it is always used
# in addition to the first matching regex or DEFAULT.
#
# You may specify a format string as part of the
# filter. The string is composed of a `%' followed
# by a single format character, or followed by a set of format
# characters surrounded by `{' and `}' as separators. The format
# characters are:
#
# s = file name
# V = old version number (pre-checkin)
# v = new version number (post-checkin)
#
# For example:
#DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog
# or
#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog
DEFAULT $CVSROOT/CVSROOT/syncmail %{sVv} jode-commit@lists.sourceforge.net

@ -1 +0,0 @@
jode jode

@ -1,12 +0,0 @@
# The "notify" file controls where notifications from watches set by
# "cvs watch add" or "cvs edit" are sent. The first entry on a line is
# a regular expression which is tested against the directory that the
# change is being made to, relative to the $CVSROOT. If it matches,
# then the remainder of the line is a filter program that should contain
# one occurrence of %s for the user to notify, and information on its
# standard input.
#
# "ALL" or "DEFAULT" can be used in place of the regular expression.
#
# For example:
#ALL mail %s -s "CVS notification"

@ -1,13 +0,0 @@
# The "rcsinfo" file is used to control templates with which the editor
# is invoked on commit and import.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being made to, relative to the
# $CVSROOT. For the first match that is found, then the remainder of the
# line is the name of the file that contains the template.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".

@ -1,206 +0,0 @@
#! /usr/bin/python
# -*- Python -*-
"""Complicated notification for CVS checkins.
This script is used to provide email notifications of changes to the CVS
repository. These email changes will include context diffs of the changes.
Really big diffs will be trimmed.
This script is run from a CVS loginfo file (see $CVSROOT/CVSROOT/loginfo). To
set this up, create a loginfo entry that looks something like this:
mymodule /path/to/this/script %%s some-email-addr@your.domain
In this example, whenever a checkin that matches `mymodule' is made, this
script is invoked, which will generate the diff containing email, and send it
to some-email-addr@your.domain.
Note: This module used to also do repository synchronizations via
rsync-over-ssh, but since the repository has been moved to SourceForge,
this is no longer necessary. The syncing functionality has been ripped
out in the 3.0, which simplifies it considerably. Access the 2.x versions
to refer to this functionality. Because of this, the script is misnamed.
It no longer makes sense to run this script from the command line. Doing so
will only print out this usage information.
Usage:
%(PROGRAM)s [options] <%%S> email-addr [email-addr ...]
Where options is:
--cvsroot=<path>
Use <path> as the environment variable CVSROOT. Otherwise this
variable must exist in the environment.
--help
-h
Print this text.
<%%S>
CVS %%s loginfo expansion. When invoked by CVS, this will be a single
string containing the directory the checkin is being made in, relative
to $CVSROOT, followed by the list of files that are changing. If the
%%s in the loginfo file is %%{sVv}, context diffs for each of the
modified files are included in any email messages that are generated.
email-addrs
At least one email address.
"""
import os
import sys
import string
import time
import getopt
# Notification command
MAILCMD = '/bin/mail -s "%(SUBJECT)s" %(PEOPLE)s 2>&1 > /dev/null'
# Diff trimming stuff
DIFF_HEAD_LINES = 20
DIFF_TAIL_LINES = 20
DIFF_TRUNCATE_IF_LARGER = 1000
PROGRAM = sys.argv[0]
def usage(code, msg=''):
print __doc__ % globals()
if msg:
print msg
sys.exit(code)
def calculate_diff(filespec):
try:
file, oldrev, newrev = string.split(filespec, ',')
except ValueError:
# No diff to report
return '***** Bogus filespec: %s' % filespec
if oldrev == 'NONE':
try:
if os.path.exists(file):
fp = open(file)
else:
update_cmd = 'cvs -fn update -r %s -p %s' % (newrev, file)
fp = os.popen(update_cmd)
lines = fp.readlines()
fp.close()
lines.insert(0, '--- NEW FILE ---\n')
except IOError, e:
lines = ['***** Error reading new file: ',
str(e), '\n***** file: ', file, ' cwd: ', os.getcwd()]
elif newrev == 'NONE':
lines = ['--- %s DELETED ---\n' % file]
else:
# This /has/ to happen in the background, otherwise we'll run into CVS
# lock contention. What a crock.
diffcmd = '/usr/bin/cvs -f diff -kk -C 2 -r %s -r %s %s' % (
oldrev, newrev, file)
fp = os.popen(diffcmd)
lines = fp.readlines()
sts = fp.close()
# ignore the error code, it always seems to be 1 :(
## if sts:
## return 'Error code %d occurred during diff\n' % (sts >> 8)
if len(lines) > DIFF_TRUNCATE_IF_LARGER:
removedlines = len(lines) - DIFF_HEAD_LINES - DIFF_TAIL_LINES
del lines[DIFF_HEAD_LINES:-DIFF_TAIL_LINES]
lines.insert(DIFF_HEAD_LINES,
'[...%d lines suppressed...]\n' % removedlines)
return string.join(lines, '')
def calculate_url(dir, filespec):
try:
file, oldrev, newrev = string.split(filespec, ',')
except ValueError:
# No diff to report
return '***** Bogus filespec: %s' % filespec
if oldrev == 'NONE':
lines = [ 'http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jode/%s/%s?rev=%s' % (dir, file, newrev) ]
elif newrev == 'NONE':
lines = [ 'DELETED: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jode/%s/%s?rev=%s' % (dir, file, oldrev) ]
else:
lines = [ 'http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jode/%s/%s.diff?r1=%s&r2=%s&diff_format=u' % (dir, file, oldrev, newrev) ]
return string.join(lines, '')
def blast_mail(mailcmd, dir, filestodiff):
## cannot wait for child process or that will cause parent to retain cvs
## lock for too long. Urg!
#if not os.fork():
# in the child
# give up the lock you cvs thang!
time.sleep(2)
fp = os.popen(mailcmd, 'w')
fp.write(sys.stdin.read())
fp.write('\n')
# append the cvsweb urls if available
fp.write('CVSWeb URLs:\n');
for file in filestodiff:
# fp.write(calculate_diff(file))
fp.write(calculate_url(dir, file))
fp.write('\n')
fp.close()
## doesn't matter what code we return, it isn't waited on
# os._exit(0)
# scan args for options
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], 'h', ['cvsroot=', 'help'])
except getopt.error, msg:
usage(1, msg)
# parse the options
for opt, arg in opts:
if opt in ('-h', '--help'):
usage(0)
elif opt == '--cvsroot':
os.environ['CVSROOT'] = arg
# What follows is the specification containing the files that were
# modified. The argument actually must be split, with the first component
# containing the directory the checkin is being made in, relative to
# $CVSROOT, followed by the list of files that are changing.
if not args:
usage(1, 'No CVS module specified')
specs = string.split(args[0])
changedfiles = [ specs[0] ];
for filespec in specs[1:]:
try:
file, oldrev, newrev = string.split(filespec, ',')
changedfiles.append(file)
except ValueError:
changedfiles.append(filespec)
SUBJECT = string.join(changedfiles, ' ')
del args[0]
# The remaining args should be the email addresses
if not args:
usage(1, 'No recipients specified')
# Now do the mail command
PEOPLE = string.join(args)
mailcmd = MAILCMD % vars()
if specs == ['-', 'Imported', 'sources']:
return
if specs[-3:] == ['-', 'New', 'directory']:
del specs[-3:]
blast_mail(mailcmd, specs[0], specs[1:])
if __name__ == '__main__':
main()
sys.exit(0)

@ -1,20 +0,0 @@
# The "taginfo" file is used to control pre-tag checks.
# The filter on the right is invoked with the following arguments:
#
# $1 -- tagname
# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d
# $3 -- repository
# $4-> file revision [file revision ...]
#
# A non-zero exit of the filter program will cause the tag to be aborted.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being committed to, relative
# to the $CVSROOT. For the first match that is found, then the remainder
# of the line is the name of the filter to run.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".

@ -1,21 +0,0 @@
# The "verifymsg" file is used to allow verification of logging
# information. It works best when a template (as specified in the
# rcsinfo file) is provided for the logging procedure. Given a
# template with locations for, a bug-id number, a list of people who
# reviewed the code before it can be checked in, and an external
# process to catalog the differences that were code reviewed, the
# following test can be applied to the code:
#
# Making sure that the entered bug-id number is correct.
# Validating that the code that was reviewed is indeed the code being
# checked in (using the bug-id number or a seperate review
# number to identify this particular code set.).
#
# If any of the above test failed, then the commit would be aborted.
#
# Actions such as mailing a copy of the report to each reviewer are
# better handled by an entry in the loginfo file.
#
# One thing that should be noted is the the ALL keyword is not
# supported. There can be only one entry that matches a given
# repository.

@ -1,7 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry excluding="net/sf/jode/obfuscator/modules/LocalOptimizer.java|net/sf/jode/obfuscator/modules/LocalizeFieldTransformer.java|net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java" kind="src" output="build" path="src"/> <classpathentry excluding="net/sf/jode/obfuscator/modules/LocalOptimizer.java|net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java" kind="src" path="src"/>
<classpathentry excluding="src/|innerclasses/" kind="src" path="test"/>
<classpathentry kind="src" path="test/innerclasses"/>
<classpathentry kind="src" path="test/src"/>
<classpathentry kind="lib" path="lib/java-getopt-1.0.8.jar"/> <classpathentry kind="lib" path="lib/java-getopt-1.0.8.jar"/>
<classpathentry kind="src" path="props"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3.8.1"/>
<classpathentry kind="output" path="build"/> <classpathentry kind="output" path="build"/>
</classpath> </classpath>

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<projectDescription> <projectDescription>
<name>jode</name> <name>Jode</name>
<comment></comment> <comment></comment>
<projects> <projects>
</projects> </projects>

@ -1,353 +0,0 @@
#Thu Mar 01 23:39:18 CET 2012
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.4
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.3
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
org.eclipse.jdt.core.formatter.comment.line_length=80
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=2
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=80
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=mixed
org.eclipse.jdt.core.formatter.tabulation.size=8
org.eclipse.jdt.core.formatter.use_on_off_tags=false
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true

@ -1,4 +0,0 @@
#Thu Mar 01 22:21:28 CET 2012
eclipse.preferences.version=1
formatter_profile=org.eclipse.jdt.ui.default.sun_profile
formatter_settings_version=12

@ -1,3 +0,0 @@
#Thu Mar 01 22:15:48 CET 2012
eclipse.preferences.version=1
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false

@ -302,7 +302,7 @@
<target name="test" depends="build-test"> <target name="test" depends="build-test">
<mkdir dir="${test.log}"/> <mkdir dir="${test.log}"/>
<junit printsummary="yes" fork="yes" haltonfailure="yes"> <junit printsummary="yes" haltonfailure="yes">
<classpath> <classpath>
<pathelement path="${test.build}"/> <pathelement path="${test.build}"/>
<pathelement path="${build}"/> <pathelement path="${build}"/>
@ -319,7 +319,7 @@
<target name="test-cvs" depends="build-test"> <target name="test-cvs" depends="build-test">
<mkdir dir="${test.log}"/> <mkdir dir="${test.log}"/>
<junit printsummary="yes" fork="yes" haltonfailure="yes"> <junit printsummary="yes" haltonfailure="yes">
<classpath> <classpath>
<pathelement path="${test.build}"/> <pathelement path="${test.build}"/>
<pathelement path="${build}"/> <pathelement path="${build}"/>

@ -18,22 +18,21 @@ packages are already included in the archive. </li>
without any other package.</li> </ul> without any other package.</li> </ul>
</section> </section>
<section title="Subversion Repository"> <section title="CVS Repository">
<p>You can get the latest sources from the <sflink href="cvs/"> CVS
<p>You can get the latest sources from the <a repository</a>. Follow the instruction on that page; use
href="http://sourceforge.net/svn/?group_id=3790">SVN repository</a>. <code>jode</code> as <i>modulename</i>. If you want to checkout a
Follow the instruction on that page; use specific version you can use the <code>-r</code> option:</p>
<code>/svnroot/jode/trunk/jode</code> as last part of the URL. If you
want to checkout a specific version you can checkout the URL
<code>.../svnroot/jode/tags/xxx/jode</code>:</p>
<ul> <ul>
<li><code>../jode/tags/jode_1_0_93/jode</code>: checks out the version 1.0.93</li> <li><code>-r jode_1_0_93</code>: checks out the version 1.0.93</li>
<li><code>../jode/branches/branch_1_1/jode</code>: checks out the latest version in the <li><code>-r branch_1_1</code>: checks out the latest version in the
1.1 series.</li> </ul> 1.1 series.</li> </ul>
<p>To build the sources from latest SVN change to the main directory and invoke ant.</p> <p>To build the sources from CVS change to the main directory where
<p>To build the 1.1 versions of jode change to the main directory and run the <code>configure.in</code> file resides and run
<pre>aclocal && automake -a && autoconf</pre> <pre>aclocal && automake -a && autoconf</pre>
<p>Afterwards follow the instruction in the INSTALL file. </p> <p>Afterwards follow the instruction in the INSTALL file. </p>
</section> </section>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -63,11 +63,6 @@ class BasicBlockReader implements Opcodes {
String name, type; String name, type;
} }
private class LNTEntry {
int lineNr;
int start;
}
InstrInfo[] infos; InstrInfo[] infos;
HandlerEntry[] handlers; HandlerEntry[] handlers;
BasicBlocks bb; BasicBlocks bb;
@ -543,8 +538,10 @@ class BasicBlockReader implements Opcodes {
case opc_ldc: { case opc_ldc: {
int index = input.readUnsignedByte(); int index = input.readUnsignedByte();
int tag = cp.getTag(index); int tag = cp.getTag(index);
if (tag != ConstantPool.STRING && tag != ConstantPool.CLASS if (tag != ConstantPool.STRING
&& tag != ConstantPool.INTEGER && tag != ConstantPool.FLOAT) && tag != ConstantPool.CLASS
&& tag != ConstantPool.INTEGER
&& tag != ConstantPool.FLOAT)
throw new ClassFormatException throw new ClassFormatException
("wrong constant tag: "+tag); ("wrong constant tag: "+tag);
instr = new ConstantInstruction instr = new ConstantInstruction
@ -555,8 +552,10 @@ class BasicBlockReader implements Opcodes {
case opc_ldc_w: { case opc_ldc_w: {
int index = input.readUnsignedShort(); int index = input.readUnsignedShort();
int tag = cp.getTag(index); int tag = cp.getTag(index);
if (tag != ConstantPool.STRING && tag != ConstantPool.CLASS if (tag != ConstantPool.STRING
&& tag != ConstantPool.INTEGER && tag != ConstantPool.FLOAT) && tag != ConstantPool.CLASS
&& tag != ConstantPool.INTEGER
&& tag != ConstantPool.FLOAT)
throw new ClassFormatException throw new ClassFormatException
("wrong constant tag: "+tag); ("wrong constant tag: "+tag);
instr = new ConstantInstruction instr = new ConstantInstruction

@ -35,6 +35,7 @@ class BasicBlockWriter implements Opcodes {
private class LVTEntry { private class LVTEntry {
int startAddr, endAddr; int startAddr, endAddr;
Instruction start, end;
LocalVariableInfo lvi; LocalVariableInfo lvi;
} }
@ -389,7 +390,8 @@ class BasicBlockWriter implements Opcodes {
length = 3; length = 3;
break; break;
case opc_invokeinterface: case opc_invokeinterface:
gcp.putRef(ConstantPool.INTERFACEMETHODREF, instr.getReference()); gcp.putRef(ConstantPool.INTERFACEMETHODREF,
instr.getReference());
length = 5; length = 5;
break; break;
case opc_new: case opc_new:

@ -183,7 +183,6 @@ public class BasicBlocks extends BinaryInfo implements Opcodes {
BitSet visited = new BitSet(); BitSet visited = new BitSet();
Stack todo = new Stack(); Stack todo = new Stack();
startBlock.stackHeight = 0; startBlock.stackHeight = 0;
todo.push(startBlock); todo.push(startBlock);
while (!todo.isEmpty()) { while (!todo.isEmpty()) {

@ -280,6 +280,7 @@ public final class Block {
if (succs[succs.length-1] == null) if (succs[succs.length-1] == null)
output.println("\treturn"); output.println("\treturn");
else else
output.println("\tgoto "+succs[succs.length-1]); output.println("\tgoto "+succs[succs.length-1]);
} }
} }

@ -867,6 +867,10 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
} }
if (deprecatedFlag) if (deprecatedFlag)
gcp.putUTF8("Deprecated"); gcp.putUTF8("Deprecated");
if (signature != null) {
gcp.putUTF8("Signature");
gcp.putUTF8(signature);
}
prepareAttributes(gcp); prepareAttributes(gcp);
} }
@ -934,6 +938,11 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
output.writeShort(gcp.putUTF8("Deprecated")); output.writeShort(gcp.putUTF8("Deprecated"));
output.writeInt(0); output.writeInt(0);
} }
if (signature != null) {
output.writeShort(gcp.putUTF8("Signature"));
output.writeInt(2);
output.writeShort(gcp.putUTF8(signature));
}
} }
@ -1193,14 +1202,20 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
/** /**
* Gets the type signature including template information of the class. * Gets the type signature including template information of the class.
* <b>WARNING:</b> This field may disappear and merged into getType later. * <b>WARNING:</b> This field may disappear and merged into getType later.
* @return the type signature. * The type signature of a class consists of the signature for the
* superclass followed by the signatures of the interfaces.
* @return the type signature, empty string for java.lang.Object.
* @see TypeSignature * @see TypeSignature
*/ */
public String getSignature() { public String getSignature() {
if (status < HIERARCHY) if (status < HIERARCHY)
throw new IllegalStateException("status is "+status); throw new IllegalStateException("status is "+status);
if (signature != null) if (signature != null) {
System.err.println("Sig(attrib) of "+this+": "+signature);/*XXX REMOVE*/
return signature; return signature;
}
if (superclass == null)
return "";
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append('L').append(superclass.getName().replace('.','/')) sb.append('L').append(superclass.getName().replace('.','/'))
.append(";"); .append(";");
@ -1208,6 +1223,7 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
sb.append('L').append(interfaces[i].getName().replace('.','/')) sb.append('L').append(interfaces[i].getName().replace('.','/'))
.append(";"); .append(";");
} }
System.err.println("Sig of "+this+": "+sb.toString());/*XXX REMOVE*/
return sb.toString(); return sb.toString();
} }

@ -146,6 +146,10 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
gcp.putUTF8("Synthetic"); gcp.putUTF8("Synthetic");
if (deprecatedFlag) if (deprecatedFlag)
gcp.putUTF8("Deprecated"); gcp.putUTF8("Deprecated");
if (signature != null) {
gcp.putUTF8("Signature");
gcp.putUTF8(signature);
}
prepareAttributes(gcp); prepareAttributes(gcp);
} }
@ -183,6 +187,11 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
output.writeShort(gcp.putUTF8("Deprecated")); output.writeShort(gcp.putUTF8("Deprecated"));
output.writeInt(0); output.writeInt(0);
} }
if (signature != null) {
output.writeShort(gcp.putUTF8("Signature"));
output.writeInt(2);
output.writeShort(gcp.putUTF8(signature));
}
} }
void write(GrowableConstantPool constantPool, void write(GrowableConstantPool constantPool,
@ -325,7 +334,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
public String toString() { public String toString() {
return "Field "+Modifier.toString(modifier)+" "+ return "Field "+Modifier.toString(modifier)+" "+
typeSig+" "+name; getSignature()+" "+name;
} }
} }

@ -234,6 +234,8 @@ public class GrowableConstantPool extends ConstantPool {
public int putConstant(Object c) { public int putConstant(Object c) {
if (c instanceof String) { if (c instanceof String) {
return putIndexed(STRING, c, putUTF8((String) c), 0); return putIndexed(STRING, c, putUTF8((String) c), 0);
} else if (c instanceof Reference) {
return putClassType(((Reference) c).getClazz());
} else { } else {
int tag; int tag;
if (c instanceof Integer) if (c instanceof Integer)
@ -279,6 +281,13 @@ public class GrowableConstantPool extends ConstantPool {
public int reserveConstant(Object c) { public int reserveConstant(Object c) {
if (c instanceof String) { if (c instanceof String) {
return putIndexed(STRING, c, -1, 0); return putIndexed(STRING, c, -1, 0);
} else if (c instanceof Reference) {
String name = ((Reference) c).getClazz();
if (name.charAt(0) == 'L')
name = name.substring(1, name.length()-1);
else if (name.charAt(0) != '[')
throw new IllegalArgumentException("wrong class type: "+name);
return putIndexed(CLASS, name, -1, 0);
} else { } else {
return putConstant(c); return putConstant(c);
} }

@ -147,6 +147,10 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
gcp.putUTF8("Synthetic"); gcp.putUTF8("Synthetic");
if (deprecatedFlag) if (deprecatedFlag)
gcp.putUTF8("Deprecated"); gcp.putUTF8("Deprecated");
if (signature != null) {
gcp.putUTF8("Signature");
gcp.putUTF8(signature);
}
prepareAttributes(gcp); prepareAttributes(gcp);
} }
@ -187,6 +191,11 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
output.writeShort(gcp.putUTF8("Deprecated")); output.writeShort(gcp.putUTF8("Deprecated"));
output.writeInt(0); output.writeInt(0);
} }
if (signature != null) {
output.writeShort(gcp.putUTF8("Signature"));
output.writeInt(2);
output.writeShort(gcp.putUTF8(signature));
}
} }
void write(GrowableConstantPool constantPool, void write(GrowableConstantPool constantPool,
@ -325,6 +334,6 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
* @return a string representation of this method. * @return a string representation of this method.
*/ */
public String toString() { public String toString() {
return "MethodInfo[name="+name+",type="+typeSig+"]"; return "MethodInfo[name="+name+",sig="+getSignature()+"]";
} }
} }

@ -18,6 +18,10 @@
*/ */
package net.sf.jode.bytecode; package net.sf.jode.bytecode;
///#def COLLECTIONS java.util
import java.util.ArrayList;
import java.util.Map;
///#enddef
/** /**
* This class contains some static methods to handle type signatures. <br> * This class contains some static methods to handle type signatures. <br>
@ -212,12 +216,21 @@ public class TypeSignature {
* @param position the index to the last entry. * @param position the index to the last entry.
* @return the index to the next entry. * @return the index to the next entry.
*/ */
static int skipType(String methodTypeSig, int position) { public static int skipType(String methodTypeSig, int position) {
char c = methodTypeSig.charAt(position++); char c = methodTypeSig.charAt(position++);
while (c == '[') while (c == '[')
c = methodTypeSig.charAt(position++); c = methodTypeSig.charAt(position++);
if (c == 'L') if (c == 'L' || c == 'T') {
return methodTypeSig.indexOf(';', position) + 1; int angledepth = 0;
c = methodTypeSig.charAt(position++);
while (c != ';' || angledepth > 0) {
if (c == '<')
angledepth++;
else if (c == '>')
angledepth--;
c = methodTypeSig.charAt(position++);
}
}
return position; return position;
} }
@ -262,12 +275,50 @@ public class TypeSignature {
return 1; return 1;
} }
/**
* Gets the argument type signatures of the given template signature.
* @param templateTypeSig the template type signature.
* @return an array containing all parameter types in correct order.
*/
public static String[] getArgumentTypes(String templateTypeSig) {
System.err.println(templateTypeSig);
int pos = 1;
int count = 0;
char c;
while ((c = templateTypeSig.charAt(pos)) != '>') {
if (c == '*') {
pos++;
} else {
if (c == '+' || c == '-')
pos++;
pos = skipType(templateTypeSig, pos);
}
count++;
}
String[] params = new String[count];
pos = 1;
for (int i = 0; i < count; i++) {
int start = pos;
c = templateTypeSig.charAt(pos);
if (c == '*') {
pos++;
} else {
if (c == '+' || c == '-')
pos++;
pos = skipType(templateTypeSig, pos);
}
params[i] = templateTypeSig.substring(start, pos);
}
return params;
}
/** /**
* Gets the parameter type signatures of the given method signature. * Gets the parameter type signatures of the given method signature.
* @param methodTypeSig the method type signature. * @param methodTypeSig the method type signature.
* @return an array containing all parameter types in correct order. * @return an array containing all parameter types in correct order.
*/ */
public static String[] getParameterTypes(String methodTypeSig) { public static String[] getParameterTypes(String methodTypeSig) {
System.err.println(methodTypeSig);
int pos = 1; int pos = 1;
int count = 0; int count = 0;
while (methodTypeSig.charAt(pos) != ')') { while (methodTypeSig.charAt(pos) != ')') {
@ -293,6 +344,230 @@ public class TypeSignature {
return methodTypeSig.substring(methodTypeSig.lastIndexOf(')')+1); return methodTypeSig.substring(methodTypeSig.lastIndexOf(')')+1);
} }
/**
* Gets the names and types of the generic parameters of the given type signature.
* @param typeSig the type signature.
* @return an array containing all generic parameters together with their
* type in correct order, or null if there aren't any generic parameters.
*/
public static String[] getGenericSignatures(String typeSig) {
System.err.println(typeSig);
if (typeSig.charAt(0) != '<')
return null;
int pos = 1;
int count = 0;
while (typeSig.charAt(pos) != '>') {
while (typeSig.charAt(pos) != ':')
pos++;
/* check for empty entry */
if (typeSig.charAt(pos+1) == ':')
pos++;
while (typeSig.charAt(pos) == ':') {
/* skip colon and type */
pos = skipType(typeSig, pos + 1);
}
count++;
}
String[] params = new String[count];
pos = 1;
count = 0;
while (typeSig.charAt(pos) != '>') {
int spos = pos;
while (typeSig.charAt(pos) != ':')
pos++;
/* check for empty entry */
if (typeSig.charAt(pos+1) == ':')
pos++;
while (typeSig.charAt(pos) == ':') {
/* skip colon and type */
pos = skipType(typeSig, pos + 1);
}
params[count++] = typeSig.substring(spos, pos);
}
return params;
}
/**
* Gets the names of the generic parameters of the given type signature.
* @param typeSig the type signature.
* @return an array containing all generic parameter types
* in correct order, or null if there aren't any generic parameters.
*/
public static String[] getGenericNames(String typeSig) {
System.err.println(typeSig);
if (typeSig.charAt(0) != '<')
return null;
int pos = 1;
int count = 0;
while (typeSig.charAt(pos) != '>') {
while (typeSig.charAt(pos) != ':')
pos++;
/* check for empty entry */
if (typeSig.charAt(pos+1) == ':')
pos++;
while (typeSig.charAt(pos) == ':') {
/* skip colon and type */
pos = skipType(typeSig, pos + 1);
}
count++;
}
String[] params = new String[count];
pos = 1;
count = 0;
while (typeSig.charAt(pos) != '>') {
int spos = pos;
while (typeSig.charAt(pos) != ':')
pos++;
params[count++] = typeSig.substring(spos, pos);
/* check for empty entry */
if (typeSig.charAt(pos+1) == ':')
pos++;
while (typeSig.charAt(pos) == ':') {
/* skip colon and type */
pos = skipType(typeSig, pos + 1);
}
}
return params;
}
/**
* Gets the signature of the super class from a class signature.
* @param typeSig the class's signature.
* @return the signature of the super class.
*/
public static String getSuperSignature(String typeSig) {
int pos = 0;
if (typeSig.charAt(0) == '<') {
/* Skip generic info */
pos++;
while (typeSig.charAt(pos) != '>') {
while (typeSig.charAt(pos) != ':')
pos++;
/* check for empty entry */
if (typeSig.charAt(pos+1) == ':')
pos++;
while (typeSig.charAt(pos) == ':') {
/* skip colon and type */
pos = skipType(typeSig, pos + 1);
}
}
pos++;
}
return typeSig.substring(pos, skipType(typeSig, pos));
}
/**
* Gets the signatures of the super interfaces from a class signature.
* @param typeSig the class's signature.
* @return an array containing the signatures of the interfaces.
*/
public static String[] getIfaceSignatures(String typeSig) {
int pos = 0;
if (typeSig.charAt(0) == '<') {
/* Skip generic info */
pos++;
while (typeSig.charAt(pos) != '>') {
while (typeSig.charAt(pos) != ':')
pos++;
/* check for empty entry */
if (typeSig.charAt(pos+1) == ':')
pos++;
while (typeSig.charAt(pos) == ':') {
/* skip colon and type */
pos = skipType(typeSig, pos + 1);
}
}
pos++;
}
pos = skipType(typeSig, pos);
ArrayList list = new ArrayList();
while (pos < typeSig.length()) {
int epos = skipType(typeSig, pos);
list.add(typeSig.substring(pos, epos));
pos = epos;
}
return (String[]) list.toArray(new String[list.size()]);
}
private static int mapGenericsInType(String typeSig, Map generics,
StringBuffer mapped, int spos) {
int pos = spos;
char c = typeSig.charAt(pos++);
while (c == '[')
c = typeSig.charAt(pos++);
if (c == 'T') {
int epos = typeSig.indexOf(';', pos);
String key = typeSig.substring(pos, epos);
String mapval = (String) generics.get(key);
if (mapval != null) {
mapped.append(typeSig.substring(spos, pos - 1))
.append(key);
spos = epos + 1;
}
pos = epos + 1;
} else if (c == 'L') {
c = typeSig.charAt(pos++);
while (c != ';' && c != '<')
c = typeSig.charAt(pos++);
if (c == '<') {
mapped.append(typeSig.substring(spos, pos));
while (typeSig.charAt(pos) != '>') {
pos = mapGenericsInType(typeSig, generics, mapped, pos);
}
spos = pos;
pos += 2;
}
}
mapped.append(typeSig.substring(spos, pos));
return pos;
}
/**
* Map the names of the generic parameters in the given type signature
* and return the type signature with the generic parameters mapped to
* (more or less) real types.
* @param typeSig the type signature.
* @param generics A map from generic names to type signatures.
* @return the mapped generic type signature.
*/
public static String mapGenerics(String typeSig, Map generics) {
StringBuffer mapped = new StringBuffer();
int pos = 0;
int spos = 0;
if (typeSig.length() == 0)
return "";
char c = typeSig.charAt(pos++);
if (c == '<') {
c = typeSig.charAt(pos++);
while (c != '>') {
while (c != ':') {
c = typeSig.charAt(pos++);
}
if (typeSig.charAt(pos) == ':')
pos++;
while (c == ':') {
mapped.append(typeSig.substring(spos, pos));
pos = mapGenericsInType(typeSig, generics, mapped, pos);
spos = pos;
c = typeSig.charAt(pos);
}
}
}
if (c == '(') {
while (typeSig.charAt(pos) != ')') {
mapped.append(typeSig.substring(spos, pos));
pos = mapGenericsInType(typeSig, generics, mapped, pos);
spos = pos;
}
pos++;
}
mapped.append(typeSig.substring(spos, pos));
while (pos < typeSig.length()) {
pos = mapGenericsInType(typeSig, generics, mapped, pos);
}
return mapped.toString();
}
/** /**
* Gets the default value an object of the given type has. It is * Gets the default value an object of the given type has. It is
* null for objects and arrays, Integer(0) for boolean and short * null for objects and arrays, Integer(0) for boolean and short
@ -328,19 +603,61 @@ public class TypeSignature {
/** /**
* Checks if there is a valid class name starting at index * Checks if there is a valid class name starting at index
* in string typesig and ending with a semicolon. * in string typeSig and ending with a semicolon.
* @return the index at which the class name ends. * @return the index at which the class name ends.
* @exception IllegalArgumentException if there was an illegal character. * @exception IllegalArgumentException if there was an illegal character.
* @exception StringIndexOutOfBoundsException if the typesig ended early. * @exception StringIndexOutOfBoundsException if the typeSig ended early.
*/ */
private static int checkClassName(String clName, int i) private static int checkClassName(String clName, int i)
throws IllegalArgumentException, StringIndexOutOfBoundsException throws IllegalArgumentException, StringIndexOutOfBoundsException
{
char c = clName.charAt(i++);
while (c != ';' && c != '.' && c != '<') {
if (c != '/' && !Character.isJavaIdentifierPart(c))
throw new IllegalArgumentException("Illegal java class name: "
+ clName);
c = clName.charAt(i++);
}
if (c == '<') {
c = clName.charAt(i++);
do {
if (c == '*')
i++;
else {
if (c == '+' || c == '-')
c = clName.charAt(i++);
if (c != 'L' && c != 'T' && c != '[')
throw new IllegalArgumentException
("Wrong class instantiation: "+clName);
i = checkTypeSig(clName, i - 1);
}
c = clName.charAt(i++);
} while (c != '>');
c = clName.charAt(i++);
}
if (c == '.')
return checkClassName(clName, i);
if (c != ';')
throw new IllegalArgumentException
("no ; after > in "+clName);
return i;
}
/**
* Checks if there is a valid class name starting at index
* in string typeSig and ending with a semicolon.
* @return the index at which the class name ends.
* @exception IllegalArgumentException if there was an illegal character.
* @exception StringIndexOutOfBoundsException if the typeSig ended early.
*/
private static int checkTemplateName(String clName, int i)
throws IllegalArgumentException, StringIndexOutOfBoundsException
{ {
while (true) { while (true) {
char c = clName.charAt(i++); char c = clName.charAt(i++);
if (c == ';') if (c == ';')
return i; return i;
if (c != '/' && !Character.isJavaIdentifierPart(c)) if (!Character.isJavaIdentifierPart(c))
throw new IllegalArgumentException("Illegal java class name: " throw new IllegalArgumentException("Illegal java class name: "
+ clName); + clName);
} }
@ -348,76 +665,149 @@ public class TypeSignature {
/** /**
* Checks if there is a valid simple type signature starting at index * Checks if there is a valid simple type signature starting at index
* in string typesig. * in string typeSig.
* @return the index at which the type signature ends. * @return the index at which the type signature ends.
* @exception IllegalArgumentException if there was an illegal character. * @exception IllegalArgumentException if there was an illegal character.
* @exception StringIndexOutOfBoundsException if the typesig ended early. * @exception StringIndexOutOfBoundsException if the typeSig ended early.
*/ */
private static int checkTypeSig(String typesig, int index) { private static int checkTypeSig(String typeSig, int index) {
char c = typesig.charAt(index++); char c = typeSig.charAt(index++);
while (c == '[') while (c == '[')
c = typesig.charAt(index++); c = typeSig.charAt(index++);
if (c == 'L') { if (c == 'L') {
index = checkClassName(typesig, index); index = checkClassName(typeSig, index);
} else if (c == 'T') {
index = checkTemplateName(typeSig, index);
} else { } else {
if ("ZBSCIJFD".indexOf(c) == -1) if ("ZBSCIJFD".indexOf(c) == -1)
throw new IllegalArgumentException("Type sig error: "+typesig); throw new IllegalArgumentException("Type sig error: "+typeSig);
} }
return index; return index;
} }
/**
* Checks whether a given type signature starts with valid generic
* part and returns the index where generics end.
* @param typeSig the type signature.
* @param i the start index.
* @exception NullPointerException if typeSig is null.
* @exception IllegalArgumentException if typeSig is not a valid
* type signature.
* @return 0 if no generics at beginning, otherwise the
* index after the &gt; sign.
*/
private static int checkGenerics(String typeSig, int i) {
if (typeSig.charAt(i) == '<') {
i++;
char c = typeSig.charAt(i++);
if (c == '>')
throw new IllegalArgumentException("Empty Generics: "+typeSig);
while (c != '>') {
if (c == ':')
throw new IllegalArgumentException("Empty type name: "+typeSig);
while (c != ':') {
if (!Character.isJavaIdentifierPart(c))
throw new IllegalArgumentException
("Illegal generic name: "+ typeSig);
c = typeSig.charAt(i++);
}
c = typeSig.charAt(i++);
if (c != 'L' && c != 'T' && c != ':')
throw new IllegalArgumentException
("Wrong generic extends: "+typeSig);
if (c != ':')
i = checkTypeSig(typeSig, i - 1);
c = typeSig.charAt(i++);
while(c == ':') {
i = checkTypeSig(typeSig, i);
c = typeSig.charAt(i++);
}
}
}
return i;
}
/** /**
* Checks whether a given type signature is a valid (not method) * Checks whether a given type signature is a valid (not method)
* type signature. Throws an exception otherwise. * type signature. Throws an exception otherwise.
* @param typesig the type signature. * @param typeSig the type signature.
* @exception NullPointerException if typeSig is null. * @exception NullPointerException if typeSig is null.
* @exception IllegalArgumentException if typeSig is not a valid * @exception IllegalArgumentException if typeSig is not a valid
* type signature or if it's a method type signature. * type signature or if it's a method type signature.
*/ */
public static void checkTypeSig(String typesig) public static void checkTypeSig(String typeSig)
throws IllegalArgumentException throws IllegalArgumentException
{ {
try { try {
if (checkTypeSig(typesig, 0) != typesig.length()) int i = checkGenerics(typeSig, 0);
if (checkTypeSig(typeSig, i) != typeSig.length())
throw new IllegalArgumentException throw new IllegalArgumentException
("Type sig too long: "+typesig); ("Type sig too long: "+typeSig);
} catch (StringIndexOutOfBoundsException ex) {
throw new IllegalArgumentException
("Incomplete type sig: "+typeSig);
}
}
/**
* Checks whether a given type signature is a valid class
* type signature. Throws an exception otherwise.
* A class type signature starts optionally with generics,
* followed by type signature of super class, followed by
* type signature of super interfaces.
* @param typeSig the type signature.
* @exception NullPointerException if typeSig is null.
* @exception IllegalArgumentException if typeSig is not a valid
* type signature or if it's a method type signature.
*/
public static void checkClassTypeSig(String typeSig)
throws IllegalArgumentException
{
try {
int i = checkGenerics(typeSig, 0);
i = checkTypeSig(typeSig, i);
while (i != typeSig.length()) {
i = checkTypeSig(typeSig, i);
}
} catch (StringIndexOutOfBoundsException ex) { } catch (StringIndexOutOfBoundsException ex) {
throw new IllegalArgumentException throw new IllegalArgumentException
("Incomplete type sig: "+typesig); ("Incomplete type sig: "+typeSig);
} }
} }
/** /**
* Checks whether a given type signature is a valid method * Checks whether a given type signature is a valid method
* type signature. Throws an exception otherwise. * type signature. Throws an exception otherwise.
* @param typesig the type signature. * @param typeSig the type signature.
* @exception NullPointerException if typeSig is null. * @exception NullPointerException if typeSig is null.
* @exception IllegalArgumentException if typeSig is not a valid * @exception IllegalArgumentException if typeSig is not a valid
* method type signature. * method type signature.
*/ */
public static void checkMethodTypeSig(String typesig) public static void checkMethodTypeSig(String typeSig)
throws IllegalArgumentException throws IllegalArgumentException
{ {
try { try {
if (typesig.charAt(0) != '(') int i = checkGenerics(typeSig, 0);
if (typeSig.charAt(i) != '(')
throw new IllegalArgumentException throw new IllegalArgumentException
("No method signature: "+typesig); ("No method signature: "+typeSig);
int i = 1; i++;
while (typesig.charAt(i) != ')') while (typeSig.charAt(i) != ')')
i = checkTypeSig(typesig, i); i = checkTypeSig(typeSig, i);
// skip closing parenthesis. // skip closing parenthesis.
i++; i++;
if (typesig.charAt(i) == 'V') if (typeSig.charAt(i) == 'V')
// accept void return type. // accept void return type.
i++; i++;
else else
i = checkTypeSig(typesig, i); i = checkTypeSig(typeSig, i);
if (i != typesig.length()) if (i != typeSig.length())
throw new IllegalArgumentException throw new IllegalArgumentException
("Type sig too long: "+typesig); ("Type sig too long: "+typeSig);
} catch (StringIndexOutOfBoundsException ex) { } catch (StringIndexOutOfBoundsException ex) {
throw new IllegalArgumentException throw new IllegalArgumentException
("Incomplete type sig: "+typesig); ("Incomplete type sig: "+typeSig);
} }
} }
} }

@ -24,7 +24,8 @@ import java.awt.Graphics;
import java.awt.Insets; import java.awt.Insets;
public class Applet extends java.applet.Applet { public class Applet extends java.applet.Applet {
private final int BORDER = 10; private static final long serialVersionUID = -132941289170424862L;
private final int BORDER = 10;
private final int BEVEL = 2; private final int BEVEL = 2;
private Window jodeWin = new Window(this); private Window jodeWin = new Window(this);
private Insets myInsets; private Insets myInsets;

@ -21,11 +21,14 @@ package net.sf.jode.decompiler;
import net.sf.jode.GlobalOptions; import net.sf.jode.GlobalOptions;
import net.sf.jode.type.MethodType; import net.sf.jode.type.MethodType;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.type.GenericParameterType;
import net.sf.jode.type.ClassType;
import net.sf.jode.bytecode.ClassFormatException; import net.sf.jode.bytecode.ClassFormatException;
import net.sf.jode.bytecode.ClassInfo; import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.bytecode.ClassPath; import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.bytecode.FieldInfo; import net.sf.jode.bytecode.FieldInfo;
import net.sf.jode.bytecode.MethodInfo; import net.sf.jode.bytecode.MethodInfo;
import net.sf.jode.bytecode.TypeSignature;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
import net.sf.jode.expr.ThisOperator; import net.sf.jode.expr.ThisOperator;
import net.sf.jode.flow.TransformConstructors; import net.sf.jode.flow.TransformConstructors;
@ -33,7 +36,11 @@ import net.sf.jode.flow.StructuredBlock;
import net.sf.jode.util.SimpleSet; import net.sf.jode.util.SimpleSet;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Vector; import java.util.Vector;
import java.util.Enumeration;
import java.io.IOException; import java.io.IOException;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
@ -46,8 +53,11 @@ public class ClassAnalyzer
{ {
ImportHandler imports; ImportHandler imports;
ClassInfo clazz; ClassInfo clazz;
ClassType myType;
ClassDeclarer parent; ClassDeclarer parent;
ProgressListener progressListener; ProgressListener progressListener;
String[] generics;
GenericParameterType[] genericTypes;
/** /**
* The complexity for initi#alizing a class. * The complexity for initi#alizing a class.
@ -92,9 +102,49 @@ public class ClassAnalyzer
throws ClassFormatException, IOException throws ClassFormatException, IOException
{ {
clazz.load(ClassInfo.ALL); clazz.load(ClassInfo.ALL);
String signature = clazz.getSignature();
if (signature.charAt(0) == '<') {
String[] genericSignatures = TypeSignature.getGenericSignatures(signature);
generics = new String[genericSignatures.length];
genericTypes = new GenericParameterType[genericSignatures.length];
for (int i = 0; i < generics.length; i++) {
int colon = genericSignatures[i].indexOf(':');
String genName;
if (colon == -1) {
generics[i] = genericSignatures[i];
genericTypes[i] =
new GenericParameterType(genericSignatures[i],
Type.tObject,
new ClassType[0]);
} else {
generics[i] = genericSignatures[i].substring(0, colon);
String remainder = genericSignatures[i].substring(colon+1);
int nextIndex = TypeSignature.skipType(remainder, 0);
List superClazzes = new ArrayList();
for (;;) {
String clazzSig = remainder.substring(0, nextIndex);
superClazzes.add(Type.tType(clazz.getClassPath(),
clazzSig));
if (nextIndex >= remainder.length())
break;
remainder = remainder.substring(nextIndex+1);
}
ClassType genSupClass = (ClassType) superClazzes.get(0);
if (!genSupClass.isInterface())
superClazzes.remove(0);
else
genSupClass = Type.tObject;
ClassType[] genSupIfaces = (ClassType[])
superClazzes.toArray(new ClassType[0]);
genericTypes[i] = new GenericParameterType(generics[i],
genSupClass,
genSupIfaces);
}
}
}
ClassInfo superClass = clazz.getSuperclass(); ClassInfo superClass = clazz.getSuperclass();
String myPackage = clazz.getName().substring String myPackage = clazz.getName().substring
(clazz.getName().lastIndexOf('.') + 1); (clazz.getName().lastIndexOf('.') + 1);
while (superClass != null) { while (superClass != null) {
int howMuch = (superClass.getName().startsWith(myPackage) int howMuch = (superClass.getName().startsWith(myPackage)
&& (superClass.getName().lastIndexOf('.') && (superClass.getName().lastIndexOf('.')
@ -117,6 +167,7 @@ public class ClassAnalyzer
this.parent = parent; this.parent = parent;
this.clazz = clazz; this.clazz = clazz;
this.myType = Type.tClass(clazz, genericTypes);
this.imports = imports; this.imports = imports;
modifiers = clazz.getModifiers(); modifiers = clazz.getModifiers();
@ -127,7 +178,7 @@ public class ClassAnalyzer
*/ */
if ((Options.options & Options.OPTION_INNER) != 0 if ((Options.options & Options.OPTION_INNER) != 0
&& parent instanceof ClassAnalyzer && !isStatic()) && parent instanceof ClassAnalyzer && !isStatic())
outerInstance = new ThisOperator(((ClassAnalyzer) parent).clazz); outerInstance = new ThisOperator((ClassAnalyzer) parent);
if (outerValues != null) if (outerValues != null)
this.outerValues = new OuterValues(this, outerValues); this.outerValues = new OuterValues(this, outerValues);
} }
@ -195,6 +246,10 @@ public class ClassAnalyzer
return clazz; return clazz;
} }
public ClassType getType() {
return myType;
}
public String getName() { public String getName() {
return name; return name;
@ -457,6 +512,9 @@ public class ClassAnalyzer
dumpDeclaration(writer, null, 0.0, 0.0); dumpDeclaration(writer, null, 0.0, 0.0);
} }
public void dumpGenericDeclaration(GenericParameterType gen) {
}
public void dumpDeclaration(TabbedPrintWriter writer, public void dumpDeclaration(TabbedPrintWriter writer,
ProgressListener pl, double done, double scale) ProgressListener pl, double done, double scale)
throws IOException throws IOException
@ -468,7 +526,7 @@ public class ClassAnalyzer
return; return;
} }
writer.startOp(TabbedPrintWriter.NO_PAREN, 0); writer.startOp(writer.NO_PAREN, 0);
/* Clear the SUPER bit, which is also used as SYNCHRONIZED bit. */ /* Clear the SUPER bit, which is also used as SYNCHRONIZED bit. */
int modifiedModifiers = modifiers & ~(Modifier.SYNCHRONIZED int modifiedModifiers = modifiers & ~(Modifier.SYNCHRONIZED
| STRICTFP); | STRICTFP);
@ -495,28 +553,23 @@ public class ClassAnalyzer
if (!clazz.isInterface()) if (!clazz.isInterface())
writer.print("class "); writer.print("class ");
writer.print(name); writer.print(name);
ClassInfo superClazz = clazz.getSuperclass(); if (genericTypes != null) {
if (superClazz != null && writer.print("<");
superClazz.getName() != "java.lang.Object") { writer.startOp(TabbedPrintWriter.EXPL_PAREN, 0);
writer.breakOp(); for (int i=0; i< genericTypes.length; i++) {
writer.print(" extends " + (writer.getClassString
(superClazz, Scope.CLASSNAME)));
}
ClassInfo[] interfaces = clazz.getInterfaces();
if (interfaces.length > 0) {
writer.breakOp();
writer.print(clazz.isInterface() ? " extends " : " implements ");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 1);
for (int i=0; i < interfaces.length; i++) {
if (i > 0) { if (i > 0) {
writer.print(", "); writer.print(", ");
writer.breakOp(); writer.breakOp();
} }
writer.print(writer.getClassString writer.print(genericTypes[i].getClassName());
(interfaces[i], Scope.CLASSNAME)); writer.printExtendsImplements(genericTypes[i]);
} }
writer.endOp(); writer.endOp();
writer.print(">");
} }
String signature = clazz.getSignature();
System.err.println("Class Signature: "+signature+ " (class "+name+")");
writer.printExtendsImplements(myType);
writer.println(); writer.println();
writer.openBraceClass(); writer.openBraceClass();
@ -630,7 +683,7 @@ public class ClassAnalyzer
needNewLine = true; needNewLine = true;
} }
writer.popScope(); writer.popScope();
clazz.drop(ClassInfo.DECLARATIONS); clazz.drop(clazz.DECLARATIONS);
} }
public void dumpSource(TabbedPrintWriter writer) public void dumpSource(TabbedPrintWriter writer)
@ -668,7 +721,6 @@ public class ClassAnalyzer
dumpSource(writer, pl, 0.8, 0.2); dumpSource(writer, pl, 0.8, 0.2);
if (pl != null) if (pl != null)
pl.updateProgress(1.0, name); pl.updateProgress(1.0, name);
writer.flush();
} }
public boolean isScopeOf(Object obj, int scopeType) { public boolean isScopeOf(Object obj, int scopeType) {
@ -705,9 +757,9 @@ public class ClassAnalyzer
} }
if (usageType == CLASSNAME || usageType == AMBIGUOUSNAME) { if (usageType == CLASSNAME || usageType == AMBIGUOUSNAME) {
try { try {
info.load(ClassInfo.DECLARATIONS); info.load(info.DECLARATIONS);
} catch (IOException ex) { } catch (IOException ex) {
info.guess(ClassInfo.DECLARATIONS); info.guess(info.DECLARATIONS);
} }
ClassInfo[] iinfos = info.getClasses(); ClassInfo[] iinfos = info.getClasses();
if (iinfos != null) { if (iinfos != null) {
@ -747,6 +799,18 @@ public class ClassAnalyzer
return getParent().getClassAnalyzer(cinfo); return getParent().getClassAnalyzer(cinfo);
} }
public GenericParameterType getGenericType(String name) {
if (genericTypes != null) {
for (int i = 0; i < genericTypes.length; i++) {
if (genericTypes[i].getClassName().equals(name))
return genericTypes[i];
}
}
if (parent != null)
return parent.getGenericType(name);
return null;
}
/** /**
* Get the class analyzer for the given inner class. * Get the class analyzer for the given inner class.
* @param name the short name of the inner class * @param name the short name of the inner class

@ -19,6 +19,8 @@
package net.sf.jode.decompiler; package net.sf.jode.decompiler;
import net.sf.jode.bytecode.ClassInfo; import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.type.GenericParameterType;
/** /**
* This is the interface for objects, that a method can declare * This is the interface for objects, that a method can declare
@ -30,6 +32,12 @@ public interface ClassDeclarer {
*/ */
public ClassDeclarer getParent(); public ClassDeclarer getParent();
/**
* Get the current class path.
* @return the current class path.
*/
public ClassPath getClassPath();
/** /**
* Get the class analyzer for the given anonymous class info. It * Get the class analyzer for the given anonymous class info. It
* will search it in the classes we declare and in the parent * will search it in the classes we declare and in the parent
@ -38,5 +46,13 @@ public interface ClassDeclarer {
*/ */
public ClassAnalyzer getClassAnalyzer(ClassInfo ci); public ClassAnalyzer getClassAnalyzer(ClassInfo ci);
/**
* Gets the generic type for the given named generic.
* @param name the name of the generic, e.g. K.
* @return the generic type for the named generic.
*/
public GenericParameterType getGenericType(String name);
public void addClassAnalyzer(ClassAnalyzer classAna); public void addClassAnalyzer(ClassAnalyzer classAna);
} }

@ -21,6 +21,8 @@ package net.sf.jode.decompiler;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.bytecode.FieldInfo; import net.sf.jode.bytecode.FieldInfo;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
import net.sf.jode.expr.ThisOperator;
import net.sf.jode.expr.LocalLoadOperator;
import net.sf.jode.expr.ConstOperator; import net.sf.jode.expr.ConstOperator;
import net.sf.jode.expr.OuterLocalOperator; import net.sf.jode.expr.OuterLocalOperator;
@ -49,13 +51,18 @@ public class FieldAnalyzer implements Analyzer {
imports = i; imports = i;
modifiers = fd.getModifiers(); modifiers = fd.getModifiers();
type = Type.tType(cla.getClassPath(), fd.getType()); type = Type.tType(cla.getClassPath(), cla.getType(), fd.getSignature());
fieldName = fd.getName(); fieldName = fd.getName();
constant = null; constant = null;
this.isSynthetic = fd.isSynthetic(); this.isSynthetic = fd.isSynthetic();
this.isDeprecated = fd.isDeprecated(); this.isDeprecated = fd.isDeprecated();
if (fd.getConstant() != null) { if (fd.getConstant() != null) {
constant = new ConstOperator(fd.getConstant()); if (fd.getConstant() instanceof String) {
constant = new ConstOperator(cla.getClassPath(),
(String) fd.getConstant());
} else {
constant = new ConstOperator(fd.getConstant());
}
constant.setType(type); constant.setType(type);
constant.makeInitializer(type); constant.makeInitializer(type);
} }

@ -21,6 +21,7 @@ package net.sf.jode.decompiler;
import net.sf.jode.GlobalOptions; import net.sf.jode.GlobalOptions;
import net.sf.jode.bytecode.ClassInfo; import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.bytecode.ClassPath; import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.type.SystemClassType;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.type.ArrayType; import net.sf.jode.type.ArrayType;
import net.sf.jode.type.ClassInfoType; import net.sf.jode.type.ClassInfoType;
@ -208,6 +209,7 @@ public class ImportHandler {
} }
public void dumpHeader(TabbedPrintWriter writer) public void dumpHeader(TabbedPrintWriter writer)
throws java.io.IOException
{ {
writer.println("/* "+ className writer.println("/* "+ className
+ " - Decompiled by JODE"); + " - Decompiled by JODE");
@ -320,7 +322,7 @@ public class ImportHandler {
useType(((ArrayType) type).getElementType()); useType(((ArrayType) type).getElementType());
else if (type instanceof ClassInfoType) else if (type instanceof ClassInfoType)
useClass(((ClassInfoType) type).getClassInfo()); useClass(((ClassInfoType) type).getClassInfo());
else if (type instanceof ClassType) else if (type instanceof SystemClassType)
useClass(((ClassType) type).getClassName()); useClass(((ClassType) type).getClassName());
} }
@ -371,6 +373,7 @@ public class ImportHandler {
String pkgName = name.substring(0, pkgdelim); String pkgName = name.substring(0, pkgdelim);
Integer i;
if (pkgName.equals(pkg) if (pkgName.equals(pkg)
|| (imports.get(pkgName+".*") != null || (imports.get(pkgName+".*") != null
&& !conflictsImport(name))) { && !conflictsImport(name))) {

@ -53,7 +53,6 @@ public class Main extends Options {
new LongOpt("debug", LongOpt.OPTIONAL_ARGUMENT, null, 'D'), new LongOpt("debug", LongOpt.OPTIONAL_ARGUMENT, null, 'D'),
new LongOpt("import", LongOpt.REQUIRED_ARGUMENT, null, 'i'), new LongOpt("import", LongOpt.REQUIRED_ARGUMENT, null, 'i'),
new LongOpt("style", LongOpt.REQUIRED_ARGUMENT, null, 's'), new LongOpt("style", LongOpt.REQUIRED_ARGUMENT, null, 's'),
new LongOpt("chars-per-line", LongOpt.REQUIRED_ARGUMENT, null, 'l'),
new LongOpt("lvt", LongOpt.OPTIONAL_ARGUMENT, null, new LongOpt("lvt", LongOpt.OPTIONAL_ARGUMENT, null,
OPTION_START+0), OPTION_START+0),
new LongOpt("inner", LongOpt.OPTIONAL_ARGUMENT, null, new LongOpt("inner", LongOpt.OPTIONAL_ARGUMENT, null,
@ -95,10 +94,8 @@ public class Main extends Options {
"The directories should be separated by ','."); "The directories should be separated by ','.");
err.println(" -d, --dest <dir> "+ err.println(" -d, --dest <dir> "+
"write decompiled files to disk into directory destdir."); "write decompiled files to disk into directory destdir.");
err.println(" -s, --style {sun|gnu|pascal|python} "+ err.println(" -s, --style {sun|gnu} "+
"specify indentation style"); "specify indentation style");
err.println(" -l, --chars-per-line <number> "+
"specify line length");
err.println(" -i, --import <pkglimit>,<clslimit>"); err.println(" -i, --import <pkglimit>,<clslimit>");
err.println(" "+ err.println(" "+
"import classes used more than clslimit times"); "import classes used more than clslimit times");
@ -215,8 +212,14 @@ public class Main extends Options {
} }
} }
public static void main(String[] params) throws Throwable{ public static void main(String[] params) {
decompile(params); try {
decompile(params);
} catch (ExceptionInInitializerError ex) {
ex.getException().printStackTrace();
} catch (Throwable ex) {
ex.printStackTrace();
}
/* When AWT applications are compiled with insufficient /* When AWT applications are compiled with insufficient
* classpath the type guessing by reflection code can * classpath the type guessing by reflection code can
* generate an awt thread that will prevent normal * generate an awt thread that will prevent normal
@ -247,13 +250,12 @@ public class Main extends Options {
int importClassLimit = ImportHandler.DEFAULT_CLASS_LIMIT;; int importClassLimit = ImportHandler.DEFAULT_CLASS_LIMIT;;
int outputStyle = TabbedPrintWriter.BRACE_AT_EOL; int outputStyle = TabbedPrintWriter.BRACE_AT_EOL;
int indentSize = 4; int indentSize = 4;
int outputLineLength = 79;
boolean keepGoing = false; boolean keepGoing = false;
GlobalOptions.err.println(GlobalOptions.copyright); GlobalOptions.err.println(GlobalOptions.copyright);
boolean errorInParams = false; boolean errorInParams = false;
Getopt g = new Getopt("net.sf.jode.decompiler.Main", params, "hVvkc:d:D:i:s:l:", Getopt g = new Getopt("net.sf.jode.decompiler.Main", params, "hVvkc:d:D:i:s:",
longOptions, true); longOptions, true);
for (int opt = g.getopt(); opt != -1; opt = g.getopt()) { for (int opt = g.getopt(); opt != -1; opt = g.getopt()) {
switch(opt) { switch(opt) {
@ -307,12 +309,9 @@ public class Main extends Options {
} else if (arg.equals("sun")) { } else if (arg.equals("sun")) {
outputStyle = TabbedPrintWriter.BRACE_AT_EOL; outputStyle = TabbedPrintWriter.BRACE_AT_EOL;
indentSize = 4; indentSize = 4;
} else if (arg.equals("pascal")) { } else if (arg.equals("pascal")) {
outputStyle = 0; outputStyle = 0;
indentSize = 4; indentSize = 4;
} else if (arg.equals("python") || arg.equals("codd")) {
outputStyle = TabbedPrintWriter.BRACE_AT_EOL|TabbedPrintWriter.CODD_FORMATTING;
indentSize = 4;
} else { } else {
GlobalOptions.err.println GlobalOptions.err.println
("net.sf.jode.decompiler.Main: Unknown style `"+arg+"'."); ("net.sf.jode.decompiler.Main: Unknown style `"+arg+"'.");
@ -320,18 +319,6 @@ public class Main extends Options {
} }
break; break;
} }
case 'l': {
String arg = g.getOptarg();
try {
outputLineLength = Integer.parseInt(arg.trim());
}
catch (RuntimeException rte) {
GlobalOptions.err.println(
"net.sf.jode.decompiler.Main: Invalid Linelength " + arg);
errorInParams = true;
}
break;
}
case 'i': { case 'i': {
String arg = g.getOptarg(); String arg = g.getOptarg();
int comma = arg.indexOf(','); int comma = arg.indexOf(',');
@ -378,7 +365,7 @@ public class Main extends Options {
TabbedPrintWriter writer = null; TabbedPrintWriter writer = null;
if (destDir == null) if (destDir == null)
writer = new TabbedPrintWriter(System.out, imports, true, writer = new TabbedPrintWriter(System.out, imports, true,
outputStyle, indentSize, 0, outputLineLength); outputStyle, indentSize, 0, 79);
else if (destDir.toLowerCase().endsWith(".zip") else if (destDir.toLowerCase().endsWith(".zip")
|| destDir.toLowerCase().endsWith(".jar")) { || destDir.toLowerCase().endsWith(".jar")) {
try { try {
@ -390,7 +377,7 @@ public class Main extends Options {
} }
writer = new TabbedPrintWriter(new BufferedOutputStream(destZip), writer = new TabbedPrintWriter(new BufferedOutputStream(destZip),
imports, false, imports, false,
outputStyle, indentSize, 0, outputLineLength); outputStyle, indentSize, 0, 79);
} }
for (int i= g.getOptind(); i< params.length; i++) { for (int i= g.getOptind(); i< params.length; i++) {
try { try {

@ -22,13 +22,16 @@ import net.sf.jode.GlobalOptions;
import net.sf.jode.bytecode.BasicBlocks; import net.sf.jode.bytecode.BasicBlocks;
import net.sf.jode.bytecode.Block; import net.sf.jode.bytecode.Block;
import net.sf.jode.bytecode.ClassInfo; import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.bytecode.Handler; import net.sf.jode.bytecode.Handler;
import net.sf.jode.bytecode.Instruction; import net.sf.jode.bytecode.Instruction;
import net.sf.jode.bytecode.LocalVariableInfo; import net.sf.jode.bytecode.LocalVariableInfo;
import net.sf.jode.bytecode.MethodInfo; import net.sf.jode.bytecode.MethodInfo;
import net.sf.jode.bytecode.TypeSignature;
import net.sf.jode.jvm.SyntheticAnalyzer; import net.sf.jode.jvm.SyntheticAnalyzer;
import net.sf.jode.type.*; import net.sf.jode.type.*;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
import net.sf.jode.expr.ConstOperator;
import net.sf.jode.expr.CheckNullOperator; import net.sf.jode.expr.CheckNullOperator;
import net.sf.jode.expr.ThisOperator; import net.sf.jode.expr.ThisOperator;
import net.sf.jode.expr.LocalLoadOperator; import net.sf.jode.expr.LocalLoadOperator;
@ -37,15 +40,23 @@ import net.sf.jode.expr.InvokeOperator;
import net.sf.jode.flow.StructuredBlock; import net.sf.jode.flow.StructuredBlock;
import net.sf.jode.flow.FlowBlock; import net.sf.jode.flow.FlowBlock;
import net.sf.jode.flow.TransformExceptionHandlers; import net.sf.jode.flow.TransformExceptionHandlers;
import net.sf.jode.flow.Jump;
import net.sf.jode.jvm.CodeVerifier; import net.sf.jode.jvm.CodeVerifier;
import net.sf.jode.jvm.VerifyException; import net.sf.jode.jvm.VerifyException;
import net.sf.jode.util.SimpleMap;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.BitSet;
import java.util.Stack;
import java.util.Vector; import java.util.Vector;
import java.util.Enumeration; import java.util.Enumeration;
import java.io.DataInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.List;
import java.util.Map;
import java.util.Collection; import java.util.Collection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
@ -178,6 +189,11 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
* classes that are used in this method. * classes that are used in this method.
*/ */
Collection usedAnalyzers; Collection usedAnalyzers;
/**
* This array contains the generic types this method declares if
* it is generic.
*/
GenericParameterType[] genericTypes;
/** /**
* This is the default constructor. * This is the default constructor.
@ -191,7 +207,47 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
this.imports = imports; this.imports = imports;
this.minfo = minfo; this.minfo = minfo;
this.methodName = minfo.getName(); this.methodName = minfo.getName();
this.methodType = Type.tMethod(cla.getClassPath(), minfo.getType()); String signature = minfo.getSignature();
if (signature.charAt(0) == '<') {
String[] genericSignatures =
TypeSignature.getGenericSignatures(signature);
genericTypes = new GenericParameterType[genericSignatures.length];
for (int i = 0; i < genericTypes.length; i++) {
int colon = genericSignatures[i].indexOf(':');
String genName;
if (colon == -1) {
genericTypes[i] =
new GenericParameterType(genericSignatures[i],
Type.tObject,
new ClassType[0]);
} else {
String genname = genericSignatures[i].substring(0, colon);
String remainder = genericSignatures[i].substring(colon+1);
int nextIndex = TypeSignature.skipType(remainder, 0);
List superClazzes = new ArrayList();
for (;;) {
String clazzSig = remainder.substring(0, nextIndex);
superClazzes.add(Type.tType(classAnalyzer.getClassPath(),
classAnalyzer.getType(), clazzSig));
if (nextIndex >= remainder.length())
break;
remainder = remainder.substring(nextIndex+1);
}
ClassType genSupClass = (ClassType) superClazzes.get(0);
if (!genSupClass.isInterface())
superClazzes.remove(0);
else
genSupClass = Type.tObject;
ClassType[] genSupIfaces = (ClassType[])
superClazzes.toArray(new ClassType[0]);
genericTypes[i] = new GenericParameterType(genname,
genSupClass,
genSupIfaces);
}
}
}
this.methodType = Type.tMethod(cla.getClassPath(), cla.getType(), signature, genericTypes);
this.isConstructor = this.isConstructor =
methodName.equals("<init>") || methodName.equals("<clinit>"); methodName.equals("<init>") || methodName.equals("<clinit>");
@ -415,8 +471,10 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
LocalInfo li = new LocalInfo(this, lvi.getSlot()); LocalInfo li = new LocalInfo(this, lvi.getSlot());
if ((Options.options & Options.OPTION_LVT) != 0 if ((Options.options & Options.OPTION_LVT) != 0
&& lvi.getName() != null) && lvi.getName() != null)
li.addHint(lvi.getName(), Type.tType(classAnalyzer.getClassPath(), li.addHint(lvi.getName(),
lvi.getType())); Type.tType(classAnalyzer.getClassPath(),
classAnalyzer.getType(),
lvi.getType()));
allLocals.addElement(li); allLocals.addElement(li);
return li; return li;
} }
@ -433,7 +491,7 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
Block[] blocks = bb.getBlocks(); Block[] blocks = bb.getBlocks();
for (int i=0; i < blocks.length; i++) for (int i=0; i < blocks.length; i++)
count += blocks[i].getInstructions().length; count += blocks[i].getInstructions().length;
return count; return (double) count;
} }
} }
@ -453,12 +511,15 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
Block[] blocks = bb.getBlocks(); Block[] blocks = bb.getBlocks();
FlowBlock[] flows = new FlowBlock[blocks.length]; FlowBlock[] flows = new FlowBlock[blocks.length];
TransformExceptionHandlers excHandlers; TransformExceptionHandlers excHandlers;
{ {
for (int i=0; i < blocks.length; i++) for (int i=0; i < blocks.length; i++)
flows[i] = new FlowBlock(this, i, i > 0 ? flows[i-1]: null); flows[i] = new FlowBlock(this, i, i > 0 ? flows[i-1]: null);
/* We transform every basic block into a FlowBlock /* While we read the opcodes into FlowBlocks
* we try to combine sequential blocks, as soon as we
* find two sequential instructions in a row, where the
* second has no predecessors.
*/ */
int count = 0; int count = 0;
for (int i=0; i < blocks.length; i++) { for (int i=0; i < blocks.length; i++) {
@ -507,23 +568,22 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
excHandlers = new TransformExceptionHandlers(flows); excHandlers = new TransformExceptionHandlers(flows);
for (int i=0; i<handlers.length; i++) { for (int i=0; i<handlers.length; i++) {
Type type = null; Type type = null;
int start = handlers[i].getStart().getBlockNr(); FlowBlock start = flows[handlers[i].getStart().getBlockNr()];
int end = handlers[i].getEnd().getBlockNr(); FlowBlock end = flows[handlers[i].getEnd().getBlockNr()];
FlowBlock handler = flows[handlers[i].getCatcher().getBlockNr()]; FlowBlock handler
= flows[handlers[i].getCatcher().getBlockNr()];
if (handlers[i].getType() != null) if (handlers[i].getType() != null)
type = Type.tClass(classAnalyzer.getClassPath(), type = Type.tClass(classAnalyzer.getClassPath(),
handlers[i].getType()); handlers[i].getType());
for (int j = start; j <= end; j++) {
if (flows[j] != handler) excHandlers.addHandler(start, end, handler, type);
flows[j].addExceptionHandler(type, handler);
}
} }
} }
if (GlobalOptions.verboseLevel > 0) if (GlobalOptions.verboseLevel > 0)
GlobalOptions.err.print('-'); GlobalOptions.err.print('-');
//excHandlers.analyze(); excHandlers.analyze();
methodHeader.analyze(); methodHeader.analyze();
methodHeader.removeStartPred(); methodHeader.removeStartPred();
@ -572,11 +632,10 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
int offset = 0; int offset = 0;
int slot = 0; int slot = 0;
if (!isStatic()) { if (!isStatic()) {
ClassInfo classInfo = classAnalyzer.getClazz();
param[offset] = getLocalInfo(bb != null param[offset] = getLocalInfo(bb != null
? bb.getParamInfo(slot) ? bb.getParamInfo(slot)
: LocalVariableInfo.getInfo(slot)); : LocalVariableInfo.getInfo(slot));
param[offset].setExpression(new ThisOperator(classInfo, true)); param[offset].setExpression(new ThisOperator(classAnalyzer, true));
slot++; slot++;
offset++; offset++;
} }
@ -607,6 +666,7 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
public void analyzeInnerClasses() public void analyzeInnerClasses()
throws ClassFormatError throws ClassFormatError
{ {
int serialnr = 0;
Enumeration elts = anonConstructors.elements(); Enumeration elts = anonConstructors.elements();
while (elts.hasMoreElements()) { while (elts.hasMoreElements()) {
InvokeOperator cop = (InvokeOperator) elts.nextElement(); InvokeOperator cop = (InvokeOperator) elts.nextElement();
@ -682,10 +742,10 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
if (synth != null) { if (synth != null) {
// We don't need this class anymore (hopefully?) // We don't need this class anymore (hopefully?)
if (synth.getKind() == SyntheticAnalyzer.GETCLASS) if (synth.getKind() == synth.GETCLASS)
return true; return true;
if (synth.getKind() >= SyntheticAnalyzer.ACCESSGETFIELD if (synth.getKind() >= synth.ACCESSGETFIELD
&& synth.getKind() <= SyntheticAnalyzer.ACCESSDUPPUTSTATIC && synth.getKind() <= synth.ACCESSDUPPUTSTATIC
&& (Options.options & Options.OPTION_INNER) != 0 && (Options.options & Options.OPTION_INNER) != 0
&& (Options.options & Options.OPTION_ANON) != 0) && (Options.options & Options.OPTION_ANON) != 0)
return true; return true;
@ -814,8 +874,8 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
| Modifier.PROTECTED | Modifier.PRIVATE); | Modifier.PROTECTED | Modifier.PRIVATE);
modifiedModifiers &= ~STRICTFP; modifiedModifiers &= ~STRICTFP;
writer.startOp(TabbedPrintWriter.NO_PAREN, 0); writer.startOp(writer.NO_PAREN, 0);
writer.startOp(TabbedPrintWriter.NO_PAREN, 5); writer.startOp(writer.NO_PAREN, 5);
String delim =""; String delim ="";
if (minfo.isSynthetic()) { if (minfo.isSynthetic()) {
@ -859,7 +919,7 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
writer.breakOp(); writer.breakOp();
writer.printOptionalSpace(); writer.printOptionalSpace();
writer.print("("); writer.print("(");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 0); writer.startOp(writer.EXPL_PAREN, 0);
int offset = skipParams + (isStatic() ? 0 : 1); int offset = skipParams + (isStatic() ? 0 : 1);
for (int i = offset; i < param.length; i++) { for (int i = offset; i < param.length; i++) {
if (i > offset) { if (i > offset) {
@ -875,7 +935,7 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
if (exceptions.length > 0) { if (exceptions.length > 0) {
writer.breakOp(); writer.breakOp();
writer.print(" throws "); writer.print(" throws ");
writer.startOp(TabbedPrintWriter.NO_PAREN, 0); writer.startOp(writer.NO_PAREN, 0);
for (int i= 0; i< exceptions.length; i++) { for (int i= 0; i< exceptions.length; i++) {
if (i > 0) { if (i > 0) {
writer.print(", "); writer.print(", ");
@ -982,7 +1042,7 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
} }
public void analyzeInvokeOperator(InvokeOperator cop) { public void analyzeInvokeOperator(InvokeOperator cop) {
ClassInfo clazz = cop.getClassInfo(); ClassInfo clazz = (ClassInfo) cop.getClassInfo();
ClassAnalyzer anonAnalyzer = getParent().getClassAnalyzer(clazz); ClassAnalyzer anonAnalyzer = getParent().getClassAnalyzer(clazz);
if (anonAnalyzer == null) { if (anonAnalyzer == null) {
@ -1000,7 +1060,7 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
expr).getSubExpressions()[0]; expr).getSubExpressions()[0];
if (expr instanceof ThisOperator) { if (expr instanceof ThisOperator) {
outerValueArray[j] = outerValueArray[j] =
new ThisOperator(((ThisOperator) expr).getClassInfo()); new ThisOperator(((ThisOperator) expr).getClassAnalyzer());
continue; continue;
} }
LocalInfo li = null; LocalInfo li = null;
@ -1098,6 +1158,23 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
return getParent().getClassAnalyzer(cinfo); return getParent().getClassAnalyzer(cinfo);
} }
public GenericParameterType getGenericType(String name) {
if (genericTypes != null) {
for (int i = 0; i < genericTypes.length; i++) {
if (genericTypes[i].getClassName().equals(name))
return genericTypes[i];
}
}
return getParent().getGenericType(name);
}
/**
* Gets the current class path.
*/
public ClassPath getClassPath() {
return classAnalyzer.getClassPath();
}
public void addClassAnalyzer(ClassAnalyzer clazzAna) { public void addClassAnalyzer(ClassAnalyzer clazzAna) {
if (innerAnalyzers == null) if (innerAnalyzers == null)
innerAnalyzers = new Vector(); innerAnalyzers = new Vector();

@ -20,9 +20,12 @@
package net.sf.jode.decompiler; package net.sf.jode.decompiler;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.type.IntegerType; import net.sf.jode.type.IntegerType;
import net.sf.jode.type.MethodType;
import net.sf.jode.expr.*; import net.sf.jode.expr.*;
import net.sf.jode.flow.*; import net.sf.jode.flow.*;
import net.sf.jode.bytecode.*; import net.sf.jode.bytecode.*;
import java.io.*;
import java.util.Vector;
/** /**
* This is an abstract class which creates flow blocks for the * This is an abstract class which creates flow blocks for the
@ -84,6 +87,12 @@ public abstract class Opcodes implements net.sf.jode.bytecode.Opcodes {
return new SpecialBlock(type, stackcount, param); return new SpecialBlock(type, stackcount, param);
} }
private static StructuredBlock createGoto(MethodAnalyzer ma,
Instruction instr)
{
return new EmptyBlock();
}
private static StructuredBlock createJsr(MethodAnalyzer ma, private static StructuredBlock createJsr(MethodAnalyzer ma,
Instruction instr) Instruction instr)
{ {
@ -143,7 +152,10 @@ public abstract class Opcodes implements net.sf.jode.bytecode.Opcodes {
if (instr.getConstant() instanceof Reference) { if (instr.getConstant() instanceof Reference) {
Reference ref = (Reference) instr.getConstant(); Reference ref = (Reference) instr.getConstant();
expr = new ClassFieldOperator expr = new ClassFieldOperator
(Type.tType(cp, ref.getClazz())); (Type.tType(ma.getClassPath(), null, ref.getType()),
Type.tType(ma.getClassPath(), null, ref.getClazz()));
} else if (instr.getConstant() instanceof String) {
expr = new ConstOperator(cp, (String) instr.getConstant());
} else { } else {
expr = new ConstOperator(instr.getConstant()); expr = new ConstOperator(instr.getConstant());
} }

@ -35,7 +35,7 @@ public class Options {
public static int options = public static int options =
OPTION_LVT | OPTION_INNER | OPTION_ANON | OPTION_PRETTY | OPTION_LVT | OPTION_INNER | OPTION_ANON | OPTION_PRETTY |
OPTION_DECRYPT | OPTION_VERIFY | OPTION_CONTRAFO | OPTION_PUSH; OPTION_DECRYPT | OPTION_VERIFY | OPTION_CONTRAFO;
public final static boolean doAnonymous() { public final static boolean doAnonymous() {
return (options & OPTION_ANON) != 0; return (options & OPTION_ANON) != 0;

@ -23,6 +23,7 @@ import net.sf.jode.expr.Expression;
import net.sf.jode.expr.ThisOperator; import net.sf.jode.expr.ThisOperator;
import net.sf.jode.expr.LocalLoadOperator; import net.sf.jode.expr.LocalLoadOperator;
import net.sf.jode.expr.OuterLocalOperator; import net.sf.jode.expr.OuterLocalOperator;
import net.sf.jode.util.SimpleMap;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import java.util.Vector; import java.util.Vector;
@ -323,6 +324,13 @@ public class OuterValues
implicitOuterClass = value; implicitOuterClass = value;
} }
private static int countSlots(Expression[] exprs, int length) {
int slots = 0;
for (int i=0; i < length; i++)
slots += exprs[i].getType().stackSize();
return slots;
}
public void setMinCount(int newMin) { public void setMinCount(int newMin) {
if (headCount < newMin) { if (headCount < newMin) {
GlobalOptions.err.println GlobalOptions.err.println

@ -22,6 +22,7 @@ import java.io.*;
import java.util.Stack; import java.util.Stack;
import java.util.Vector; import java.util.Vector;
import java.util.Enumeration; import java.util.Enumeration;
import net.sf.jode.GlobalOptions;
import net.sf.jode.bytecode.ClassInfo; import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.type.*; import net.sf.jode.type.*;
@ -41,7 +42,6 @@ public class TabbedPrintWriter {
public static final int BRACE_AT_EOL = 0x10; public static final int BRACE_AT_EOL = 0x10;
public static final int INDENT_BRACES = 0x20; public static final int INDENT_BRACES = 0x20;
public static final int GNU_SPACING = 0x40; public static final int GNU_SPACING = 0x40;
public static final int CODD_FORMATTING = 0x80; // allow trailing CLOSING braces as well
/** /**
* This string contains a few tab characters followed by tabWidth - 1 * This string contains a few tab characters followed by tabWidth - 1
@ -74,16 +74,17 @@ public class TabbedPrintWriter {
/* The fast way. */ /* The fast way. */
return tabSpaceString.substring(FASTINDENT - tabs, return tabSpaceString.substring(FASTINDENT - tabs,
FASTINDENT + indent); FASTINDENT + indent);
} else {
/* the not so fast way */
StringBuffer sb = new StringBuffer(tabs + indent);
while (tabs > FASTINDENT) {
sb.append(tabSpaceString.substring(0, FASTINDENT));
tabs -= 20;
}
sb.append(tabSpaceString.substring(FASTINDENT - tabs,
FASTINDENT + indent));
return sb.toString();
} }
/* the not so fast way */
StringBuffer sb = new StringBuffer(tabs + indent);
while (tabs > FASTINDENT) {
sb.append(tabSpaceString.substring(0, FASTINDENT));
tabs -= 20;
}
sb.append(tabSpaceString.substring(FASTINDENT - tabs,
FASTINDENT + indent));
return sb.toString();
} }
class BreakPoint { class BreakPoint {
@ -459,10 +460,7 @@ public class TabbedPrintWriter {
public TabbedPrintWriter (OutputStream os, ImportHandler imports, public TabbedPrintWriter (OutputStream os, ImportHandler imports,
boolean autoFlush, int style, boolean autoFlush, int style,
int indentSize, int tabWidth, int lineWidth) { int indentSize, int tabWidth, int lineWidth) {
if ((style & CODD_FORMATTING) != 0) pw = new PrintWriter(os, autoFlush);
pw = new PrintWriter(new NlRemover(new OutputStreamWriter(os), tabWidth), autoFlush);
else
pw = new PrintWriter(os, autoFlush);
this.imports = imports; this.imports = imports;
this.style = style; this.style = style;
this.indentsize = indentSize; this.indentsize = indentSize;
@ -471,11 +469,10 @@ public class TabbedPrintWriter {
init(); init();
} }
public TabbedPrintWriter (Writer os, ImportHandler imports, boolean autoFlush, int style, int indentSize, int tabWidth, int lineWidth) { public TabbedPrintWriter (Writer os, ImportHandler imports,
if ((style & CODD_FORMATTING) != 0) boolean autoFlush, int style,
pw = new PrintWriter(new NlRemover(os, tabWidth), autoFlush); int indentSize, int tabWidth, int lineWidth) {
else { pw = new PrintWriter(os, autoFlush);
pw = new PrintWriter(os, autoFlush); }
this.imports = imports; this.imports = imports;
this.style = style; this.style = style;
this.indentsize = indentSize; this.indentsize = indentSize;
@ -495,19 +492,19 @@ public class TabbedPrintWriter {
} }
public TabbedPrintWriter (OutputStream os, ImportHandler imports) { public TabbedPrintWriter (OutputStream os, ImportHandler imports) {
this(os, imports, true); this(os, imports, true, BRACE_AT_EOL, 4, 8, 79);
} }
public TabbedPrintWriter (Writer os, ImportHandler imports) { public TabbedPrintWriter (Writer os, ImportHandler imports) {
this(os, imports, true); this(os, imports, true, BRACE_AT_EOL, 4, 8, 79);
} }
public TabbedPrintWriter (OutputStream os) { public TabbedPrintWriter (OutputStream os) {
this(os, null); this(os, null, true, BRACE_AT_EOL, 4, 8, 79);
} }
public TabbedPrintWriter (Writer os) { public TabbedPrintWriter (Writer os) {
this(os, null); this(os, null, true, BRACE_AT_EOL, 4, 8, 79);
} }
private void init() { private void init() {
@ -519,7 +516,7 @@ public class TabbedPrintWriter {
private void initTabString() { private void initTabString() {
char tabChar = '\t'; char tabChar = '\t';
if (tabWidth <= 1) { if (tabWidth == 0) {
/* If tabWidth is 0 use spaces instead of tabs. */ /* If tabWidth is 0 use spaces instead of tabs. */
tabWidth = 1; tabWidth = 1;
tabChar = ' '; tabChar = ' ';
@ -622,6 +619,29 @@ public class TabbedPrintWriter {
print(getTypeString(type)); print(getTypeString(type));
} }
public void printExtendsImplements(ClassType clazz) {
ClassType superClazz = clazz.getSuperClass();
if (superClazz != null &&
superClazz.getClassName() != "java.lang.Object") {
breakOp();
print(" extends " + getTypeString(superClazz));
}
ClassType[] interfaces = clazz.getInterfaces();
if (interfaces.length > 0) {
breakOp();
print(clazz.isInterface() ? " extends " : " implements ");
startOp(EXPL_PAREN, 1);
for (int i=0; i < interfaces.length; i++) {
if (i > 0) {
print(", ");
breakOp();
}
print(getTypeString(interfaces[i]));
}
endOp();
}
}
public void pushScope(Scope scope) { public void pushScope(Scope scope) {
scopes.push(scope); scopes.push(scope);
} }
@ -693,7 +713,8 @@ public class TabbedPrintWriter {
if (scope != null) if (scope != null)
return "NAME CONFLICT " + className; return "NAME CONFLICT " + className;
return "UNREACHABLE " + className; else
return "UNREACHABLE " + className;
} }
if (imports != null) { if (imports != null) {
String importedName = imports.getClassString(clazz); String importedName = imports.getClassString(clazz);
@ -710,8 +731,21 @@ public class TabbedPrintWriter {
if (type instanceof ArrayType) if (type instanceof ArrayType)
return getTypeString(((ArrayType) type).getElementType()) + "[]"; return getTypeString(((ArrayType) type).getElementType()) + "[]";
else if (type instanceof ClassInfoType) { else if (type instanceof ClassInfoType) {
ClassInfo clazz = ((ClassInfoType) type).getClassInfo(); ClassInfoType classInfoType = (ClassInfoType) type;
return getClassString(clazz, Scope.CLASSNAME); ClassInfo clazz = classInfoType.getClassInfo();
String clazzName = getClassString(clazz, Scope.CLASSNAME);
Type[] genInstances = classInfoType.getGenericInstances();
if (genInstances == null)
return clazzName;
StringBuffer sb = new StringBuffer(clazzName);
sb.append("<");
for (int i = 0; i < genInstances.length; i++) {
if (i > 0)
sb.append(",");
sb.append(getTypeString(genInstances[i]));
}
sb.append(">");
return sb.toString();
} else if (type instanceof ClassType) { } else if (type instanceof ClassType) {
String name = ((ClassType) type).getClassName(); String name = ((ClassType) type).getClassName();
if (imports != null) { if (imports != null) {
@ -793,7 +827,7 @@ public class TabbedPrintWriter {
} }
public void closeBraceContinue() { public void closeBraceContinue() {
if ((style & (BRACE_AT_EOL|CODD_FORMATTING)) == BRACE_AT_EOL) if ((style & BRACE_AT_EOL) != 0)
print("} "); print("} ");
else else
println("}"); println("}");
@ -825,84 +859,3 @@ public class TabbedPrintWriter {
pw.close(); pw.close();
} }
} }
class NlRemover extends Writer {
private int tabWidth;
private Writer out;
private int pendingNL;
private boolean lastWasClBr;
private int pendingSpace;
public NlRemover(Writer to, int tabWidth) {
this.out = to;
this.tabWidth = tabWidth; }
public void close() throws IOException {
if (out != null) {
while (pendingNL > 0) {
out.write('\n');
pendingNL--;
}
out.close();
out = null;
}
}
public void flush() throws IOException {
if (out != null) {
while (pendingNL > 0) {
out.write('\n');
pendingNL--;
}
out.flush();
}
}
public void write(int x) throws IOException {
switch ((char)x) {
case '}':
if (! lastWasClBr && pendingSpace > 0)
out.write(' ');
out.write('}');
pendingSpace = 0;
pendingNL = 0;
lastWasClBr = true;
return;
case '\r':
pendingSpace = 0;
return;
case '\n':
if (pendingNL > 0) {
out.write('\n'); }
else
pendingNL++;
pendingSpace = 0;
return;
case '\t':
pendingSpace = (pendingSpace + tabWidth) / tabWidth * tabWidth;
return;
case ' ':
pendingSpace += 1;
return;
default:
while (pendingNL > 0) {
out.write('\n');
pendingNL--;
}
while (pendingSpace > 0) {
out.write(' ');
pendingSpace--;
}
out.write(x);
lastWasClBr = false;
}
}
public void write(char[] cbuf, int off, int len) throws IOException {
len+=off;
while (off < len)
write(cbuf[off++]);
}
}

@ -18,6 +18,7 @@
*/ */
package net.sf.jode.decompiler; package net.sf.jode.decompiler;
import java.applet.*;
import java.awt.*; import java.awt.*;
///#ifndef AWT10 ///#ifndef AWT10
import java.awt.event.*; import java.awt.event.*;
@ -181,7 +182,7 @@ public class Window
FileDialog.SAVE); FileDialog.SAVE);
fd.setFile(lastClassName.substring fd.setFile(lastClassName.substring
(lastClassName.lastIndexOf('.')+1).concat(".java")); (lastClassName.lastIndexOf('.')+1).concat(".java"));
fd.setVisible(true); fd.show();
String fileName = fd.getFile(); String fileName = fd.getFile();
if (fileName == null) if (fileName == null)
return; return;
@ -301,6 +302,6 @@ public class Window
}); });
///#endif ///#endif
frame.pack(); frame.pack();
frame.setVisible(true); frame.show();
} }
} }

@ -41,7 +41,7 @@ public class ArrayStoreOperator extends ArrayLoadOperator
if (!elemType.isOfType(getType())) { if (!elemType.isOfType(getType())) {
/* We need an explicit widening cast */ /* We need an explicit widening cast */
writer.print("("); writer.print("(");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 1); writer.startOp(writer.EXPL_PAREN, 1);
writer.print("("); writer.print("(");
writer.printType(Type.tArray(getType().getHint())); writer.printType(Type.tArray(getType().getHint()));
writer.print(") "); writer.print(") ");

@ -19,13 +19,14 @@
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;
public class ClassFieldOperator extends NoArgOperator { public class ClassFieldOperator extends NoArgOperator {
Type classType; Type classType;
public ClassFieldOperator(Type classType) { public ClassFieldOperator(Type javaLangClass, Type classType) {
super(Type.tJavaLangClass); super(javaLangClass);
this.classType = classType; this.classType = classType;
} }

@ -18,6 +18,7 @@
*/ */
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.type.IntegerType; import net.sf.jode.type.IntegerType;
import net.sf.jode.util.StringQuoter; import net.sf.jode.util.StringQuoter;
@ -32,6 +33,11 @@ public class ConstOperator extends NoArgOperator {
| IntegerType.IT_Z | IntegerType.IT_Z
| IntegerType.IT_S | IntegerType.IT_B); | IntegerType.IT_S | IntegerType.IT_B);
public ConstOperator(ClassPath cp, String constant) {
super(Type.tClass(cp, "java.lang.String"));
value = constant;
}
public ConstOperator(Object constant) { public ConstOperator(Object constant) {
super(Type.tUnknown); super(Type.tUnknown);
if (constant instanceof Boolean) { if (constant instanceof Boolean) {
@ -60,8 +66,6 @@ public class ConstOperator extends NoArgOperator {
updateParentType(Type.tFloat); updateParentType(Type.tFloat);
else if (constant instanceof Double) else if (constant instanceof Double)
updateParentType(Type.tDouble); updateParentType(Type.tDouble);
else if (constant instanceof String)
updateParentType(Type.tString);
else if (constant == null) else if (constant == null)
updateParentType(Type.tUObject); updateParentType(Type.tUObject);
else else
@ -129,7 +133,7 @@ public class ConstOperator extends NoArgOperator {
if (type.getHint().equals(Type.tChar)) { if (type.getHint().equals(Type.tChar)) {
char c = (char) ((Integer) value).intValue(); char c = (char) ((Integer) value).intValue();
return StringQuoter.quote(c); return StringQuoter.quote(c);
} else if (type.equals(Type.tString)) { } else if (value instanceof String) {
return StringQuoter.quote(strVal); return StringQuoter.quote(strVal);
} else if (parent != null) { } else if (parent != null) {
int opindex = parent.getOperatorIndex(); int opindex = parent.getOperatorIndex();

@ -204,8 +204,6 @@ public abstract class Expression {
return this; return this;
} }
public static Expression EMPTYSTRING = new ConstOperator("");
public Expression simplifyStringBuffer() { public Expression simplifyStringBuffer() {
return null; return null;
} }
@ -239,6 +237,7 @@ public abstract class Expression {
public void dumpExpression(TabbedPrintWriter writer, int minPriority) public void dumpExpression(TabbedPrintWriter writer, int minPriority)
throws java.io.IOException { throws java.io.IOException {
int options;
boolean needParen1 = false, needParen2 = false; boolean needParen1 = false, needParen2 = false;
boolean needEndOp1 = false, needEndOp2 = false; boolean needEndOp1 = false, needEndOp2 = false;
@ -255,10 +254,10 @@ public abstract class Expression {
needParen1 = true; needParen1 = true;
needEndOp1 = true; needEndOp1 = true;
writer.print("("); writer.print("(");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 0); writer.startOp(writer.EXPL_PAREN, 0);
} else if (minPriority < 700) { } else if (minPriority < 700) {
needEndOp1 = true; needEndOp1 = true;
writer.startOp(TabbedPrintWriter.IMPL_PAREN, 1); writer.startOp(writer.IMPL_PAREN, 1);
} }
writer.print(typecast); writer.print(typecast);
writer.breakOp(); writer.breakOp();
@ -271,13 +270,13 @@ public abstract class Expression {
needParen2 = true; needParen2 = true;
needEndOp2 = true; needEndOp2 = true;
writer.print("("); writer.print("(");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, getBreakPenalty()); writer.startOp(writer.EXPL_PAREN, getBreakPenalty());
} else if (priority != minPriority) { } else if (priority != minPriority) {
needEndOp2 = true; needEndOp2 = true;
if (getType() == Type.tVoid) if (getType() == Type.tVoid)
writer.startOp(TabbedPrintWriter.NO_PAREN, getBreakPenalty()); writer.startOp(writer.NO_PAREN, getBreakPenalty());
else else
writer.startOp(TabbedPrintWriter.IMPL_PAREN, 1 + getBreakPenalty()); writer.startOp(writer.IMPL_PAREN, 1 + getBreakPenalty());
} }
try { try {

@ -18,6 +18,7 @@
*/ */
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.GlobalOptions;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.type.NullType; import net.sf.jode.type.NullType;
import net.sf.jode.type.ClassInfoType; import net.sf.jode.type.ClassInfoType;
@ -28,6 +29,7 @@ import net.sf.jode.bytecode.Reference;
import net.sf.jode.bytecode.TypeSignature; import net.sf.jode.bytecode.TypeSignature;
import net.sf.jode.decompiler.MethodAnalyzer; import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.ClassAnalyzer; import net.sf.jode.decompiler.ClassAnalyzer;
import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.FieldAnalyzer; import net.sf.jode.decompiler.FieldAnalyzer;
import net.sf.jode.decompiler.Options; import net.sf.jode.decompiler.Options;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;
@ -60,8 +62,8 @@ public abstract class FieldOperator extends Operator {
this.methodAnalyzer = methodAnalyzer; this.methodAnalyzer = methodAnalyzer;
this.staticFlag = staticFlag; this.staticFlag = staticFlag;
this.type = Type.tType(classPath, ref.getType()); this.type = Type.tType(methodAnalyzer, ref.getType());
this.classType = Type.tType(classPath, ref.getClazz()); this.classType = Type.tType(methodAnalyzer, ref.getClazz());
this.ref = ref; this.ref = ref;
if (staticFlag) if (staticFlag)
methodAnalyzer.useType(classType); methodAnalyzer.useType(classType);
@ -117,7 +119,7 @@ public abstract class FieldOperator extends Operator {
while (true) { while (true) {
if (clazz == ana.getClazz()) { if (clazz == ana.getClazz()) {
int field = ana.getFieldIndex int field = ana.getFieldIndex
(ref.getName(), Type.tType(classPath, ref.getType())); (ref.getName(), Type.tType(methodAnalyzer, ref.getType()));
if (field >= 0) if (field >= 0)
return ana.getField(field); return ana.getField(field);
return null; return null;
@ -141,12 +143,27 @@ public abstract class FieldOperator extends Operator {
} }
public Type getFieldType() { public Type getFieldType() {
return Type.tType(classPath, ref.getType()); return Type.tType(methodAnalyzer, ref.getType());
} }
private static FieldInfo getFieldInfo(ClassInfo clazz, private void loadFields(ClassInfo clazz) {
String name, String type) { int howMuch = (clazz.getName().startsWith(callerPackage)
&& (clazz.getName().lastIndexOf('.')
< callerPackage.length()))
? ClassInfo.DECLARATIONS : ClassInfo.PUBLICDECLARATIONS;
try {
clazz.load(howMuch);
} catch (IOException ex) {
GlobalOptions.err.println("Warning: Can't find fields of "
+clazz+" to detect hiding conflicts");
clazz.guess(howMuch);
}
}
private FieldInfo getFieldInfo(ClassInfo clazz,
String name, String type) {
while (clazz != null) { while (clazz != null) {
loadFields(clazz);
FieldInfo field = clazz.findField(name, type); FieldInfo field = clazz.findField(name, type);
if (field != null) if (field != null)
return field; return field;
@ -164,14 +181,14 @@ public abstract class FieldOperator extends Operator {
} }
public FieldInfo getFieldInfo() { public FieldInfo getFieldInfo() {
ClassInfo clazz; return getFieldInfo(classInfo, ref.getName(), ref.getType());
if (ref.getClazz().charAt(0) == '[')
clazz = classPath.getClassInfo("java.lang.Object");
else
clazz = TypeSignature.getClassInfo(classPath, ref.getClazz());
return getFieldInfo(clazz, ref.getName(), ref.getType());
} }
/**
* Checks if we need a cast to the super class, to which the field
* belongs.
* @param type the canonic type of the zeroth subexpression.
*/
public boolean needsCast(Type type) { public boolean needsCast(Type type) {
if (type instanceof NullType) if (type instanceof NullType)
return true; return true;
@ -179,46 +196,43 @@ public abstract class FieldOperator extends Operator {
&& classType instanceof ClassInfoType)) && classType instanceof ClassInfoType))
return false; return false;
ClassInfo clazz = ((ClassInfoType) classType).getClassInfo(); ClassInfo subexprClass = ((ClassInfoType) type).getClassInfo();
ClassInfo parClazz = ((ClassInfoType) type).getClassInfo(); FieldInfo field = getFieldInfo();
FieldInfo field = clazz.findField(ref.getName(), ref.getType()); if (field == null) {
/* Weird, field not existing? */
find_field: return false;
while (field == null) {
ClassInfo ifaces[] = clazz.getInterfaces();
for (int i = 0; i < ifaces.length; i++) {
field = ifaces[i].findField(ref.getName(), ref.getType());
if (field != null)
break find_field;
}
clazz = clazz.getSuperclass();
if (clazz == null)
/* Weird, field not existing? */
return false;
field = clazz.findField(ref.getName(), ref.getType());
} }
/**
* We need an explicit cast if we access a private field
* of a parent class (which is only possible if the parent
* class is an outer class of the current class).
*/
if (Modifier.isPrivate(field.getModifiers())) if (Modifier.isPrivate(field.getModifiers()))
return parClazz != clazz; return subexprClass != classInfo;
else if ((field.getModifiers() else if ((field.getModifiers()
& (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) { & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) {
/* Field is protected. We need a cast if parClazz is in /* Field is protected. We need a cast if subexprClass is in
* other package than clazz. * other package than classInfo.
*/ */
int lastDot = clazz.getName().lastIndexOf('.'); int lastDot = classInfo.getName().lastIndexOf('.');
if (lastDot == -1 if (lastDot == -1
|| lastDot != parClazz.getName().lastIndexOf('.') || lastDot != subexprClass.getName().lastIndexOf('.')
|| !(parClazz.getName() || !(subexprClass.getName()
.startsWith(clazz.getName().substring(0,lastDot)))) .startsWith(classInfo.getName().substring(0,lastDot))))
return true; return true;
} }
while (clazz != parClazz && clazz != null) { /* We also need an explicit cast if the field is hidden by a
FieldInfo[] fields = parClazz.getFields(); * declaration in param class.
*/
while (classInfo != subexprClass && classInfo != null) {
FieldInfo[] fields = subexprClass.getFields();
for (int i = 0; i < fields.length; i++) { for (int i = 0; i < fields.length; i++) {
if (fields[i].getName().equals(ref.getName())) if (fields[i].getName().equals(ref.getName()))
return true; return true;
} }
parClazz = parClazz.getSuperclass(); subexprClass = subexprClass.getSuperclass();
} }
return false; return false;
} }
@ -258,10 +272,9 @@ public abstract class FieldOperator extends Operator {
writer.breakOp(); writer.breakOp();
writer.print("."); writer.print(".");
} }
writer.print(fieldName);
} else if (needsCast(subExpressions[0].getType().getCanonic())) { } else if (needsCast(subExpressions[0].getType().getCanonic())) {
writer.print("("); writer.print("(");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 1); writer.startOp(writer.EXPL_PAREN, 1);
writer.print("("); writer.print("(");
writer.printType(classType); writer.printType(classType);
writer.print(") "); writer.print(") ");
@ -271,36 +284,33 @@ public abstract class FieldOperator extends Operator {
writer.print(")"); writer.print(")");
writer.breakOp(); writer.breakOp();
writer.print("."); writer.print(".");
writer.print(fieldName); } else if (opIsThis) {
} else { ThisOperator thisOp = (ThisOperator) subExpressions[0];
if (opIsThis) { Scope scope = writer.getScope(thisOp.getClassInfo(),
ThisOperator thisOp = (ThisOperator) subExpressions[0]; Scope.CLASSSCOPE);
Scope scope = writer.getScope(thisOp.getClassInfo(),
Scope.CLASSSCOPE);
if (scope == null || writer.conflicts(fieldName, scope, if (scope == null || writer.conflicts(fieldName, scope,
Scope.FIELDNAME)) { Scope.FIELDNAME)) {
thisOp.dumpExpression(writer, 950); thisOp.dumpExpression(writer, 950);
writer.breakOp(); writer.breakOp();
writer.print("."); writer.print(".");
} else if (writer.conflicts(fieldName, scope, } else if (writer.conflicts(fieldName, scope,
Scope.AMBIGUOUSNAME) Scope.AMBIGUOUSNAME)
|| (/* This is a inherited field conflicting || (/* This is a inherited field conflicting
* with a field name in some outer class. * with a field name in some outer class.
*/ */
getField() == null getField() == null
&& writer.conflicts(fieldName, null, && writer.conflicts(fieldName, null,
Scope.NOSUPERFIELDNAME))) { Scope.NOSUPERFIELDNAME))) {
thisOp.dumpExpression(writer, 950); thisOp.dumpExpression(writer, 950);
writer.breakOp();
writer.print(".");
}
} else {
subExpressions[0].dumpExpression(writer, 950);
writer.breakOp(); writer.breakOp();
writer.print("."); writer.print(".");
} }
writer.print(fieldName); } else {
subExpressions[0].dumpExpression(writer, 950);
writer.breakOp();
writer.print(".");
} }
writer.print(fieldName);
} }
} }

@ -19,6 +19,7 @@
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;
public class IIncOperator extends Operator public class IIncOperator extends Operator

@ -76,6 +76,7 @@ public class IfThenElseOperator extends Operator {
= (GetFieldOperator) subExpressions[2 - cmpType]; = (GetFieldOperator) subExpressions[2 - cmpType];
StoreInstruction put StoreInstruction put
= (StoreInstruction) subExpressions[1 + cmpType]; = (StoreInstruction) subExpressions[1 + cmpType];
int opIndex = cmp.getOperatorIndex();
FieldAnalyzer field; FieldAnalyzer field;
if (put.getLValue() instanceof PutFieldOperator if (put.getLValue() instanceof PutFieldOperator
&& ((field = ((PutFieldOperator)put.getLValue()) && ((field = ((PutFieldOperator)put.getLValue())
@ -97,8 +98,9 @@ public class IfThenElseOperator extends Operator {
ClassPath cp = field.getClassAnalyzer().getClassPath(); ClassPath cp = field.getClassAnalyzer().getClassPath();
if (field.setClassConstant(clazz)) if (field.setClassConstant(clazz))
return new ClassFieldOperator return new ClassFieldOperator
(clazz.charAt(0) == '[' (invoke.getType(),
? Type.tType(cp, clazz) clazz.charAt(0) == '['
? Type.tType(field.getClassAnalyzer(), clazz)
: Type.tClass(cp, clazz)); : Type.tClass(cp, clazz));
} }
} }
@ -119,7 +121,7 @@ public class IfThenElseOperator extends Operator {
int subPriority = 0; int subPriority = 0;
if (!subExpressions[1].getType().getHint().isOfType if (!subExpressions[1].getType().getHint().isOfType
(subExpressions[2].getType())) { (subExpressions[2].getType())) {
writer.startOp(TabbedPrintWriter.IMPL_PAREN, 2); writer.startOp(writer.IMPL_PAREN, 2);
/* We need a cast here */ /* We need a cast here */
writer.print("("); writer.print("(");
writer.printType(getType().getHint()); writer.printType(getType().getHint());

@ -51,7 +51,7 @@ public class InstanceOfOperator extends Operator {
Type superType Type superType
= instanceType.getCastHelper(subExpressions[0].getType()); = instanceType.getCastHelper(subExpressions[0].getType());
if (superType != null) { if (superType != null) {
writer.startOp(TabbedPrintWriter.IMPL_PAREN, 2); writer.startOp(writer.IMPL_PAREN, 2);
writer.print("("); writer.print("(");
writer.printType(superType); writer.printType(superType);
writer.print(") "); writer.print(") ");

@ -20,6 +20,7 @@
package net.sf.jode.expr; package net.sf.jode.expr;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.MethodAnalyzer; import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.ClassAnalyzer; import net.sf.jode.decompiler.ClassAnalyzer;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;
@ -39,6 +40,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
///#enddef ///#enddef
@ -153,10 +155,12 @@ public final class InvokeOperator extends Operator
super(Type.tUnknown, 0); super(Type.tUnknown, 0);
this.classPath = methodAnalyzer.getClassAnalyzer().getClassPath(); this.classPath = methodAnalyzer.getClassAnalyzer().getClassPath();
this.ref = reference; this.ref = reference;
this.methodType = Type.tMethod(classPath, reference.getType()); //TODO: generics
this.methodType = Type.tMethod(methodAnalyzer.getClassPath(),
null, reference.getType(), null);
this.methodName = reference.getName(); this.methodName = reference.getName();
this.classType = (ClassType) this.classType = (ClassType)
Type.tType(classPath, reference.getClazz()); Type.tType(methodAnalyzer.getClassPath(), null, reference.getClazz());
this.hints = null; this.hints = null;
Map allHints = (Map) hintTypes.get(methodName+"."+methodType); Map allHints = (Map) hintTypes.get(methodName+"."+methodType);
if (allHints != null) { if (allHints != null) {
@ -216,9 +220,9 @@ public final class InvokeOperator extends Operator
String name, String type) { String name, String type) {
while (clazz != null) { while (clazz != null) {
try { try {
clazz.load(ClassInfo.DECLARATIONS); clazz.load(clazz.DECLARATIONS);
} catch (IOException ex) { } catch (IOException ex) {
clazz.guess(ClassInfo.DECLARATIONS); clazz.guess(clazz.DECLARATIONS);
} }
MethodInfo method = clazz.findMethod(name, type); MethodInfo method = clazz.findMethod(name, type);
if (method != null) if (method != null)
@ -413,7 +417,7 @@ public final class InvokeOperator extends Operator
* Checks, whether this is a call of a method from the super class. * Checks, whether this is a call of a method from the super class.
*/ */
public boolean isSuperOrThis() { public boolean isSuperOrThis() {
return classType.maybeSubTypeOf return classType.maybeSuperTypeOf
(Type.tClass(methodAnalyzer.getClazz())); (Type.tClass(methodAnalyzer.getClazz()));
} }
@ -513,7 +517,7 @@ public final class InvokeOperator extends Operator
} }
return null; return null;
} }
return new ConstOperator(result); return new ConstOperator(classPath, result);
} }
public Expression simplifyStringBuffer() { public Expression simplifyStringBuffer() {
@ -522,7 +526,7 @@ public final class InvokeOperator extends Operator
if (isConstructor() if (isConstructor()
&& subExpressions[0] instanceof NewOperator) { && subExpressions[0] instanceof NewOperator) {
if (methodType.getParameterTypes().length == 0) if (methodType.getParameterTypes().length == 0)
return EMPTYSTRING; return emptyString();
if (methodType.getParameterTypes().length == 1 if (methodType.getParameterTypes().length == 1
&& methodType.getParameterTypes()[0].equals(Type.tString)) && methodType.getParameterTypes()[0].equals(Type.tString))
return subExpressions[1].simplifyString(); return subExpressions[1].simplifyString();
@ -538,14 +542,14 @@ public final class InvokeOperator extends Operator
subExpressions[1] = subExpressions[1].simplifyString(); subExpressions[1] = subExpressions[1].simplifyString();
if (firstOp == EMPTYSTRING if (isEmptyString(firstOp)
&& subExpressions[1].getType().isOfType(Type.tString)) && subExpressions[1].getType().isOfType(Type.tString))
return subExpressions[1]; return subExpressions[1];
if (firstOp instanceof StringAddOperator if (firstOp instanceof StringAddOperator
&& (((Operator)firstOp).getSubExpressions()[0] && isEmptyString(((Operator) firstOp)
== EMPTYSTRING)) .getSubExpressions()[0]))
firstOp = ((Operator)firstOp).getSubExpressions()[1]; firstOp = ((Operator) firstOp).getSubExpressions()[1];
Expression secondOp = subExpressions[1]; Expression secondOp = subExpressions[1];
Type[] paramTypes = new Type[] { Type[] paramTypes = new Type[] {
@ -566,6 +570,15 @@ public final class InvokeOperator extends Operator
return null; return null;
} }
public boolean isEmptyString(Expression expr) {
return (expr instanceof ConstOperator
&& ((ConstOperator) expr).getValue() == "");
}
public ConstOperator emptyString() {
return new ConstOperator(classPath, "");
}
public Expression simplifyString() { public Expression simplifyString() {
if (getMethodName().equals("toString") if (getMethodName().equals("toString")
&& !isStatic() && !isStatic()
@ -586,7 +599,7 @@ public final class InvokeOperator extends Operator
Operator op = new StringAddOperator(); Operator op = new StringAddOperator();
op.addOperand(subExpressions[0]); op.addOperand(subExpressions[0]);
op.addOperand(EMPTYSTRING); op.addOperand(emptyString());
} }
/* The pizza way (pizza is the compiler of kaffe) */ /* The pizza way (pizza is the compiler of kaffe) */
else if (getMethodName().equals("concat") else if (getMethodName().equals("concat")
@ -598,7 +611,7 @@ public final class InvokeOperator extends Operator
if (right instanceof StringAddOperator) { if (right instanceof StringAddOperator) {
Operator op = (Operator) right; Operator op = (Operator) right;
if (op.subExpressions != null if (op.subExpressions != null
&& op.subExpressions[0] == EMPTYSTRING) && isEmptyString(op.subExpressions[0]))
right = op.subExpressions[1]; right = op.subExpressions[1];
} }
result.addOperand(right); result.addOperand(right);
@ -640,7 +653,7 @@ public final class InvokeOperator extends Operator
op = new StoreInstruction op = new StoreInstruction
(new PutFieldOperator(methodAnalyzer, false, (new PutFieldOperator(methodAnalyzer, false,
synth.getReference())); synth.getReference()));
if (synth.getKind() == SyntheticAnalyzer.ACCESSDUPPUTFIELD) if (synth.getKind() == synth.ACCESSDUPPUTFIELD)
((StoreInstruction) op).makeNonVoid(); ((StoreInstruction) op).makeNonVoid();
break; break;
case SyntheticAnalyzer.ACCESSPUTSTATIC: case SyntheticAnalyzer.ACCESSPUTSTATIC:
@ -648,7 +661,7 @@ public final class InvokeOperator extends Operator
op = new StoreInstruction op = new StoreInstruction
(new PutFieldOperator(methodAnalyzer, true, (new PutFieldOperator(methodAnalyzer, true,
synth.getReference())); synth.getReference()));
if (synth.getKind() == SyntheticAnalyzer.ACCESSDUPPUTSTATIC) if (synth.getKind() == synth.ACCESSDUPPUTSTATIC)
((StoreInstruction) op).makeNonVoid(); ((StoreInstruction) op).makeNonVoid();
break; break;
case SyntheticAnalyzer.ACCESSMETHOD: case SyntheticAnalyzer.ACCESSMETHOD:
@ -762,8 +775,10 @@ public final class InvokeOperator extends Operator
/* method name doesn't match*/ /* method name doesn't match*/
continue next_method; continue next_method;
// TODO Generics
Type[] otherParamTypes Type[] otherParamTypes
= Type.tMethod(classPath, methods[i].getType()) = Type.tMethod(methodAnalyzer.getClassPath(), null,
methods[i].getSignature(), null)
.getParameterTypes(); .getParameterTypes();
if (otherParamTypes.length != myParamTypes.length) { if (otherParamTypes.length != myParamTypes.length) {
/* parameter count doesn't match*/ /* parameter count doesn't match*/
@ -946,7 +961,7 @@ public final class InvokeOperator extends Operator
* we have to differentiate all kinds of method calls: static, * we have to differentiate all kinds of method calls: static,
* virtual, constructor, anonymous constructors, super calls etc. * virtual, constructor, anonymous constructors, super calls etc.
*/ */
writer.startOp(TabbedPrintWriter.NO_PAREN, 0); writer.startOp(writer.NO_PAREN, 0);
switch (methodFlag) { switch (methodFlag) {
case CONSTRUCTOR: { case CONSTRUCTOR: {
@ -1038,7 +1053,7 @@ public final class InvokeOperator extends Operator
if (outerExpr.getType().getCanonic() if (outerExpr.getType().getCanonic()
instanceof NullType) { instanceof NullType) {
writer.print("("); writer.print("(");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 1); writer.startOp(writer.EXPL_PAREN, 1);
writer.print("("); writer.print("(");
writer.printType(Type.tClass(clazz)); writer.printType(Type.tClass(clazz));
writer.print(") "); writer.print(") ");
@ -1076,7 +1091,7 @@ public final class InvokeOperator extends Operator
} }
writer.print("("); writer.print("(");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 0); writer.startOp(writer.EXPL_PAREN, 0);
writer.print("(UNCONSTRUCTED)"); writer.print("(UNCONSTRUCTED)");
writer.breakOp(); writer.breakOp();
subExpressions[0].dumpExpression(writer, 700); subExpressions[0].dumpExpression(writer, 700);
@ -1146,7 +1161,7 @@ public final class InvokeOperator extends Operator
subExpressions[0].dumpExpression(writer, 950); subExpressions[0].dumpExpression(writer, 950);
else { else {
writer.print("("); writer.print("(");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 0); writer.startOp(writer.EXPL_PAREN, 0);
writer.print("("); writer.print("(");
writer.printType(classType); writer.printType(classType);
writer.print(") "); writer.print(") ");
@ -1197,7 +1212,7 @@ public final class InvokeOperator extends Operator
} else { } else {
if (needsCast(0, paramTypes)){ if (needsCast(0, paramTypes)){
writer.print("("); writer.print("(");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 1); writer.startOp(writer.EXPL_PAREN, 1);
writer.print("("); writer.print("(");
writer.printType(classType); writer.printType(classType);
writer.print(") "); writer.print(") ");
@ -1221,7 +1236,7 @@ public final class InvokeOperator extends Operator
writer.breakOp(); writer.breakOp();
writer.printOptionalSpace(); writer.printOptionalSpace();
writer.print("("); writer.print("(");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 0); writer.startOp(writer.EXPL_PAREN, 0);
boolean first = true; boolean first = true;
int offset = skippedArgs; int offset = skippedArgs;
while (arg < length) { while (arg < length) {
@ -1233,7 +1248,7 @@ public final class InvokeOperator extends Operator
int priority = 0; int priority = 0;
if (needsCast(arg, paramTypes)) { if (needsCast(arg, paramTypes)) {
Type castType = methodType.getParameterTypes()[arg-offset]; Type castType = methodType.getParameterTypes()[arg-offset];
writer.startOp(TabbedPrintWriter.IMPL_PAREN, 1); writer.startOp(writer.IMPL_PAREN, 1);
writer.print("("); writer.print("(");
writer.printType(castType); writer.printType(castType);
writer.print(") "); writer.print(") ");

@ -18,6 +18,9 @@
*/ */
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.type.Type;
import net.sf.jode.GlobalOptions;
import net.sf.jode.decompiler.TabbedPrintWriter;
public interface LValueExpression extends MatchableOperator { public interface LValueExpression extends MatchableOperator {
} }

@ -18,9 +18,12 @@
*/ */
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.GlobalOptions;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.decompiler.MethodAnalyzer; import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.ClassAnalyzer;
import net.sf.jode.decompiler.LocalInfo; import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.decompiler.TabbedPrintWriter;
public class LocalLoadOperator extends LocalVarOperator { public class LocalLoadOperator extends LocalVarOperator {

@ -18,8 +18,10 @@
*/ */
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.GlobalOptions;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.decompiler.LocalInfo; import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.decompiler.TabbedPrintWriter;
public class LocalStoreOperator extends LocalVarOperator public class LocalStoreOperator extends LocalVarOperator
implements LValueExpression { implements LValueExpression {

@ -19,6 +19,7 @@
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.decompiler.TabbedPrintWriter;
public abstract class NoArgOperator extends Operator { public abstract class NoArgOperator extends Operator {

@ -19,6 +19,7 @@
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.GlobalOptions;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
@ -133,7 +134,7 @@ public abstract class Operator extends Expression {
- subExpressions[i].getFreeOperandCount(); - subExpressions[i].getFreeOperandCount();
subExpressions[i] = expr; subExpressions[i] = expr;
expr.parent = this; expr.parent = this;
for (Operator ce = this; ce != null; ce = ce.parent) for (Operator ce = this; ce != null; ce = (Operator) ce.parent)
ce.operandcount += diff; ce.operandcount += diff;
updateType(); updateType();
} }
@ -220,6 +221,7 @@ public abstract class Operator extends Expression {
* is not a CombineableOperator. * is not a CombineableOperator.
*/ */
public boolean containsMatchingLoad(CombineableOperator comb) { public boolean containsMatchingLoad(CombineableOperator comb) {
Operator combOp = (Operator) comb;
if (comb.getLValue().matches(this)) { if (comb.getLValue().matches(this)) {
if (subsEquals((Operator) comb.getLValue())) if (subsEquals((Operator) comb.getLValue()))
return true; return true;

@ -19,6 +19,9 @@
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.GlobalOptions; import net.sf.jode.GlobalOptions;
import net.sf.jode.type.Type;
import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.ClassAnalyzer;
import net.sf.jode.decompiler.LocalInfo; import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;

@ -52,6 +52,7 @@ public class PrePostFixOperator extends Operator {
public void dumpExpression(TabbedPrintWriter writer) public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException { throws java.io.IOException {
boolean needBrace = false;
int priority = 700; int priority = 700;
if (!postfix) { if (!postfix) {
writer.print(getOperatorString()); writer.print(getOperatorString());

@ -20,6 +20,7 @@
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.bytecode.Reference; import net.sf.jode.bytecode.Reference;
import net.sf.jode.decompiler.MethodAnalyzer; import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.FieldAnalyzer;
public class PutFieldOperator extends FieldOperator public class PutFieldOperator extends FieldOperator
implements LValueExpression { implements LValueExpression {

@ -19,6 +19,7 @@
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.GlobalOptions;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;
public class StoreInstruction extends Operator public class StoreInstruction extends Operator
@ -72,6 +73,9 @@ public class StoreInstruction extends Operator
} }
public void updateType() { public void updateType() {
Type newType;
if (!opAssign) { if (!opAssign) {
/* An opassign (+=, -=, etc.) doesn't merge rvalue type. */ /* An opassign (+=, -=, etc.) doesn't merge rvalue type. */
Type lvalueType = subExpressions[0].getType(); Type lvalueType = subExpressions[0].getType();

@ -48,13 +48,6 @@ public class StringAddOperator extends Operator {
public void dumpExpression(TabbedPrintWriter writer) public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException { throws java.io.IOException {
if (!subExpressions[0].getType().isOfType(Type.tString)
&& !subExpressions[1].getType().isOfType(Type.tString)) {
writer.print("\"\"");
writer.breakOp();
writer.print(getOperatorString());
}
subExpressions[0].dumpExpression(writer, 610); subExpressions[0].dumpExpression(writer, 610);
writer.breakOp(); writer.breakOp();
writer.print(getOperatorString()); writer.print(getOperatorString());

@ -20,25 +20,30 @@
package net.sf.jode.expr; package net.sf.jode.expr;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.bytecode.ClassInfo; import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.decompiler.ClassAnalyzer;
import net.sf.jode.decompiler.Scope; import net.sf.jode.decompiler.Scope;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;
public class ThisOperator extends NoArgOperator { public class ThisOperator extends NoArgOperator {
boolean isInnerMost; boolean isInnerMost;
ClassInfo classInfo; ClassAnalyzer classAna;
public ThisOperator(ClassInfo classInfo, boolean isInnerMost) { public ThisOperator(ClassAnalyzer classAna, boolean isInnerMost) {
super(Type.tClass(classInfo)); super(classAna.getType());
this.classInfo = classInfo; this.classAna = classAna;
this.isInnerMost = isInnerMost; this.isInnerMost = isInnerMost;
} }
public ThisOperator(ClassInfo classInfo) { public ThisOperator(ClassAnalyzer classAna) {
this(classInfo, false); this(classAna, false);
} }
public ClassInfo getClassInfo() { public ClassInfo getClassInfo() {
return classInfo; return classAna.getClazz();
}
public ClassAnalyzer getClassAnalyzer() {
return classAna;
} }
public int getPriority() { public int getPriority() {
@ -46,18 +51,18 @@ public class ThisOperator extends NoArgOperator {
} }
public String toString() { public String toString() {
return classInfo+".this"; return classAna+".this";
} }
public boolean opEquals(Operator o) { public boolean opEquals(Operator o) {
return (o instanceof ThisOperator && return (o instanceof ThisOperator &&
((ThisOperator) o).classInfo.equals(classInfo)); ((ThisOperator) o).classAna == classAna);
} }
public void dumpExpression(TabbedPrintWriter writer) public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException { throws java.io.IOException {
if (!isInnerMost) { if (!isInnerMost) {
writer.print(writer.getClassString(classInfo, writer.print(writer.getClassString(getClassInfo(),
Scope.AMBIGUOUSNAME)); Scope.AMBIGUOUSNAME));
writer.print("."); writer.print(".");
} }

@ -18,6 +18,7 @@
*/ */
package net.sf.jode.flow; package net.sf.jode.flow;
import net.sf.jode.decompiler.TabbedPrintWriter;
/** /**
* This is a structured block, that supports break. * This is a structured block, that supports break.

@ -25,8 +25,8 @@ import net.sf.jode.expr.Expression;
import net.sf.jode.expr.LocalLoadOperator; import net.sf.jode.expr.LocalLoadOperator;
import net.sf.jode.expr.LocalStoreOperator; import net.sf.jode.expr.LocalStoreOperator;
import net.sf.jode.expr.NopOperator; import net.sf.jode.expr.NopOperator;
import net.sf.jode.expr.Operator;
import net.sf.jode.expr.StoreInstruction; import net.sf.jode.expr.StoreInstruction;
import net.sf.jode.util.SimpleSet;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.Collections; import java.util.Collections;
@ -223,7 +223,7 @@ public class CatchBlock extends StructuredBlock {
((InstructionBlock) firstInstr).getInstruction(); ((InstructionBlock) firstInstr).getInstruction();
if (instr instanceof StoreInstruction) { if (instr instanceof StoreInstruction) {
StoreInstruction store = (StoreInstruction) instr; StoreInstruction store = (StoreInstruction) instr;
if (store.getOperatorIndex() == Operator.OPASSIGN_OP if (store.getOperatorIndex() == store.OPASSIGN_OP
&& store.getSubExpressions()[1] instanceof NopOperator && store.getSubExpressions()[1] instanceof NopOperator
&& store.getLValue() instanceof LocalStoreOperator) { && store.getLValue() instanceof LocalStoreOperator) {
/* The exception is stored in a local variable */ /* The exception is stored in a local variable */

@ -18,6 +18,7 @@
*/ */
package net.sf.jode.flow; package net.sf.jode.flow;
import java.util.Vector;
import net.sf.jode.expr.*; import net.sf.jode.expr.*;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;

@ -20,6 +20,7 @@
package net.sf.jode.flow; package net.sf.jode.flow;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
import net.sf.jode.expr.LocalVarOperator;
/** /**
* An ConditionalBlock is the structured block representing an if * An ConditionalBlock is the structured block representing an if
@ -35,6 +36,8 @@ public class ConditionalBlock extends InstructionContainer {
public void checkConsistent() { public void checkConsistent() {
super.checkConsistent(); super.checkConsistent();
if (!(trueBlock instanceof EmptyBlock))
throw new InternalError("Inconsistency");
} }
/** /**
@ -120,7 +123,7 @@ public class ConditionalBlock extends InstructionContainer {
throws java.io.IOException throws java.io.IOException
{ {
writer.print("IF ("); writer.print("IF (");
instr.dumpExpression(TabbedPrintWriter.EXPL_PAREN, writer); instr.dumpExpression(writer.EXPL_PAREN, writer);
writer.println(")"); writer.println(")");
writer.tab(); writer.tab();
trueBlock.dumpSource(writer); trueBlock.dumpSource(writer);

@ -115,7 +115,7 @@ public class CreateAssignExpression {
} }
if (expr instanceof BinaryOperator) { if (expr instanceof BinaryOperator) {
opIndex = expr.getOperatorIndex(); opIndex = expr.getOperatorIndex();
if (opIndex < Operator.ADD_OP || opIndex >= Operator.ASSIGN_OP) if (opIndex < expr.ADD_OP || opIndex >= expr.ASSIGN_OP)
return false; return false;
if (!(expr.getSubExpressions()[0] instanceof Operator)) if (!(expr.getSubExpressions()[0] instanceof Operator))
@ -126,7 +126,7 @@ public class CreateAssignExpression {
&& loadExpr.getSubExpressions()[0] instanceof Operator) && loadExpr.getSubExpressions()[0] instanceof Operator)
loadExpr = (Operator) loadExpr.getSubExpressions()[0]; loadExpr = (Operator) loadExpr.getSubExpressions()[0];
if (!store.lvalueMatches(loadExpr) if (!store.lvalueMatches((Operator) loadExpr)
|| !(loadExpr.isFreeOperator(lvalueCount))) || !(loadExpr.isFreeOperator(lvalueCount)))
return false; return false;
@ -179,7 +179,7 @@ public class CreateAssignExpression {
ib.setInstruction(rightHandSide); ib.setInstruction(rightHandSide);
lvalue.setType(rvalueType); lvalue.setType(rvalueType);
store.makeOpAssign(Operator.OPASSIGN_OP + opIndex); store.makeOpAssign(store.OPASSIGN_OP + opIndex);
if (isAssignOp) if (isAssignOp)
store.makeNonVoid(); store.makeNonVoid();

@ -21,6 +21,7 @@ package net.sf.jode.flow;
import net.sf.jode.expr.*; import net.sf.jode.expr.*;
import net.sf.jode.bytecode.ClassPath; import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.decompiler.LocalInfo;
public class CreateClassField { public class CreateClassField {
@ -73,8 +74,9 @@ public class CreateClassField {
if (put.getField().setClassConstant(clazz)) { if (put.getField().setClassConstant(clazz)) {
ClassPath cp = invoke.getClassPath(); ClassPath cp = invoke.getClassPath();
cmp.setSubExpressions cmp.setSubExpressions
(0, new ClassFieldOperator(clazz.charAt(0) == '[' (0, new ClassFieldOperator(put.getType(),
? Type.tType(cp, clazz) clazz.charAt(0) == '['
? Type.tType(invoke.getClassAnalyzer(), clazz)
: Type.tClass(cp, clazz))); : Type.tClass(cp, clazz)));
EmptyBlock empty = new EmptyBlock(); EmptyBlock empty = new EmptyBlock();
empty.moveJump(ifBlock.thenBlock.jump); empty.moveJump(ifBlock.thenBlock.jump);

@ -20,6 +20,7 @@
package net.sf.jode.flow; package net.sf.jode.flow;
import net.sf.jode.GlobalOptions; import net.sf.jode.GlobalOptions;
import net.sf.jode.expr.*; import net.sf.jode.expr.*;
import net.sf.jode.type.Type;
public class CreateConstantArray { public class CreateConstantArray {

@ -22,6 +22,9 @@ import net.sf.jode.GlobalOptions;
import net.sf.jode.type.Type; import net.sf.jode.type.Type;
import net.sf.jode.expr.*; import net.sf.jode.expr.*;
import java.util.Enumeration;
import java.util.Vector;
public class CreateIfThenElseOperator { public class CreateIfThenElseOperator {
/** /**
@ -52,6 +55,7 @@ public class CreateIfThenElseOperator {
if (block instanceof IfThenElseBlock) { if (block instanceof IfThenElseBlock) {
IfThenElseBlock ifBlock = (IfThenElseBlock) block; IfThenElseBlock ifBlock = (IfThenElseBlock) block;
Expression expr1, expr2;
if (ifBlock.elseBlock == null) if (ifBlock.elseBlock == null)
return false; return false;
@ -152,15 +156,18 @@ public class CreateIfThenElseOperator {
FlowBlock trueDestination; FlowBlock trueDestination;
FlowBlock falseDestination; FlowBlock falseDestination;
if (compare.getOperatorIndex() == Operator.EQUALS_OP) { if (compare.getOperatorIndex() == compare.EQUALS_OP) {
trueDestination = cb.jump.destination; trueDestination = cb.jump.destination;
falseDestination = cb.trueBlock.jump.destination; falseDestination = cb.trueBlock.jump.destination;
} else if (compare.getOperatorIndex() == Operator.NOTEQUALS_OP) { } else if (compare.getOperatorIndex() == compare.NOTEQUALS_OP) {
falseDestination = cb.jump.destination; falseDestination = cb.jump.destination;
trueDestination = cb.trueBlock.jump.destination; trueDestination = cb.trueBlock.jump.destination;
} else } else
return false; return false;
Expression[] e = new Expression[3];
IfThenElseBlock ifBlock;
SequentialBlock sequBlock = (SequentialBlock) last.outer; SequentialBlock sequBlock = (SequentialBlock) last.outer;
return createFunnyHelper(trueDestination, falseDestination, return createFunnyHelper(trueDestination, falseDestination,
sequBlock.subBlocks[0]); sequBlock.subBlocks[0]);

@ -65,9 +65,9 @@ public class CreatePrePostIncExpression {
return false; return false;
int op; int op;
if (iinc.getOperatorIndex() == Operator.ADD_OP + Operator.OPASSIGN_OP) if (iinc.getOperatorIndex() == iinc.ADD_OP + iinc.OPASSIGN_OP)
op = Operator.INC_OP; op = Operator.INC_OP;
else if (iinc.getOperatorIndex() == Operator.SUB_OP + Operator.OPASSIGN_OP) else if (iinc.getOperatorIndex() == iinc.SUB_OP + iinc.OPASSIGN_OP)
op = Operator.DEC_OP; op = Operator.DEC_OP;
else else
return false; return false;
@ -128,9 +128,9 @@ public class CreatePrePostIncExpression {
ConstOperator constOp = (ConstOperator) binOp.getSubExpressions()[1]; ConstOperator constOp = (ConstOperator) binOp.getSubExpressions()[1];
int op; int op;
if (binOp.getOperatorIndex() == Operator.ADD_OP) if (binOp.getOperatorIndex() == store.ADD_OP)
op = Operator.INC_OP; op = Operator.INC_OP;
else if (binOp.getOperatorIndex() == Operator.SUB_OP) else if (binOp.getOperatorIndex() == store.SUB_OP)
op = Operator.DEC_OP; op = Operator.DEC_OP;
else else
return false; return false;

@ -24,8 +24,8 @@ import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.LocalInfo; import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
import net.sf.jode.expr.CombineableOperator; import net.sf.jode.expr.CombineableOperator;
import net.sf.jode.type.Type;
import net.sf.jode.util.SimpleMap; import net.sf.jode.util.SimpleMap;
import net.sf.jode.util.SimpleSet;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.Map; import java.util.Map;
@ -168,18 +168,12 @@ public class FlowBlock {
* The gen locals. This are the locals, which can be * The gen locals. This are the locals, which can be
* overwritten in this block on a path to the successor. That * overwritten in this block on a path to the successor. That
* means, that there exists a path form the start of the * means, that there exists a path form the start of the
* current flow block to the successor that contains an * current flow block to the successor that contains a
* assignments to this local, and that is not overwritten * assignments to this local, and that is not overwritten
* afterwards. * afterwards.
*/ */
VariableSet gen; VariableSet gen;
/**
* If this is non-null it contains an array list of all exception types
* for which the successor is the catch block.
*/
ArrayList catched;
/** /**
* The linked list of jumps. * The linked list of jumps.
*/ */
@ -223,25 +217,8 @@ public class FlowBlock {
/* We will put all jumps that we can not resolve into this /* We will put all jumps that we can not resolve into this
* linked list. * linked list.
*/ */
if (jumps == null)
return null;
Jump remainingJumps = null; Jump remainingJumps = null;
/* find the smallest block containing all jumps */
lastModified = jumps.prev;
for (Jump jump = jumps.next; jump != null; jump = jump.next) {
while (!lastModified.contains(jump.prev))
lastModified = lastModified.outer;
}
StructuredBlock b = lastModified.outer;
while (b != null) {
if (b.outer instanceof TryBlock
&& ((TryBlock)b.outer).getSubBlocks()[0] == b) {
lastModified = b.outer;
}
b = b.outer;
}
if (lastModified.jump == null) { if (lastModified.jump == null) {
/* This can happen if lastModified is a breakable block, and /* This can happen if lastModified is a breakable block, and
* there is no break to it yet. We give lastModified this jump * there is no break to it yet. We give lastModified this jump
@ -265,11 +242,9 @@ public class FlowBlock {
cb.setInstruction(instr.negate()); cb.setInstruction(instr.negate());
cb.swapJump(prev); cb.swapJump(prev);
/* Update lastModified if it happened to be the conditional jump */
if (lastModified == prev)
lastModified = jump.prev;
} }
} }
next_jump:
while (jumps != null) { while (jumps != null) {
Jump jump = jumps; Jump jump = jumps;
jumps = jumps.next; jumps = jumps.next;
@ -291,7 +266,7 @@ public class FlowBlock {
ConditionalBlock cb = (ConditionalBlock) prev.outer; ConditionalBlock cb = (ConditionalBlock) prev.outer;
Expression instr = cb.getInstruction(); Expression instr = cb.getInstruction();
/* This is a jump inside a ConditionalBlock. /* This is a jump inside an ConditionalBlock.
* *
* cb is the conditional block, * cb is the conditional block,
* prev the empty block containing the jump * prev the empty block containing the jump
@ -299,7 +274,7 @@ public class FlowBlock {
if (cb.jump != null) { if (cb.jump != null) {
/* This can only happen if cb also jumps to succ. /* This can only happen if cb also jumps to succ.
* This is a weird "if (cond) empty"-block. We * This is a weired "if (cond) empty"-block. We
* transform it by hand. * transform it by hand.
*/ */
prev.removeJump(); prev.removeJump();
@ -344,8 +319,6 @@ public class FlowBlock {
loopBlock.setCondition(instr.negate()); loopBlock.setCondition(instr.negate());
loopBlock.moveDefinitions(cb, null); loopBlock.moveDefinitions(cb, null);
if (loopBlock.contains(lastModified))
lastModified = loopBlock;
cb.removeBlock(); cb.removeBlock();
continue; continue;
} }
@ -382,8 +355,6 @@ public class FlowBlock {
loopBlock.setType(LoopBlock.DOWHILE); loopBlock.setType(LoopBlock.DOWHILE);
loopBlock.setCondition(instr.negate()); loopBlock.setCondition(instr.negate());
loopBlock.moveDefinitions(cb, null); loopBlock.moveDefinitions(cb, null);
if (loopBlock.contains(lastModified))
lastModified = loopBlock;
cb.removeBlock(); cb.removeBlock();
continue; continue;
} }
@ -451,8 +422,8 @@ public class FlowBlock {
/* remove this jump if it jumps to the /* remove this jump if it jumps to the
* getNextFlowBlock(). */ * getNextFlowBlock(). */
if (jump.prev.outer != null && if (jump.destination
jump.destination == jump.prev.outer.getNextFlowBlock(jump.prev)) { == jump.prev.outer.getNextFlowBlock(jump.prev)) {
jump.prev.removeJump(); jump.prev.removeJump();
continue; continue;
} }
@ -603,13 +574,14 @@ public class FlowBlock {
/** /**
* Resolve remaining jumps to the successor by generating break * Resolve remaining jumps to the successor by generating break
* instructions. As last resort generate a labelled block. * instructions. As last resort generate a do while(false) block.
* @param jumps The jump list that need to be resolved. * @param jumps The jump list that need to be resolved.
*/ */
void resolveRemaining(Jump jumps) { void resolveRemaining(Jump jumps) {
LabelledBlock labelledBlock = null; LoopBlock doWhileFalse = null;
StructuredBlock outerMost = lastModified; StructuredBlock outerMost = lastModified;
boolean removeLast = false; boolean removeLast = false;
next_jump:
for (; jumps != null; jumps = jumps.next) { for (; jumps != null; jumps = jumps.next) {
StructuredBlock prevBlock = jumps.prev; StructuredBlock prevBlock = jumps.prev;
@ -635,18 +607,19 @@ public class FlowBlock {
prevBlock.removeJump(); prevBlock.removeJump();
if (breakToBlock == null) { if (breakToBlock == null) {
/* Nothing else helped, so put a labelled /* Nothing else helped, so put a do/while(0)
* block around outerMost and break to that * block around outerMost and break to that
* block. * block.
*/ */
if (labelledBlock == null) { if (doWhileFalse == null) {
labelledBlock = new LabelledBlock(); doWhileFalse = new LoopBlock(LoopBlock.DOWHILE,
LoopBlock.FALSE);
} }
/* Adapt outermost, so that it contains the break. */ /* Adapt outermost, so that it contains the break. */
while (!outerMost.contains(prevBlock)) while (!outerMost.contains(prevBlock))
outerMost = outerMost.outer; outerMost = outerMost.outer;
prevBlock.appendBlock prevBlock.appendBlock
(new BreakBlock(labelledBlock, true)); (new BreakBlock(doWhileFalse, breaklevel > 0));
} else } else
prevBlock.appendBlock prevBlock.appendBlock
(new BreakBlock(breakToBlock, breaklevel > 1)); (new BreakBlock(breakToBlock, breaklevel > 1));
@ -655,10 +628,10 @@ public class FlowBlock {
if (removeLast) if (removeLast)
lastModified.removeJump(); lastModified.removeJump();
if (labelledBlock != null) { if (doWhileFalse != null) {
labelledBlock.replace(outerMost); doWhileFalse.replace(outerMost);
labelledBlock.setBody(outerMost); doWhileFalse.setBody(outerMost);
lastModified = labelledBlock; lastModified = doWhileFalse;
} }
} }
@ -685,14 +658,10 @@ public class FlowBlock {
} else { } else {
myInfo.gen.addAll(hisInfo.gen); myInfo.gen.addAll(hisInfo.gen);
myInfo.kill.retainAll(hisInfo.kill); myInfo.kill.retainAll(hisInfo.kill);
if (myInfo.jumps == null) Jump myJumps = myInfo.jumps;
myInfo.jumps = hisInfo.jumps; while (myJumps.next != null)
else { myJumps = myJumps.next;
Jump myJumps = myInfo.jumps; myJumps.next = hisInfo.jumps;
while (myJumps.next != null)
myJumps = myJumps.next;
myJumps.next = hisInfo.jumps;
}
} }
} }
} }
@ -993,6 +962,10 @@ public class FlowBlock {
} }
public void setSuccessors(FlowBlock[] succs) { public void setSuccessors(FlowBlock[] succs) {
SlotSet blockIn = new SlotSet();
SlotSet blockKill = new SlotSet();
VariableSet blockGen = new VariableSet();
Jump[] jumps = new Jump[succs.length]; Jump[] jumps = new Jump[succs.length];
for (int i=0; i< succs.length; i++) { for (int i=0; i< succs.length; i++) {
Jump jump = new Jump(succs[i]); Jump jump = new Jump(succs[i]);
@ -1013,6 +986,7 @@ public class FlowBlock {
} }
if (jumps.length > 0) if (jumps.length > 0)
lastModified.setSuccessors(jumps); lastModified.setSuccessors(jumps);
gen = null;
kill = null; kill = null;
checkConsistent(); checkConsistent();
} }
@ -1033,10 +1007,6 @@ public class FlowBlock {
checkConsistent(); checkConsistent();
succ.checkConsistent(); succ.checkConsistent();
/* Merge catching successors */
unifyCatchSuccessors(succ);
succ.unifyCatchSuccessors(this);
if ((GlobalOptions.debuggingFlags if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_ANALYZE) != 0) & GlobalOptions.DEBUG_ANALYZE) != 0)
GlobalOptions.err.println GlobalOptions.err.println
@ -1108,6 +1078,7 @@ public class FlowBlock {
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0) if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0)
GlobalOptions.err.println("before remaining: "+this); GlobalOptions.err.println("before remaining: "+this);
next_jump:
for (; jumps != null; jumps = jumps.next) { for (; jumps != null; jumps = jumps.next) {
StructuredBlock prevBlock = jumps.prev; StructuredBlock prevBlock = jumps.prev;
@ -1143,8 +1114,7 @@ public class FlowBlock {
/* Now remove the jump of the lastModified if it points to /* Now remove the jump of the lastModified if it points to
* END_OF_METHOD. * END_OF_METHOD.
*/ */
if (lastModified.jump != null if (lastModified.jump.destination == END_OF_METHOD)
&& lastModified.jump.destination == END_OF_METHOD)
lastModified.removeJump(); lastModified.removeJump();
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0) if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0)
@ -1208,7 +1178,7 @@ public class FlowBlock {
LoopBlock lb = LoopBlock lb =
(LoopBlock) lastModified.outer.getSubBlocks()[0]; (LoopBlock) lastModified.outer.getSubBlocks()[0];
if (lb.cond == LoopBlock.FALSE && lb.type == LoopBlock.DOWHILE) { if (lb.cond == lb.FALSE && lb.type == lb.DOWHILE) {
/* The jump is directly following a /* The jump is directly following a
* do-while(false) block * do-while(false) block
@ -1344,7 +1314,7 @@ public class FlowBlock {
} }
/** /**
* Search for an appropriate successor. * Search for an apropriate successor.
* @param prevSucc The successor, that was previously tried. * @param prevSucc The successor, that was previously tried.
* @param start The minimum blockNr * @param start The minimum blockNr
* @param end The maximum blockNr + 1. * @param end The maximum blockNr + 1.
@ -1378,7 +1348,7 @@ public class FlowBlock {
} }
/** /**
* The main analysis. This calls doT1 and doT2 on appropriate * The main analyzation. This calls doT1 and doT2 on apropriate
* regions. Only blocks whose block number lies in the given block number * regions. Only blocks whose block number lies in the given block number
* range are considered. * range are considered.
* @param start the start of the block number range. * @param start the start of the block number range.
@ -1472,6 +1442,7 @@ public class FlowBlock {
* block lie in range [start,end). Otherwise * block lie in range [start,end). Otherwise
* we have no chance to combine these two blocks. * we have no chance to combine these two blocks.
*/ */
boolean predOutOfRange = false;
for (Iterator i = succ.predecessors.iterator(); for (Iterator i = succ.predecessors.iterator();
i.hasNext(); ) { i.hasNext(); ) {
FlowBlock pred = (FlowBlock)i.next(); FlowBlock pred = (FlowBlock)i.next();
@ -1915,62 +1886,4 @@ public class FlowBlock {
return super.toString(); return super.toString();
} }
} }
public void addExceptionHandler(Type excType, FlowBlock handler) {
SuccessorInfo info = (SuccessorInfo) successors.get(handler);
if (info == null) {
info = new SuccessorInfo();
info.gen = (VariableSet) gen.clone();
successors.put(handler, info);
handler.predecessors.add(this);
}
info.kill = new SlotSet();
if (info.catched == null)
info.catched = new ArrayList();
info.catched.add(excType);
}
private void unifyCatchSuccessors(FlowBlock succ) {
Iterator iter = successors.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
FlowBlock dest = (FlowBlock) entry.getKey();
SuccessorInfo myInfo = (SuccessorInfo) entry.getValue();
if (myInfo.catched == null)
continue;
SuccessorInfo succInfo = (SuccessorInfo) succ.successors.get(dest);
Iterator catchedIter = myInfo.catched.iterator();
while (catchedIter.hasNext()) {
Type excType = (Type) catchedIter.next();
if (succInfo != null && succInfo.catched != null
&& succInfo.catched.contains(excType))
continue;
if (!(block instanceof TryBlock))
new TryBlock(this);
TryBlock tryBlock = (TryBlock) block;
if (excType != null) {
CatchBlock catchBlock = new CatchBlock(excType);
tryBlock.addCatchBlock(catchBlock);
Jump jump = new Jump(dest);
jump.next = myInfo.jumps;
myInfo.jumps = jump;
lastModified = new EmptyBlock(jump);
catchBlock.setCatchBlock(lastModified);
catchedIter.remove();
} else {
FinallyBlock catchBlock = new FinallyBlock();
tryBlock.addCatchBlock(catchBlock);
Jump jump = new Jump(dest);
jump.next = myInfo.jumps;
myInfo.jumps = jump;
lastModified = new EmptyBlock(jump);
catchBlock.setCatchBlock(lastModified);
catchedIter.remove();
}
}
if (myInfo.catched.isEmpty())
myInfo.catched = null;
}
}
} }

@ -18,8 +18,10 @@
*/ */
package net.sf.jode.flow; package net.sf.jode.flow;
import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
import net.sf.jode.type.Type;
import net.sf.jode.util.SimpleSet; import net.sf.jode.util.SimpleSet;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
@ -60,13 +62,6 @@ public class IfThenElseBlock extends StructuredBlock {
this.cond = cond; this.cond = cond;
} }
/**
* Gets the condition. The expression returned has boolean type.
*/
public Expression getCondition() {
return cond;
}
/** /**
* Sets the then block. * Sets the then block.
* @param thenBlock the then block, must be non null. * @param thenBlock the then block, must be non null.
@ -172,7 +167,7 @@ public class IfThenElseBlock extends StructuredBlock {
{ {
boolean needBrace = thenBlock.needsBraces(); boolean needBrace = thenBlock.needsBraces();
writer.print("if ("); writer.print("if (");
cond.dumpExpression(TabbedPrintWriter.EXPL_PAREN, writer); cond.dumpExpression(writer.EXPL_PAREN, writer);
writer.print(")"); writer.print(")");
if (needBrace) if (needBrace)
writer.openBrace(); writer.openBrace();

@ -24,6 +24,7 @@ import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
import net.sf.jode.expr.StoreInstruction; import net.sf.jode.expr.StoreInstruction;
import net.sf.jode.expr.LocalStoreOperator; import net.sf.jode.expr.LocalStoreOperator;
import net.sf.jode.util.SimpleSet;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.Set; import java.util.Set;
@ -136,12 +137,12 @@ public class InstructionBlock extends InstructionContainer {
StoreInstruction store = (StoreInstruction) instr; StoreInstruction store = (StoreInstruction) instr;
LocalInfo local = LocalInfo local =
((LocalStoreOperator) store.getLValue()).getLocalInfo(); ((LocalStoreOperator) store.getLValue()).getLocalInfo();
writer.startOp(TabbedPrintWriter.NO_PAREN, 0); writer.startOp(writer.NO_PAREN, 0);
local.dumpDeclaration(writer); local.dumpDeclaration(writer);
writer.breakOp(); writer.breakOp();
writer.print(" = "); writer.print(" = ");
store.getSubExpressions()[1].makeInitializer(local.getType()); store.getSubExpressions()[1].makeInitializer(local.getType());
store.getSubExpressions()[1].dumpExpression(TabbedPrintWriter.IMPL_PAREN, store.getSubExpressions()[1].dumpExpression(writer.IMPL_PAREN,
writer); writer);
writer.endOp(); writer.endOp();
} else { } else {
@ -149,9 +150,9 @@ public class InstructionBlock extends InstructionContainer {
if (instr.getType() != Type.tVoid) { if (instr.getType() != Type.tVoid) {
writer.print("PUSH "); writer.print("PUSH ");
instr.dumpExpression(TabbedPrintWriter.IMPL_PAREN, writer); instr.dumpExpression(writer.IMPL_PAREN, writer);
} else } else
instr.dumpExpression(TabbedPrintWriter.NO_PAREN, writer); instr.dumpExpression(writer.NO_PAREN, writer);
} catch (RuntimeException ex) { } catch (RuntimeException ex) {
writer.print("(RUNTIME ERROR IN EXPRESSION)"); writer.print("(RUNTIME ERROR IN EXPRESSION)");
} }

@ -18,8 +18,10 @@
*/ */
package net.sf.jode.flow; package net.sf.jode.flow;
import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
import net.sf.jode.expr.InvokeOperator; import net.sf.jode.expr.InvokeOperator;
import net.sf.jode.expr.LocalVarOperator;
import net.sf.jode.util.SimpleSet; import net.sf.jode.util.SimpleSet;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util

@ -18,6 +18,7 @@
*/ */
package net.sf.jode.flow; package net.sf.jode.flow;
import net.sf.jode.GlobalOptions;
/** /**
* This class represents an unconditional jump. * This class represents an unconditional jump.
@ -62,6 +63,7 @@ public class Jump {
* @param writer The tabbed print writer, where we print to. * @param writer The tabbed print writer, where we print to.
*/ */
public void dumpSource(net.sf.jode.decompiler.TabbedPrintWriter writer) public void dumpSource(net.sf.jode.decompiler.TabbedPrintWriter writer)
throws java.io.IOException
{ {
if (destination == null) if (destination == null)
writer.println ("GOTO null-ptr!!!!!"); writer.println ("GOTO null-ptr!!!!!");

@ -1,161 +0,0 @@
/* LoopBlock Copyright (C) 1998-2002 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or 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 program; see the file COPYING.LESSER. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: LoopBlock.java 1411 2012-03-01 22:39:08Z hoenicke $
*/
package net.sf.jode.flow;
import net.sf.jode.decompiler.TabbedPrintWriter;
/**
* This is the structured block for an Loop block.
*/
public class LabelledBlock extends StructuredBlock implements BreakableBlock {
/**
* The body of this labelled block. This is always a valid block and not null.
*/
StructuredBlock bodyBlock;
/**
* The stack after the break.
*/
VariableStack breakedStack;
/**
* The serial number for labels.
*/
static int serialno = 0;
/**
* The label of this instruction, or null if it needs no label.
*/
String label = null;
public LabelledBlock() {
}
public void setBody(StructuredBlock body) {
bodyBlock = body;
bodyBlock.outer = this;
body.setFlowBlock(flowBlock);
}
/**
* Replaces the given sub block with a new block.
* @param oldBlock the old sub block.
* @param newBlock the new sub block.
* @return false, if oldBlock wasn't a direct sub block.
*/
public boolean replaceSubBlock(StructuredBlock oldBlock,
StructuredBlock newBlock) {
if (bodyBlock != oldBlock)
return false;
bodyBlock = newBlock;
newBlock.outer = this;
oldBlock.outer = null;
return true;
}
/**
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
return new StructuredBlock[] { bodyBlock };
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
super.dumpSource(writer);
}
public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException
{
if (label != null) {
writer.untab();
writer.println(label+":");
writer.tab();
}
boolean needBrace = bodyBlock.needsBraces();
if (needBrace)
writer.openBrace();
else
writer.println();
writer.tab();
bodyBlock.dumpSource(writer);
writer.untab();
writer.closeBrace();
}
/**
* Returns the label of this block and creates a new label, if
* there wasn't a label previously.
*/
public String getLabel() {
if (label == null)
label = "label_"+(serialno++);
return label;
}
/**
* Is called by BreakBlock, to tell us that this block is breaked.
*/
public void setBreaked() {
}
/**
* This is called after the analysis is completely done. It
* will remove all PUSH/stack_i expressions, (if the bytecode
* is correct).
* @param stack the stack at begin of the block
* @return null if there is no way to the end of this block,
* otherwise the stack after the block has executed.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
VariableStack afterBody = bodyBlock.mapStackToLocal(stack);
mergeBreakedStack(afterBody);
return breakedStack;
}
/**
* Is called by BreakBlock, to tell us what the stack can be after a
* break.
* @return false if the stack is inconsistent.
*/
public void mergeBreakedStack(VariableStack stack) {
if (breakedStack != null)
breakedStack.merge(stack);
else
breakedStack = stack;
}
public void removePush() {
bodyBlock.removePush();
}
/**
* Determines if there is a sub block, that flows through to the end
* of this block. If this returns true, you know that jump is null.
* @return true, if the jump may be safely changed.
*/
public boolean jumpMayBeChanged() {
return false;
}
}

@ -19,6 +19,7 @@
package net.sf.jode.flow; package net.sf.jode.flow;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;
import net.sf.jode.type.Type;
import net.sf.jode.decompiler.LocalInfo; import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
import net.sf.jode.expr.ConstOperator; import net.sf.jode.expr.ConstOperator;
@ -315,7 +316,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
writer.print("for (;;)"); writer.print("for (;;)");
else { else {
writer.print("while ("); writer.print("while (");
cond.dumpExpression(TabbedPrintWriter.EXPL_PAREN, writer); cond.dumpExpression(writer.EXPL_PAREN, writer);
writer.print(")"); writer.print(")");
} }
break; break;
@ -324,13 +325,13 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
break; break;
case FOR: case FOR:
writer.print("for ("); writer.print("for (");
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 0); writer.startOp(writer.EXPL_PAREN, 0);
if (initInstr != null) { if (initInstr != null) {
if (isDeclaration) { if (isDeclaration) {
StoreInstruction store = (StoreInstruction) initInstr; StoreInstruction store = (StoreInstruction) initInstr;
LocalInfo local = ((LocalStoreOperator) store LocalInfo local = ((LocalStoreOperator) store
.getLValue()).getLocalInfo(); .getLValue()).getLocalInfo();
writer.startOp(TabbedPrintWriter.NO_PAREN, 1); writer.startOp(writer.NO_PAREN, 1);
local.dumpDeclaration(writer); local.dumpDeclaration(writer);
writer.breakOp(); writer.breakOp();
writer.print(" = "); writer.print(" = ");
@ -339,16 +340,16 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
store.getSubExpressions()[1].dumpExpression(writer, 100); store.getSubExpressions()[1].dumpExpression(writer, 100);
writer.endOp(); writer.endOp();
} else } else
initInstr.dumpExpression(TabbedPrintWriter.NO_PAREN, writer); initInstr.dumpExpression(writer.NO_PAREN, writer);
} else { } else {
writer.print("/**/"); writer.print("/**/");
} }
writer.print("; "); writer.print("; ");
writer.breakOp(); writer.breakOp();
cond.dumpExpression(TabbedPrintWriter.IMPL_PAREN, writer); cond.dumpExpression(writer.IMPL_PAREN, writer);
writer.print("; "); writer.print("; ");
writer.breakOp(); writer.breakOp();
incrInstr.dumpExpression(TabbedPrintWriter.NO_PAREN, writer); incrInstr.dumpExpression(writer.NO_PAREN, writer);
writer.endOp(); writer.endOp();
writer.print(")"); writer.print(")");
break; break;
@ -364,7 +365,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
if (needBrace) if (needBrace)
writer.closeBraceContinue(); writer.closeBraceContinue();
writer.print("while ("); writer.print("while (");
cond.dumpExpression(TabbedPrintWriter.EXPL_PAREN, writer); cond.dumpExpression(writer.EXPL_PAREN, writer);
writer.println(");"); writer.println(");");
} else if (needBrace) } else if (needBrace)
writer.closeBrace(); writer.closeBrace();

@ -63,7 +63,7 @@ public class ReturnBlock extends InstructionContainer {
newStack = stack.pop(params); newStack = stack.pop(params);
} }
} }
return newStack; return null;
} }
public void removePush() { public void removePush() {
@ -85,7 +85,7 @@ public class ReturnBlock extends InstructionContainer {
writer.print("return"); writer.print("return");
if (instr != null) { if (instr != null) {
writer.print(" "); writer.print(" ");
instr.dumpExpression(TabbedPrintWriter.IMPL_PAREN, writer); instr.dumpExpression(writer.IMPL_PAREN, writer);
} }
writer.println(";"); writer.println(";");
} }

@ -19,6 +19,7 @@
package net.sf.jode.flow; package net.sf.jode.flow;
import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.decompiler.TabbedPrintWriter;
import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.expr.LocalStoreOperator; import net.sf.jode.expr.LocalStoreOperator;
import net.sf.jode.expr.StoreInstruction; import net.sf.jode.expr.StoreInstruction;
import net.sf.jode.util.SimpleSet; import net.sf.jode.util.SimpleSet;

@ -19,8 +19,10 @@
package net.sf.jode.flow; package net.sf.jode.flow;
import net.sf.jode.decompiler.LocalInfo; import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.util.ArrayEnum;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.Collection;
import java.util.AbstractSet; import java.util.AbstractSet;
import java.util.Set; import java.util.Set;
import java.util.Iterator; import java.util.Iterator;
@ -205,6 +207,7 @@ public final class SlotSet extends AbstractSet implements Cloneable {
*/ */
public void mergeKill(Set kill) { public void mergeKill(Set kill) {
grow(kill.size()); grow(kill.size());
big_loop:
for (Iterator i = kill.iterator(); i.hasNext(); ) { for (Iterator i = kill.iterator(); i.hasNext(); ) {
LocalInfo li2 = (LocalInfo) i.next(); LocalInfo li2 = (LocalInfo) i.next();
if (!containsSlot(li2.getSlot())) if (!containsSlot(li2.getSlot()))

@ -336,11 +336,8 @@ public abstract class StructuredBlock {
if (jump != null) if (jump != null)
outer.getSubBlocks()[0].moveJump(jump); outer.getSubBlocks()[0].moveJump(jump);
outer.getSubBlocks()[0].replace(outer); outer.getSubBlocks()[0].replace(outer);
} else { } else
if (outer.jump != null)
outer.getSubBlocks()[1].moveJump(outer.jump);
outer.getSubBlocks()[1].replace(outer); outer.getSubBlocks()[1].replace(outer);
}
return; return;
} }
@ -552,7 +549,7 @@ public abstract class StructuredBlock {
subs[i].checkConsistent(); subs[i].checkConsistent();
} }
if (jump != null && jump.destination != null) { if (jump != null && jump.destination != null) {
Jump jumps = flowBlock.getJumps(jump.destination); Jump jumps = (Jump) flowBlock.getJumps(jump.destination);
for (; jumps != jump; jumps = jumps.next) { for (; jumps != jump; jumps = jumps.next) {
if (jumps == null) if (jumps == null)
throw new InternalError("Inconsistency"); throw new InternalError("Inconsistency");

@ -91,7 +91,7 @@ public class SynchronizedBlock extends StructuredBlock {
writer.println("MISSING MONITORENTER"); writer.println("MISSING MONITORENTER");
writer.print("synchronized ("); writer.print("synchronized (");
if (object != null) if (object != null)
object.dumpExpression(TabbedPrintWriter.EXPL_PAREN, writer); object.dumpExpression(writer.EXPL_PAREN, writer);
else else
writer.print(local.getName()); writer.print(local.getName());
writer.print(")"); writer.print(")");

@ -33,7 +33,7 @@ public class ThrowBlock extends ReturnBlock {
throws java.io.IOException throws java.io.IOException
{ {
writer.print("throw "); writer.print("throw ");
instr.dumpExpression(TabbedPrintWriter.NO_PAREN, writer); instr.dumpExpression(writer.NO_PAREN, writer);
writer.println(";"); writer.println(";");
} }
} }

@ -20,9 +20,11 @@
package net.sf.jode.flow; package net.sf.jode.flow;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import net.sf.jode.GlobalOptions; import net.sf.jode.GlobalOptions;
import net.sf.jode.decompiler.Analyzer;
import net.sf.jode.decompiler.ClassAnalyzer; import net.sf.jode.decompiler.ClassAnalyzer;
import net.sf.jode.decompiler.MethodAnalyzer; import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.FieldAnalyzer; import net.sf.jode.decompiler.FieldAnalyzer;
import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.Options; import net.sf.jode.decompiler.Options;
import net.sf.jode.decompiler.OuterValues; import net.sf.jode.decompiler.OuterValues;
import net.sf.jode.decompiler.OuterValueListener; import net.sf.jode.decompiler.OuterValueListener;
@ -34,6 +36,8 @@ import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.bytecode.MethodInfo; import net.sf.jode.bytecode.MethodInfo;
import java.io.IOException; import java.io.IOException;
import java.util.Vector;
import java.util.Enumeration;
/** /**
* This class will transform the constructors. We differ three types of * This class will transform the constructors. We differ three types of
@ -436,6 +440,7 @@ public class TransformConstructors {
+ cons[i].getMethodHeader()); + cons[i].getMethodHeader());
MethodAnalyzer constr = cons[i]; MethodAnalyzer constr = cons[i];
MethodType constrType = constr.getType();
/* /*
* constructor(outerValues, params, opt. jikesAnonInner param) { * constructor(outerValues, params, opt. jikesAnonInner param) {
@ -457,6 +462,7 @@ public class TransformConstructors {
* constructor$? as Jikes constructor. */ * constructor$? as Jikes constructor. */
StructuredBlock sb = constr.getMethodHeader().block; StructuredBlock sb = constr.getMethodHeader().block;
Vector localLoads = null;
InstructionBlock superBlock = null; InstructionBlock superBlock = null;
InvokeOperator superInvoke = null; InvokeOperator superInvoke = null;
if (i >= type0Count) { if (i >= type0Count) {
@ -541,6 +547,7 @@ public class TransformConstructors {
int firstParamSlot = slot; int firstParamSlot = slot;
int firstOuterSlot = firstParam; int firstOuterSlot = firstParam;
int slotDist = firstParamSlot - firstOuterSlot;
/* check the remaining parameters. /* check the remaining parameters.
*/ */
for (int j=firstParam; j < methodParams.length; j++) { for (int j=firstParam; j < methodParams.length; j++) {
@ -850,6 +857,8 @@ public class TransformConstructors {
} }
private void transformBlockInitializer(StructuredBlock block) { private void transformBlockInitializer(StructuredBlock block) {
StructuredBlock start = null;
StructuredBlock tail = null;
int lastField = -1; int lastField = -1;
while (block instanceof SequentialBlock) { while (block instanceof SequentialBlock) {
StructuredBlock ib = block.getSubBlocks()[0]; StructuredBlock ib = block.getSubBlocks()[0];

@ -27,6 +27,7 @@ import net.sf.jode.expr.*;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.Set; import java.util.Set;
import java.util.Map;
import java.util.Iterator; import java.util.Iterator;
///#enddef ///#enddef
///#def COLLECTIONEXTRA java.lang ///#def COLLECTIONEXTRA java.lang
@ -583,7 +584,7 @@ public class TransformExceptionHandlers {
* |- monitorexit local_x | * |- monitorexit local_x |
* ` jump after this block (without jsr monexit) | * ` jump after this block (without jsr monexit) |
* | * |
* catchBlock: | * catchBlock: |
* local_n = stack | * local_n = stack |
* monitorexit local_x | * monitorexit local_x |
* throw local_n | * throw local_n |
@ -598,7 +599,7 @@ public class TransformExceptionHandlers {
/* Merge try and catch flow blocks. No need to insert the /* Merge try and catch flow blocks. No need to insert the
* catchFlow.block into the try flow though, since all its * catchFlow.block into the try flow though, since all its
* instruction are synthetic. * instructions are synthetic.
*/ */
mergeTryCatch(tryFlow, catchFlow); mergeTryCatch(tryFlow, catchFlow);
@ -713,7 +714,7 @@ public class TransformExceptionHandlers {
&& doWhileFalse.bodyBlock instanceof SequentialBlock) { && doWhileFalse.bodyBlock instanceof SequentialBlock) {
if (transformSubRoutine(catchBlock.getSubBlocks()[1])) { if (transformSubRoutine(catchBlock.getSubBlocks()[1])) {
finallyBlock = catchBlock.getSubBlocks()[1]; finallyBlock = catchBlock.getSubBlocks()[1];
catchBlock = doWhileFalse.bodyBlock; catchBlock = (SequentialBlock) doWhileFalse.bodyBlock;
} }
} }
} }
@ -776,6 +777,7 @@ public class TransformExceptionHandlers {
finallyBlock = subRoutine.block; finallyBlock = subRoutine.block;
DescriptionBlock msg = new DescriptionBlock DescriptionBlock msg = new DescriptionBlock
("ERROR: Missing return address handling"); ("ERROR: Missing return address handling");
StructuredBlock subblock = subRoutine.block;
msg.replace(finallyBlock); msg.replace(finallyBlock);
msg.appendBlock(finallyBlock); msg.appendBlock(finallyBlock);
} }
@ -933,7 +935,7 @@ public class TransformExceptionHandlers {
GlobalOptions.err.println GlobalOptions.err.println
("Warning: Can't completely analyze try."); ("Warning: Can't completely analyze try.");
} }
new TryBlock(tryFlow); TryBlock tryBlock = new TryBlock(tryFlow);
} else if (!(tryFlow.block instanceof TryBlock)) } else if (!(tryFlow.block instanceof TryBlock))
throw new InternalError("no TryBlock"); throw new InternalError("no TryBlock");

@ -19,6 +19,7 @@
package net.sf.jode.flow; package net.sf.jode.flow;
import net.sf.jode.decompiler.LocalInfo; import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.util.ArrayEnum;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.Collection; import java.util.Collection;
@ -192,6 +193,7 @@ public final class VariableSet extends AbstractSet implements Cloneable {
public VariableSet intersect(VariableSet vs) { public VariableSet intersect(VariableSet vs) {
VariableSet intersection = new VariableSet(); VariableSet intersection = new VariableSet();
intersection.grow(Math.min(count, vs.count)); intersection.grow(Math.min(count, vs.count));
big_loop:
for (int i=0; i<count; i++) { for (int i=0; i<count; i++) {
LocalInfo li = locals[i]; LocalInfo li = locals[i];
int slot = li.getSlot(); int slot = li.getSlot();
@ -210,6 +212,7 @@ public final class VariableSet extends AbstractSet implements Cloneable {
*/ */
public void mergeGenKill(Collection gen, SlotSet kill) { public void mergeGenKill(Collection gen, SlotSet kill) {
grow(gen.size()); grow(gen.size());
big_loop:
for (Iterator i = gen.iterator(); i.hasNext(); ) { for (Iterator i = gen.iterator(); i.hasNext(); ) {
LocalInfo li2 = (LocalInfo) i.next(); LocalInfo li2 = (LocalInfo) i.next();
if (!kill.containsSlot(li2.getSlot())) if (!kill.containsSlot(li2.getSlot()))

@ -21,6 +21,7 @@ package net.sf.jode.flow;
import net.sf.jode.decompiler.LocalInfo; import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
import net.sf.jode.expr.LocalLoadOperator; import net.sf.jode.expr.LocalLoadOperator;
import net.sf.jode.expr.Operator;
/** /**
* This class represents the state of the stack at various points in * This class represents the state of the stack at various points in
@ -111,7 +112,7 @@ public class VariableStack {
} }
public VariableStack executeSpecial(SpecialBlock special) { public VariableStack executeSpecial(SpecialBlock special) {
if (special.type == SpecialBlock.POP) { if (special.type == special.POP) {
int popped = 0; int popped = 0;
int newLength = stackMap.length; int newLength = stackMap.length;
while (popped < special.count) { while (popped < special.count) {
@ -123,7 +124,7 @@ public class VariableStack {
LocalInfo[] newStack = new LocalInfo[newLength]; LocalInfo[] newStack = new LocalInfo[newLength];
System.arraycopy(stackMap, 0, newStack, 0, newLength); System.arraycopy(stackMap, 0, newStack, 0, newLength);
return new VariableStack(newStack); return new VariableStack(newStack);
} else if (special.type == SpecialBlock.DUP) { } else if (special.type == special.DUP) {
int popped = 0; int popped = 0;
int numDup = 0; int numDup = 0;
int startDup = stackMap.length; int startDup = stackMap.length;
@ -150,7 +151,7 @@ public class VariableStack {
System.arraycopy(stackMap, startDup, newStack, startDup + numDup, System.arraycopy(stackMap, startDup, newStack, startDup + numDup,
numDup); numDup);
return new VariableStack(newStack); return new VariableStack(newStack);
} else if (special.type == SpecialBlock.SWAP) { } else if (special.type == special.SWAP) {
LocalInfo[] newStack = new LocalInfo[stackMap.length]; LocalInfo[] newStack = new LocalInfo[stackMap.length];
System.arraycopy(stackMap, 0, newStack, 0, stackMap.length - 2); System.arraycopy(stackMap, 0, newStack, 0, stackMap.length - 2);
if (stackMap[stackMap.length-2].getType().stackSize() != 1 if (stackMap[stackMap.length-2].getType().stackSize() != 1

@ -33,9 +33,12 @@ import net.sf.jode.bytecode.TypeSignature;
import java.io.IOException; import java.io.IOException;
import java.util.BitSet; import java.util.BitSet;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
///#enddef ///#enddef
@ -1142,6 +1145,7 @@ public class CodeVerifier implements Opcodes {
} }
if (ref.getName().equals("<init>")) { if (ref.getName().equals("<init>")) {
Type clazz = info.pop(); Type clazz = info.pop();
String typeSig = clazz.getTypeSig();
String refClazzSig = ref.getClazz(); String refClazzSig = ref.getClazz();
Type refClazz = tType("N" + refClazzSig.substring(1)); Type refClazz = tType("N" + refClazzSig.substring(1));
if (opcode != opc_invokespecial if (opcode != opc_invokespecial
@ -1415,7 +1419,7 @@ public class CodeVerifier implements Opcodes {
if (info.jsrInfo == null || !retVarType.isOfType(tType("R"))) if (info.jsrInfo == null || !retVarType.isOfType(tType("R")))
throw new VerifyException(instr.getDescription()); throw new VerifyException(instr.getDescription());
Block jsrTarget = retVarType.getJsrTarget(); Block jsrTarget = retVarType.getJsrTarget();
BitSet usedLocals = info.jsrInfo.jsrUsed; BitSet usedLocals = (BitSet) info.jsrInfo.jsrUsed;
for (Block lastTarget = info.jsrInfo.jsrTarget; for (Block lastTarget = info.jsrInfo.jsrTarget;
jsrTarget != lastTarget; jsrTarget != lastTarget;
lastTarget = subInfos[lastTarget.getBlockNr()] lastTarget = subInfos[lastTarget.getBlockNr()]

@ -92,6 +92,7 @@ public class Interpreter implements Opcodes {
for (int i=0; i < stack.length; i++) for (int i=0; i < stack.length; i++)
stack[i] = new Value(); stack[i] = new Value();
Block[] blocks = bb.getBlocks();
Block nextBlock = bb.getStartBlock(); Block nextBlock = bb.getStartBlock();
int stacktop = 0; int stacktop = 0;

@ -18,6 +18,7 @@
*/ */
package net.sf.jode.jvm; package net.sf.jode.jvm;
import net.sf.jode.GlobalOptions;
import net.sf.jode.bytecode.BasicBlocks; import net.sf.jode.bytecode.BasicBlocks;
import net.sf.jode.bytecode.Block; import net.sf.jode.bytecode.Block;
import net.sf.jode.bytecode.ClassInfo; import net.sf.jode.bytecode.ClassInfo;
@ -106,6 +107,7 @@ public class SyntheticAnalyzer implements Opcodes {
BasicBlocks bb = method.getBasicBlocks(); BasicBlocks bb = method.getBasicBlocks();
Block[] blocks = bb.getBlocks();
Block startBlock = bb.getStartBlock(); Block startBlock = bb.getStartBlock();
Handler[] excHandlers = bb.getExceptionHandlers(); Handler[] excHandlers = bb.getExceptionHandlers();
if (startBlock == null if (startBlock == null
@ -183,6 +185,7 @@ public class SyntheticAnalyzer implements Opcodes {
Handler[] excHandlers = bb.getExceptionHandlers(); Handler[] excHandlers = bb.getExceptionHandlers();
if (excHandlers != null && excHandlers.length != 0) if (excHandlers != null && excHandlers.length != 0)
return false; return false;
Block[] blocks = bb.getBlocks();
Block startBlock = bb.getStartBlock(); Block startBlock = bb.getStartBlock();
if (startBlock == null) if (startBlock == null)
return false; return false;
@ -308,12 +311,12 @@ public class SyntheticAnalyzer implements Opcodes {
} }
MethodInfo refMethod MethodInfo refMethod
= refClazz.findMethod(ref.getName(), ref.getType()); = refClazz.findMethod(ref.getName(), ref.getType());
MethodType refType = Type.tMethod(classInfo.getClassPath(), String[] refParams = TypeSignature.getParameterTypes(ref.getType());
ref.getType()); String retType = TypeSignature.getReturnType(ref.getType());
if ((refMethod.getModifiers() & modifierMask) != 0 if ((refMethod.getModifiers() & modifierMask) != 0
|| refType.getParameterTypes().length != params) || refParams.length != params)
return false; return false;
if (refType.getReturnType() == Type.tVoid) { if (retType.equals("V")) {
if (iter.hasNext()) if (iter.hasNext())
return false; return false;
} else { } else {
@ -387,12 +390,11 @@ public class SyntheticAnalyzer implements Opcodes {
return false; return false;
MethodInfo refMethod MethodInfo refMethod
= refClazz.findMethod(ref.getName(), ref.getType()); = refClazz.findMethod(ref.getName(), ref.getType());
MethodType refType = Type.tMethod(classInfo.getClassPath(), String[] refParams = TypeSignature.getParameterTypes(ref.getType());
ref.getType());
if ((refMethod.getModifiers() & modifierMask) != 0 if ((refMethod.getModifiers() & modifierMask) != 0
|| !refMethod.getName().equals("<init>") || !refMethod.getName().equals("<init>")
|| unifyParam == -1 || unifyParam == -1
|| refType.getParameterTypes().length != params - 2) || refParams.length != params - 2)
return false; return false;
if (iter.hasNext()) if (iter.hasNext())
return false; return false;

@ -18,6 +18,7 @@
*/ */
package net.sf.jode.jvm; package net.sf.jode.jvm;
import net.sf.jode.bytecode.*;
/** /**
* This class represents a stack value. * This class represents a stack value.

@ -18,6 +18,7 @@
*/ */
package net.sf.jode.jvm; package net.sf.jode.jvm;
import net.sf.jode.bytecode.*;
/** /**
* This exception is thrown by the CodeVerifier on various conditions. * This exception is thrown by the CodeVerifier on various conditions.

@ -20,6 +20,7 @@
package net.sf.jode.obfuscator; package net.sf.jode.obfuscator;
import net.sf.jode.GlobalOptions; import net.sf.jode.GlobalOptions;
import net.sf.jode.bytecode.ClassPath; import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.bytecode.Reference; import net.sf.jode.bytecode.Reference;
import net.sf.jode.obfuscator.modules.WildCard; import net.sf.jode.obfuscator.modules.WildCard;
import net.sf.jode.obfuscator.modules.MultiIdentifierMatcher; import net.sf.jode.obfuscator.modules.MultiIdentifierMatcher;
@ -35,6 +36,10 @@ import java.util.Set;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.TreeMap;
///#enddef
///#def COLLECTIONEXTRA java.lang
import java.lang.UnsupportedOperationException;
///#enddef ///#enddef
///#ifdef JDK12 ///#ifdef JDK12

@ -30,6 +30,7 @@ import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Map;
import java.util.Random; import java.util.Random;
///#enddef ///#enddef
///#def COLLECTIONEXTRA java.lang ///#def COLLECTIONEXTRA java.lang
@ -393,7 +394,7 @@ public class ClassIdentifier extends Identifier {
initialized = true; initialized = true;
try { try {
info.load(ClassInfo.ALL); info.load(info.ALL);
} catch (IOException ex) { } catch (IOException ex) {
throw new RuntimeException("Can't read class " + info.getName() throw new RuntimeException("Can't read class " + info.getName()
+ ": " + ex.getMessage()); + ": " + ex.getMessage());
@ -748,6 +749,7 @@ public class ClassIdentifier extends Identifier {
* they must be there!). * they must be there!).
*/ */
ClassInfo superInfo = info.getSuperclass(); ClassInfo superInfo = info.getSuperclass();
ClassIdentifier superIdent = this;
while (superInfo != null) { while (superInfo != null) {
ClassIdentifier superident = Main.getClassBundle() ClassIdentifier superident = Main.getClassBundle()
.getClassIdentifier(superInfo.getName()); .getClassIdentifier(superInfo.getName());

@ -18,12 +18,14 @@
*/ */
package net.sf.jode.obfuscator; package net.sf.jode.obfuscator;
import java.lang.reflect.Modifier;
import net.sf.jode.bytecode.*; import net.sf.jode.bytecode.*;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
///#enddef ///#enddef

@ -19,6 +19,7 @@
package net.sf.jode.obfuscator; package net.sf.jode.obfuscator;
import net.sf.jode.GlobalOptions; import net.sf.jode.GlobalOptions;
import java.io.*;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.Map; import java.util.Map;
import java.util.Iterator; import java.util.Iterator;

@ -23,6 +23,7 @@ import net.sf.jode.GlobalOptions;
import gnu.getopt.LongOpt; import gnu.getopt.LongOpt;
import gnu.getopt.Getopt; import gnu.getopt.Getopt;
import java.lang.reflect.Modifier;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.FileReader; import java.io.FileReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save