Line breaking added.

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1227 379699f6-c40d-0410-875b-85095c16579e
branch_1_1
jochen 25 years ago
parent b8e6d80e8c
commit 92878b6692
  1. 4
      jode/NEWS
  2. 33
      jode/jode/decompiler/ClassAnalyzer.java.in
  3. 5
      jode/jode/decompiler/FieldAnalyzer.java.in
  4. 28
      jode/jode/decompiler/MethodAnalyzer.java.in
  5. 598
      jode/jode/decompiler/TabbedPrintWriter.java
  6. 1
      jode/jode/expr/ArrayLoadOperator.java
  7. 1
      jode/jode/expr/BinaryOperator.java
  8. 2
      jode/jode/expr/CheckCastOperator.java
  9. 3
      jode/jode/expr/CompareBinaryOperator.java
  10. 3
      jode/jode/expr/CompareUnaryOperator.java
  11. 14
      jode/jode/expr/ConstantArrayOperator.java
  12. 65
      jode/jode/expr/Expression.java.in
  13. 18
      jode/jode/expr/FieldOperator.java.in
  14. 9
      jode/jode/expr/IfThenElseOperator.java
  15. 4
      jode/jode/expr/InstanceOfOperator.java
  16. 81
      jode/jode/expr/InvokeOperator.java.in
  17. 1
      jode/jode/expr/StoreInstruction.java
  18. 8
      jode/jode/expr/StringAddOperator.java
  19. 2
      jode/jode/flow/ConditionalBlock.java
  20. 2
      jode/jode/flow/IfThenElseBlock.java.in
  21. 16
      jode/jode/flow/InstructionBlock.java.in
  22. 32
      jode/jode/flow/LoopBlock.java.in
  23. 2
      jode/jode/flow/ReturnBlock.java
  24. 2
      jode/jode/flow/SwitchBlock.java
  25. 2
      jode/jode/flow/SynchronizedBlock.java.in
  26. 2
      jode/jode/flow/ThrowBlock.java

@ -1,3 +1,7 @@
New in 1.0.94
* break long lines
* small bug fixes
New in 1.0.93
* anonymous and inner class decompilation reworked.
* replaced a bash specific construct in acinclude.m4

@ -177,10 +177,10 @@ public class ClassAnalyzer
return outerValues;
}
public void addBlockInitializer(int index,
StructuredBlock initializer) {
public void addBlockInitializer(int index, StructuredBlock initializer) {
if (blockInitializers[index] == null)
blockInitializers[index] = initializer;
else
blockInitializers[index].appendBlock(initializer);
}
@ -423,7 +423,7 @@ public class ClassAnalyzer
for (int i=0; i< fields.length; i++) {
if (blockInitializers[i] != null) {
if (needNewLine)
writer.println("");
writer.println();
writer.openBrace();
writer.tab();
blockInitializers[i].dumpSource(writer);
@ -439,13 +439,13 @@ public class ClassAnalyzer
if (fields[i].skipWriting())
continue;
if (needFieldNewLine)
writer.println("");
writer.println();
fields[i].dumpSource(writer);
needNewLine = true;
}
if (blockInitializers[fields.length] != null) {
if (needNewLine)
writer.println("");
writer.println();
writer.openBrace();
writer.tab();
blockInitializers[fields.length].dumpSource(writer);
@ -455,7 +455,7 @@ public class ClassAnalyzer
}
for (int i=0; i< inners.length; i++) {
if (needNewLine)
writer.println("");
writer.println();
if ((Options.options & Options.OPTION_IMMEDIATE) != 0) {
// We now do the analyzation we skipped before.
@ -489,7 +489,7 @@ public class ClassAnalyzer
if (methods[i].skipWriting())
continue;
if (needNewLine)
writer.println("");
writer.println();
if (pl != null) {
double methodCompl = methods[i].getComplexity() * subScale;
@ -520,6 +520,7 @@ public class ClassAnalyzer
return;
}
writer.startOp(writer.NO_PAREN, 0);
/* Clear the SUPER bit, which is also used as SYNCHRONIZED bit. */
int modifiedModifiers = modifiers & ~Modifier.SYNCHRONIZED;
if (clazz.isInterface())
@ -538,26 +539,30 @@ public class ClassAnalyzer
/* interface is in modif */
if (!clazz.isInterface())
writer.print("class ");
writer.println(name);
writer.tab();
writer.print(name);
ClassInfo superClazz = clazz.getSuperclass();
if (superClazz != null &&
superClazz != ClassInfo.javaLangObject) {
writer.println("extends " + (writer.getClassString
writer.breakOp();
writer.print(" extends " + (writer.getClassString
(superClazz, Scope.CLASSNAME)));
}
ClassInfo[] interfaces = clazz.getInterfaces();
if (interfaces.length > 0) {
writer.print(clazz.isInterface() ? "extends " : "implements ");
writer.breakOp();
writer.print(clazz.isInterface() ? " extends " : " implements ");
writer.startOp(writer.EXPL_PAREN, 1);
for (int i=0; i < interfaces.length; i++) {
if (i > 0)
if (i > 0) {
writer.print(", ");
writer.breakOp();
}
writer.print(writer.getClassString
(interfaces[i], Scope.CLASSNAME));
}
writer.println("");
writer.endOp();
}
writer.untab();
writer.println();
writer.openBrace();
writer.tab();

@ -176,6 +176,7 @@ public class FieldAnalyzer implements Analyzer {
| Modifier.STATIC
| Modifier.FINAL);
*/
writer.startOp(writer.NO_PAREN, 0);
String modif = Modifier.toString(modifiedModifiers);
if (modif.length() > 0)
writer.print(modif+" ");
@ -183,9 +184,11 @@ public class FieldAnalyzer implements Analyzer {
writer.printType(type);
writer.print(" " + fieldName);
if (constant != null) {
writer.breakOp();
writer.print(" = ");
constant.dumpExpression(writer);
constant.dumpExpression(writer.IMPL_PAREN, writer);
}
writer.endOp();
writer.println(";");
}

@ -838,17 +838,18 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
if (isConstructor() && isStatic())
modifiedModifiers &= ~Modifier.FINAL;
String delim ="";
writer.startOp(writer.NO_PAREN, 1);
String delim = "";
if (minfo.isSynthetic()) {
writer.print("/*synthetic*/");
delim = " ";
}
String modif = Modifier.toString(modifiedModifiers);
if (modif.length() > 0) {
writer.print(delim + modif);
if (modif.length() > 0)
delim = " ";
}
if (isConstructor
&& (isStatic()
|| (classAnalyzer.getName() == null
@ -862,24 +863,35 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
writer.printType(getReturnType());
writer.print(" " + methodName);
}
writer.breakOp();
writer.print("(");
writer.startOp(writer.EXPL_PAREN, 0);
int offset = skipParams + (isStatic() ? 0 : 1);
for (int i = offset; i < param.length; i++) {
if (i > offset)
if (i > offset) {
writer.print(", ");
writer.breakOp();
}
param[i].dumpDeclaration(writer);
}
writer.endOp();
writer.print(")");
}
if (exceptions.length > 0) {
writer.println("");
writer.print("throws ");
writer.breakOp();
writer.print(" throws ");
writer.startOp(writer.EXPL_PAREN, 2);
for (int i= 0; i< exceptions.length; i++) {
if (i > 0)
writer.print(", ");
if (i > 0) {
writer.print(",");
writer.breakOp();
writer.print(" ");
}
writer.printType(exceptions[i]);
}
writer.endOp();
}
writer.endOp();
if (code != null) {
writer.openBrace();
writer.tab();

@ -20,34 +20,467 @@
package jode.decompiler;
import java.io.*;
import java.util.Stack;
import java.util.Vector;
import java.util.Enumeration;
import jode.AssertError;
import jode.GlobalOptions;
import jode.bytecode.ClassInfo;
import jode.bytecode.InnerClassInfo;
import jode.type.*;
public class TabbedPrintWriter {
boolean atbol;
int indentsize;
int currentIndent = 0;
String indentStr = "";
PrintWriter pw;
ImportHandler imports;
Stack scopes = new Stack();
/* The indentation size. */
private int indentsize;
/* The size of a tab, MAXINT if we shouldn't use tabs at all. */
private int tabWidth;
private int lineWidth;
private int currentIndent = 0;
private String indentStr = "";
private PrintWriter pw;
private ImportHandler imports;
private Stack scopes = new Stack();
private StringBuffer currentLine;
private BreakPoint currentBP;
public final static int EXPL_PAREN = 0;
public final static int NO_PAREN = 1;
public final static int IMPL_PAREN = 2;
public final static int DONT_BREAK = 3;
/**
* Convert the numeric indentation to a string.
*/
protected String makeIndentStr(int indent) {
String tabSpaceString = /* (tab x 20) . (space x 20) */
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ";
if (indent < 0)
return "NEGATIVEINDENT"+indent;
int tabs = indent / tabWidth;
indent -= tabs * tabWidth;
if (tabs <= 20 && indent <= 20) {
/* The fast way. */
return tabSpaceString.substring(20 - tabs, 20 + indent);
} else {
/* the not so fast way */
StringBuffer sb = new StringBuffer(tabs + indent);
while (tabs > 20) {
sb.append(tabSpaceString.substring(0,20));
tabs -= 20;
}
sb.append(tabSpaceString.substring(0, tabs));
while (indent > 20) {
sb.append(tabSpaceString.substring(20));
indent -= 20;
}
sb.append(tabSpaceString.substring(40 - indent));
return sb.toString();
}
}
class BreakPoint {
int options;
int breakPenalty;
int breakPos;
int startPos;
BreakPoint parentBP;
Vector childBPs;
int nesting = 0;
int endPos;
int whatBreak = 0;
public BreakPoint(BreakPoint parent, int position) {
this.breakPos = position;
this.parentBP = parent;
this.options = DONT_BREAK;
this.breakPenalty = 0;
this.startPos = -1;
this.endPos = -1;
this.whatBreak = 0;
this.childBPs = null;
}
public void startOp(int opts, int penalty, int pos) {
if (startPos != -1) {
System.err.println("WARNING: missing breakOp");
Thread.dumpStack();
return;
}
startPos = pos;
options = opts;
breakPenalty = penalty;
childBPs = new Vector();
breakOp(pos);
}
public void breakOp(int pos) {
childBPs.addElement (new BreakPoint(this, pos));
}
public void endOp(int pos) {
endPos = pos;
if (childBPs.size() == 1) {
BreakPoint child =
(BreakPoint) currentBP.childBPs.elementAt(0);
if (child.startPos == -1) {
startPos = endPos = -1;
childBPs = null;
} else if (child.startPos == currentBP.startPos
&& child.endPos == currentBP.endPos) {
if (options == DONT_BREAK)
options = child.options;
childBPs = child.childBPs;
}
}
}
public void dump(String line) {
if (startPos == -1) {
pw.print(line);
} else {
pw.print(line.substring(0, startPos));
dumpRegion(line);
pw.print(line.substring(endPos));
}
}
public void dumpRegion(String line) {
String parens = "{\010{}\010}<\010<>\010>[\010[]\010]`\010`'\010'"
.substring(options*6, options*6+6);
pw.print(parens.substring(0,3));
Enumeration enum = childBPs.elements();
int cur = startPos;
BreakPoint child = (BreakPoint) enum.nextElement();
if (child.startPos >= 0) {
pw.print(line.substring(cur, child.startPos));
child.dumpRegion(line);
cur = child.endPos;
}
while (enum.hasMoreElements()) {
child = (BreakPoint) enum.nextElement();
pw.print(line.substring(cur, child.breakPos));
pw.print("!\010!"+breakPenalty);
cur = child.breakPos;
if (child.startPos >= 0) {
pw.print(line.substring(child.breakPos, child.startPos));
child.dumpRegion(line);
cur = child.endPos;
}
}
pw.print(line.substring(cur, endPos));
pw.print(parens.substring(3));
}
public void printLines(int indent, String line) {
if (startPos == -1) {
pw.print(line);
} else {
pw.print(line.substring(0, startPos));
printRegion(indent + startPos, line);
pw.print(line.substring(endPos));
}
}
public void printRegion(int indent, String line) {
if (options == IMPL_PAREN) {
pw.print("(");
indent++;
}
Enumeration enum = childBPs.elements();
int cur = startPos;
BreakPoint child = (BreakPoint) enum.nextElement();
if (child.startPos >= 0) {
pw.print(line.substring(cur, child.startPos));
child.printRegion(indent + child.startPos - cur, line);
cur = child.endPos;
}
if (options == NO_PAREN)
indent += indentsize;
String indentStr = makeIndentStr(indent);
while (enum.hasMoreElements()) {
child = (BreakPoint) enum.nextElement();
pw.print(line.substring(cur, child.breakPos));
pw.println();
pw.print(indentStr);
cur = child.breakPos;
if (cur < endPos && line.charAt(cur) == ' ')
cur++;
if (child.startPos >= 0) {
pw.print(line.substring(cur, child.startPos));
child.printRegion(indent + child.startPos - cur, line);
cur = child.endPos;
}
}
pw.print(line.substring(cur, endPos));
if (options == IMPL_PAREN)
pw.print(")");
}
public BreakPoint commitMinPenalty(int space, int lastSpace,
int minPenalty) {
if (startPos == -1 || lastSpace > endPos - startPos
|| minPenalty == 10 * (endPos - startPos - lastSpace)) {
/* We don't have to break anything */
startPos = -1;
childBPs = null;
return this;
}
int size = childBPs.size();
if (size > 1 && options != DONT_BREAK) {
/* penalty if we are breaking the line here. */
int breakPen
= getBreakPenalty(space, lastSpace, minPenalty + 1);
// pw.print("commit[bp="+breakPen+";"+minPenalty+";"
// +space+","+lastSpace+"]");
if (minPenalty == breakPen) {
commitBreakPenalty(space, lastSpace, breakPen);
return this;
}
}
/* penalty if we are breaking only one child */
for (int i=0; i < size; i++) {
BreakPoint child = (BreakPoint) childBPs.elementAt(i);
int front = child.startPos - startPos;
int tail = endPos - child.endPos;
int needPenalty = minPenalty - (i < size - 1 ? 1 : 0);
if (needPenalty ==
child.getMinPenalty(space - front,
lastSpace - front - tail,
needPenalty + 1)) {
child = child.commitMinPenalty(space - front,
lastSpace - front - tail,
needPenalty);
child.breakPos = breakPos;
return child;
}
}
pw.println("XXXXXXXXXXX CAN'T COMMIT");
startPos = -1;
childBPs = null;
return this;
}
public int getMinPenalty(int space, int lastSpace, int minPenalty) {
// pw.print("getMinPenalty["+startPos+","+endPos+"]("+space+","+lastSpace+","+minPenalty+") ");
if (10 * -lastSpace >= minPenalty) {
// pw.println("= minPenalty");
return minPenalty;
}
if (startPos == -1)
return 10 * -lastSpace;
if (lastSpace > endPos - startPos) {
// pw.println("= NULL");
return 0;
}
if (minPenalty <= 1) {
// pw.println("= ONE");
return minPenalty;
}
if (minPenalty > 10 * (endPos - startPos - lastSpace))
minPenalty = 10 * (endPos - startPos - lastSpace);
// pw.print("[mp="+minPenalty+"]");
int size = childBPs.size();
if (size == 0)
return minPenalty;
if (size > 1 && options != DONT_BREAK) {
/* penalty if we are breaking at this level. */
minPenalty = getBreakPenalty(space, lastSpace, minPenalty);
// pw.print("[bp="+minPenalty+"]");
}
/* penalty if we are breaking only one child */
for (int i=0; i < size; i++) {
BreakPoint child = (BreakPoint) childBPs.elementAt(i);
int front = child.startPos - startPos;
int tail = endPos - child.endPos;
int penalty = (i < size - 1 ? 1 : 0);
minPenalty = penalty +
child.getMinPenalty(space - front,
lastSpace - front - tail,
minPenalty - penalty);
}
// pw.println("= "+minPenalty);
return minPenalty;
}
public void commitBreakPenalty(int space, int lastSpace,
int minPenalty) {
// pw.println("commitBreakPenalty: "+startPos+","+endPos+";"
// +space+","+lastSpace+";"+minPenalty);
if (options == IMPL_PAREN) {
space--;
lastSpace -= 2;
}
Enumeration enum = childBPs.elements();
childBPs = new Vector();
int currInd = 0;
BreakPoint lastChild, nextChild;
boolean indentNext = options == NO_PAREN;
for (lastChild = (BreakPoint) enum.nextElement();
enum.hasMoreElements(); lastChild = nextChild) {
nextChild = (BreakPoint) enum.nextElement();
int childStart = lastChild.breakPos;
int childEnd = nextChild.breakPos;
if (currInd > 0) {
currInd += childEnd - childStart;
if (currInd <= space)
continue;
}
if (childStart < endPos
&& currentLine.charAt(childStart) == ' ')
childStart++;
if (childEnd - childStart > space) {
int front = lastChild.startPos - childStart;
int tail = childEnd - lastChild.endPos;
int childPenalty = lastChild.getMinPenalty
(space - front, space - front - tail, minPenalty);
currInd = 0;
childBPs.addElement
(lastChild.commitMinPenalty
(space - front, space - front - tail, childPenalty));
} else {
lastChild.startPos = -1;
lastChild.childBPs = null;
childBPs.addElement(lastChild);
currInd = childEnd - childStart;
}
if (indentNext) {
space -= indentsize;
lastSpace -= indentsize;
indentNext = false;
}
}
int childStart = lastChild.breakPos;
if (currInd > 0 && currInd + endPos - childStart <= lastSpace)
return;
if (childStart < endPos
&& currentLine.charAt(childStart) == ' ')
childStart++;
if (endPos - childStart > lastSpace) {
int front = lastChild.startPos - childStart;
int tail = endPos - lastChild.endPos;
int childPenalty = lastChild.getMinPenalty
(space - front, lastSpace - front - tail, minPenalty + 1);
childBPs.addElement
(lastChild.commitMinPenalty
(space - front, lastSpace - front - tail, childPenalty));
} else {
lastChild.startPos = -1;
lastChild.childBPs = null;
childBPs.addElement(lastChild);
}
}
public int getBreakPenalty(int space, int lastSpace, int minPenalty) {
int penalty = breakPenalty;
int currInd = 0;
if (options == IMPL_PAREN) {
space--;
lastSpace -= 2;
}
if (space < 0)
return minPenalty;
Enumeration enum = childBPs.elements();
BreakPoint lastChild, nextChild;
boolean indentNext = options == NO_PAREN;
for (lastChild = (BreakPoint) enum.nextElement();
enum.hasMoreElements(); lastChild = nextChild) {
nextChild = (BreakPoint) enum.nextElement();
int childStart = lastChild.breakPos;
int childEnd = nextChild.breakPos;
if (currInd > 0) {
currInd += childEnd - childStart;
if (currInd <= space)
continue;
penalty++;
if (indentNext) {
space -= indentsize;
lastSpace -= indentsize;
indentNext = false;
}
}
if (childStart < endPos
&& currentLine.charAt(childStart) == ' ')
childStart++;
if (childEnd - childStart > space) {
int front = lastChild.startPos - childStart;
int tail = childEnd - lastChild.endPos;
penalty += 1 + lastChild.getMinPenalty
(space - front, space - front - tail,
minPenalty - penalty - 1);
if (indentNext) {
space -= indentsize;
lastSpace -= indentsize;
indentNext = false;
}
currInd = 0;
} else
currInd = childEnd - childStart;
if (penalty >= minPenalty)
return minPenalty;
}
int childStart = lastChild.breakPos;
if (currInd > 0) {
if (currInd + endPos - childStart <= lastSpace)
return penalty;
penalty++;
if (indentNext) {
space -= indentsize;
lastSpace -= indentsize;
indentNext = false;
}
}
if (childStart < endPos
&& currentLine.charAt(childStart) == ' ')
childStart++;
if (endPos - childStart > lastSpace) {
int front = lastChild.startPos - childStart;
int tail = endPos - lastChild.endPos;
penalty += lastChild.getMinPenalty
(space - front, lastSpace - front - tail,
minPenalty - penalty);
}
if (penalty < minPenalty)
return penalty;
return minPenalty;
}
}
public TabbedPrintWriter (OutputStream os, ImportHandler imports,
boolean autoFlush) {
pw = new PrintWriter(os, autoFlush);
this.imports = imports;
this.indentsize = (Options.outputStyle & Options.TAB_SIZE_MASK);
atbol = true;
init();
}
public TabbedPrintWriter (Writer os, ImportHandler imports,
boolean autoFlush) {
pw = new PrintWriter(os, autoFlush);
this.imports = imports;
this.indentsize = (Options.outputStyle & Options.TAB_SIZE_MASK);
atbol = true;
init();
}
public TabbedPrintWriter (OutputStream os, ImportHandler imports) {
@ -66,82 +499,101 @@ public class TabbedPrintWriter {
this(os, null);
}
/**
* Convert the numeric indentation to a string.
*/
protected void makeIndentStr() {
int tabs = (currentIndent >> 3);
// This is a very fast implementation.
if (tabs <= 20)
indentStr = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t "
.substring(20 - tabs, 20 + (currentIndent&7));
else {
/* the slow way */
StringBuffer sb = new StringBuffer(tabs+7);
while (tabs > 20) {
sb.append("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t "
.substring(0,20));
tabs -= 20;
}
sb.append("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t "
.substring(20 - tabs, 20 + (currentIndent&7)));
indentStr = sb.toString();
}
public void init() {
this.indentsize = (Options.outputStyle & Options.TAB_SIZE_MASK);
this.tabWidth = 8;
this.lineWidth = 79;
currentLine = new StringBuffer();
currentBP = new BreakPoint(null, 0);
currentBP.startOp(DONT_BREAK, 1, 0);
}
public void tab() {
currentIndent += indentsize;
makeIndentStr();
indentStr = makeIndentStr(currentIndent);
}
public void untab() {
currentIndent -= indentsize;
makeIndentStr();
indentStr = makeIndentStr(currentIndent);
}
public void startOp(int options, int penalty) {
currentBP = (BreakPoint) currentBP.childBPs.lastElement();
currentBP.startOp(options, penalty, currentLine.length());
}
public void breakOp() {
int pos = currentLine.length();
if (pos > currentBP.startPos && currentLine.charAt(pos-1) == ' ')
pos--;
currentBP.breakOp(pos);
}
public void endOp() {
currentBP.endOp(currentLine.length());
currentBP = currentBP.parentBP;
if (currentBP == null)
throw new NullPointerException();
}
public Object saveOps() {
Stack state = new Stack();
int pos = currentLine.length();
while (currentBP.parentBP != null) {
state.push(new Integer(currentBP.options));
state.push(new Integer(currentBP.breakPenalty));
currentBP.endPos = pos;
currentBP = currentBP.parentBP;
}
return state;
}
public void restoreOps(Object s) {
Stack state = (Stack) s;
while (!state.isEmpty()) {
int penalty = ((Integer) state.pop()).intValue();
int options = ((Integer) state.pop()).intValue();
startOp(options, penalty);
}
}
public void println(String str) {
if (atbol)
pw.print(indentStr);
pw.println(str);
atbol = true;
print(str);
println();
}
public void println() {
currentBP.endPos = currentLine.length();
// pw.print(indentStr);
// currentBP.dump(currentLine.toString());
// pw.println();
int lw = lineWidth - currentIndent;
int minPenalty = currentBP.getMinPenalty(lw, lw, Integer.MAX_VALUE/2);
currentBP = currentBP.commitMinPenalty(lw, lw, minPenalty);
// pw.print(indentStr);
// currentBP.dump(currentLine.toString());
// pw.println();
pw.print(indentStr);
currentBP.printLines(currentIndent, currentLine.toString());
pw.println();
atbol = true;
currentLine.setLength(0);
currentBP = new BreakPoint(null, 0);
currentBP.startOp(DONT_BREAK, 1, 0);
}
public void print(String str) {
if (atbol)
pw.print(indentStr);
pw.print(str);
atbol = false;
currentLine.append(str);
}
public void printType(Type type) {
print(getTypeString(type));
}
/**
* Print a opening brace with the current indentation style.
* Called at the end of the line of the instance that opens the
* brace. It doesn't do a tab stop after opening the brace.
*/
public void openBrace() {
if ((Options.outputStyle & Options.BRACE_AT_EOL) != 0)
if (atbol)
println("{");
else
println(" {");
else {
if (!atbol)
println();
if (currentIndent > 0)
tab();
println("{");
}
}
public void pushScope(Scope scope) {
scopes.push(scope);
}
@ -282,6 +734,24 @@ public class TabbedPrintWriter {
return type.toString();
}
/**
* Print a opening brace with the current indentation style.
* Called at the end of the line of the instance that opens the
* brace. It doesn't do a tab stop after opening the brace.
*/
public void openBrace() {
if ((Options.outputStyle & Options.BRACE_AT_EOL) != 0) {
print(currentLine.length() > 0 ? " {" : "{");
println();
} else {
if (currentLine.length() > 0)
println();
if (currentIndent > 0)
tab();
println("{");
}
}
/**
* Print a opening brace with the current indentation style.
* Called at the end of the line of the instance that opens the
@ -291,7 +761,7 @@ public class TabbedPrintWriter {
if ((Options.outputStyle & Options.BRACE_AT_EOL) != 0)
println("{");
else {
if (!atbol)
if (currentLine.length() > 0)
println();
if (currentIndent > 0)
tab();

@ -50,6 +50,7 @@ public class ArrayLoadOperator extends Operator {
public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException {
subExpressions[0].dumpExpression(writer, 950);
writer.breakOp();
writer.print("[");
subExpressions[1].dumpExpression(writer, 0);
writer.print("]");

@ -87,6 +87,7 @@ public class BinaryOperator extends Operator {
public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException {
subExpressions[0].dumpExpression(writer, getPriority());
writer.breakOp();
writer.print(getOperatorString());
subExpressions[1].dumpExpression(writer, getPriority()+1);
}

@ -56,6 +56,7 @@ public class CheckCastOperator extends Operator {
writer.print("(");
writer.printType(castType);
writer.print(") ");
writer.breakOp();
/* There are special cases where a cast isn't allowed. We must cast
* to the common super type before. This cases always give a runtime
@ -66,6 +67,7 @@ public class CheckCastOperator extends Operator {
writer.print("(");
writer.printType(superType);
writer.print(") ");
writer.breakOp();
}
subExpressions[0].dumpExpression(writer, 700);
}

@ -86,7 +86,8 @@ public class CompareBinaryOperator extends Operator {
public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException {
subExpressions[0].dumpExpression(writer, getPriority());
subExpressions[0].dumpExpression(writer, getPriority()+1);
writer.breakOp();
writer.print(getOperatorString());
subExpressions[1].dumpExpression(writer, getPriority()+1);
}

@ -108,7 +108,8 @@ public class CompareUnaryOperator extends Operator {
public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException {
subExpressions[0].dumpExpression(writer, getPriority());
subExpressions[0].dumpExpression(writer, getPriority()+1);
writer.breakOp();
writer.print(getOperatorString());
writer.print(objectType?"null":"0");
}

@ -99,24 +99,22 @@ public class ConstantArrayOperator extends Operator {
if (!isInitializer) {
writer.print("new ");
writer.printType(type.getHint());
writer.breakOp();
writer.print(" ");
}
writer.openBraceNoSpace();
writer.tab();
writer.print("{ ");
writer.startOp(writer.EXPL_PAREN, 0);
for (int i=0; i< subExpressions.length; i++) {
if (i>0) {
if (i % 10 == 0)
writer.println(",");
else
writer.print(", ");
writer.breakOp();
}
if (subExpressions[i] != null)
subExpressions[i].dumpExpression(writer, 0);
else
empty.dumpExpression(writer, 0);
}
writer.println();
writer.untab();
writer.closeBraceNoSpace();
writer.endOp();
writer.print(" }");
}
}

@ -96,7 +96,6 @@ public abstract class Expression {
return parent;
}
/**
* Get priority of the operator.
* Currently this priorities are known:
@ -121,6 +120,13 @@ public abstract class Expression {
*/
public abstract int getPriority();
/**
* Get the penalty for splitting up this operator.
*/
public int getBreakPenalty() {
return 0;
}
/**
* Get the number of operands.
* @return The number of stack entries this expression needs.
@ -237,29 +243,56 @@ public abstract class Expression {
public abstract void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException;
public void dumpExpression(int options, TabbedPrintWriter writer)
throws java.io.IOException
{
writer.startOp(options, getBreakPenalty());
dumpExpression(writer);
writer.endOp();
}
public void dumpExpression(TabbedPrintWriter writer, int minPriority)
throws java.io.IOException {
int options;
boolean needParen1 = false, needParen2 = false;
if (type == Type.tError) {
if (minPriority > 700) {
needParen1 = true;
writer.print("(");
}
writer.print("/*TYPE ERROR*/ ");
minPriority = 700;
}
boolean needEndOp1 = false, needEndOp2 = false;
String typecast = "";
if (type == Type.tError)
typecast = "/*TYPE_ERROR*/";
else if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_TYPES) != 0) {
& GlobalOptions.DEBUG_TYPES) != 0)
typecast = "(TYPE "+type+")";
if (typecast != "") {
if (minPriority > 700) {
needParen1 = true;
needEndOp1 = true;
writer.print("(");
}
writer.print("(TYPE "+type+") ");
writer.startOp(writer.EXPL_PAREN, 0);
} else if (minPriority < 700) {
needEndOp1 = true;
writer.startOp(writer.IMPL_PAREN, 1);
}
writer.print(typecast);
writer.breakOp();
writer.print(" ");
minPriority = 700;
}
if (getPriority() < minPriority) {
int priority = getPriority();
if (priority < minPriority) {
needParen2 = true;
needEndOp2 = true;
writer.print("(");
writer.startOp(writer.EXPL_PAREN, getBreakPenalty());
} else if (priority != minPriority) {
needEndOp2 = true;
if (getType() == Type.tVoid)
writer.startOp(writer.NO_PAREN, getBreakPenalty());
else
writer.startOp(writer.IMPL_PAREN, 1 + getBreakPenalty());
}
try {
@ -268,11 +301,17 @@ public abstract class Expression {
writer.print("(RUNTIME ERROR IN EXPRESSION)");
}
if (needEndOp2) {
writer.endOp();
if (needParen2)
writer.print(")");
}
if (needEndOp1) {
writer.endOp();
if (needParen1)
writer.print(")");
}
}
public String toString() {
try {

@ -181,15 +181,22 @@ public abstract class FieldOperator extends Operator {
if (!classType.equals(Type.tClass(methodAnalyzer.getClazz()))
|| methodAnalyzer.findLocal(fieldName) != null) {
writer.printType(classType);
writer.breakOp();
writer.print(".");
}
writer.print(fieldName);
} else if (needsCast(subExpressions[0].getType().getCanonic())) {
writer.print("((");
writer.print("(");
writer.startOp(writer.EXPL_PAREN, 1);
writer.print("(");
writer.printType(classType);
writer.print(") ");
writer.breakOp();
subExpressions[0].dumpExpression(writer, 700);
writer.print(").");
writer.endOp();
writer.print(")");
writer.breakOp();
writer.print(".");
writer.print(fieldName);
} else {
if (opIsThis) {
@ -200,6 +207,7 @@ public abstract class FieldOperator extends Operator {
if (scope == null || writer.conflicts(fieldName, scope,
Scope.FIELDNAME)) {
thisOp.dumpExpression(writer, 950);
writer.breakOp();
writer.print(".");
} else if (writer.conflicts(fieldName, scope,
Scope.AMBIGUOUSNAME)
@ -216,16 +224,18 @@ public abstract class FieldOperator extends Operator {
ana = (ClassAnalyzer) ana.getParent();
if (ana == scope)
// For a simple outer class we can say this
writer.print("this.");
writer.print("this");
else {
// For a class that owns a method that owns
// us, we have to give the full class name
thisOp.dumpExpression(writer, 950);
writer.print(".");
}
writer.breakOp();
writer.print(".");
}
} else {
subExpressions[0].dumpExpression(writer, 950);
writer.breakOp();
writer.print(".");
}
writer.print(fieldName);

@ -103,15 +103,22 @@ public class IfThenElseOperator extends Operator {
public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException {
subExpressions[0].dumpExpression(writer, 201);
writer.breakOp();
writer.print(" ? ");
int subPriority = 0;
if (!subExpressions[1].getType().getHint().isOfType
(subExpressions[2].getType())) {
writer.startOp(writer.IMPL_PAREN, 2);
/* We need a cast here */
writer.print("(");
writer.printType(getType().getHint());
writer.print(") ");
subPriority = 700;
}
subExpressions[1].dumpExpression(writer, 0);
subExpressions[1].dumpExpression(writer, subPriority);
if (subPriority == 700)
writer.endOp();
writer.breakOp();
writer.print(" : ");
subExpressions[2].dumpExpression(writer, 200);
}

@ -51,12 +51,16 @@ public class InstanceOfOperator extends Operator {
Type superType
= instanceType.getCastHelper(subExpressions[0].getType());
if (superType != null) {
writer.startOp(writer.IMPL_PAREN, 2);
writer.print("(");
writer.printType(superType);
writer.print(") ");
writer.breakOp();
subExpressions[0].dumpExpression(writer, 700);
writer.endOp();
} else
subExpressions[0].dumpExpression(writer, 550);
writer.breakOp();
writer.print(" instanceof ");
writer.printType(instanceType);
}

@ -800,6 +800,10 @@ public final class InvokeOperator extends Operator
}
}
public int getBreakPenalty() {
return 5;
}
/* Invokes never equals: they may return different values even if
* they have the same parameters.
*/
@ -816,6 +820,7 @@ public final class InvokeOperator extends Operator
for (int i=0; i< subExpressions.length; i++)
paramTypes[i] = subExpressions[i].getType().getCanonic();
writer.startOp(writer.NO_PAREN, 0);
switch (methodFlag) {
case CONSTRUCTOR: {
@ -903,19 +908,25 @@ public final class InvokeOperator extends Operator
if (writer.conflicts(outer.name, scope, Scope.CLASSNAME)) {
qualifiedNew = true;
outerExpr.dumpExpression(writer, 950);
writer.breakOp();
writer.print(".");
}
} else {
qualifiedNew = true;
if (outerExpr.getType() instanceof NullType) {
writer.print("((");
writer.print("(");
writer.startOp(writer.EXPL_PAREN, 1);
writer.print("(");
writer.printType(Type.tClass
(ClassInfo.forName(outer.outer)));
writer.print(") ");
writer.breakOp();
outerExpr.dumpExpression(writer, 700);
writer.endOp();
writer.print(")");
} else
outerExpr.dumpExpression(writer, 950);
writer.breakOp();
writer.print(".");
}
}
@ -940,9 +951,15 @@ public final class InvokeOperator extends Operator
break;
}
writer.print("((UNCONSTRUCTED)");
subExpressions[0].dumpExpression(writer, 950);
writer.print(").");
writer.print("(");
writer.startOp(writer.EXPL_PAREN, 0);
writer.print("(UNCONSTRUCTED)");
writer.breakOp();
subExpressions[0].dumpExpression(writer, 700);
writer.endOp();
writer.print(")");
writer.breakOp();
writer.print(".");
writer.printType(Type.tClass(clazz));
break;
}
@ -956,17 +973,23 @@ public final class InvokeOperator extends Operator
ClassInfo superClazz = getClassInfo().getSuperclass();
paramTypes[0] = superClazz == null
? Type.tObject : Type.tClass(superClazz);
writer.breakOp();
writer.print(".");
} else {
/* XXX check if this is a private method. */
}
} else {
writer.print("((NON VIRTUAL ");
writer.print("(");
writer.startOp(writer.EXPL_PAREN, 0);
writer.print("(NON VIRTUAL ");
writer.printType(classType);
writer.print(")");
paramTypes[0] = classType;
writer.print(") ");
writer.breakOp();
subExpressions[0].dumpExpression(writer, 700);
writer.print(").");
writer.endOp();
writer.print(")");
writer.breakOp();
writer.print(".");
}
writer.print(methodName);
break;
@ -978,13 +1001,18 @@ public final class InvokeOperator extends Operator
if (paramTypes[0].equals(classType))
subExpressions[0].dumpExpression(writer, 950);
else {
writer.print("((");
writer.print("(");
writer.startOp(writer.EXPL_PAREN, 0);
writer.print("(");
writer.printType(classType);
writer.print(")");
writer.print(") ");
writer.breakOp();
paramTypes[0] = classType;
subExpressions[0].dumpExpression(writer, 700);
writer.endOp();
writer.print(")");
}
writer.breakOp();
writer.print(".");
writer.print(methodName);
break;
@ -996,6 +1024,7 @@ public final class InvokeOperator extends Operator
if (scope == null
||writer.conflicts(methodName, scope, Scope.METHODNAME)) {
writer.printType(classType);
writer.breakOp();
writer.print(".");
}
writer.print(methodName);
@ -1009,6 +1038,7 @@ public final class InvokeOperator extends Operator
Scope.CLASSSCOPE);
if (writer.conflicts(methodName, scope, Scope.METHODNAME)) {
thisOp.dumpExpression(writer, 950);
writer.breakOp();
writer.print(".");
} else if (/* This is a inherited field conflicting
* with a field name in some outer class.
@ -1020,61 +1050,78 @@ public final class InvokeOperator extends Operator
while (ana.getParent() instanceof ClassAnalyzer
&& ana != scope)
ana = (ClassAnalyzer) ana.getParent();
if (ana == scope)
if (ana == scope) {
// For a simple outer class we can say this
writer.print("this.");
else {
writer.print("this");
} else {
// For a class that owns a method that owns
// us, we have to give the full class name
thisOp.dumpExpression(writer, 950);
writer.print(".");
}
writer.breakOp();
writer.print(".");
}
} else {
if (needsCast(0, paramTypes)){
writer.print("((");
writer.print("(");
writer.startOp(writer.EXPL_PAREN, 1);
writer.print("(");
writer.printType(classType);
writer.print(") ");
writer.breakOp();
subExpressions[0].dumpExpression(writer, 700);
writer.endOp();
writer.print(")");
paramTypes[0] = classType;
} else
subExpressions[0].dumpExpression(writer, 950);
writer.breakOp();
writer.print(".");
}
writer.print(methodName);
}
writer.endOp();
writer.breakOp();
writer.print("(");
writer.startOp(writer.EXPL_PAREN, 0);
boolean first = true;
int offset = skippedArgs;
while (arg < length) {
if (!first)
if (!first) {
writer.print(", ");
else
writer.breakOp();
} else
first = false;
int priority = 0;
if (needsCast(arg, paramTypes)) {
Type castType = methodType.getParameterTypes()[arg-offset];
writer.startOp(writer.IMPL_PAREN, 1);
writer.print("(");
writer.printType(castType);
writer.print(") ");
writer.breakOp();
paramTypes[arg] = castType;
priority = 700;
}
subExpressions[arg++].dumpExpression(writer, priority);
if (priority == 700)
writer.endOp();
}
writer.endOp();
writer.print(")");
if (anonymousNew) {
/* If this was an anonymous constructor call, we must now
* dump the source code of the anonymous class.
*/
Object state = writer.saveOps();
writer.openBrace();
writer.tab();
clazzAna.dumpBlock(writer);
writer.untab();
writer.closeBraceNoSpace();
writer.restoreOps(state);
}
}

@ -112,6 +112,7 @@ public class StoreInstruction extends Operator
throws java.io.IOException
{
subExpressions[0].dumpExpression(writer, 950);
writer.breakOp();
writer.print(getOperatorString());
subExpressions[1].dumpExpression(writer, 100);
}

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

@ -123,7 +123,7 @@ public class ConditionalBlock extends InstructionContainer {
throws java.io.IOException
{
writer.print("IF (");
instr.dumpExpression(writer);
instr.dumpExpression(writer.EXPL_PAREN, writer);
writer.println(")");
writer.tab();
trueBlock.dumpSource(writer);

@ -165,7 +165,7 @@ public class IfThenElseBlock extends StructuredBlock {
{
boolean needBrace = thenBlock.needsBraces();
writer.print("if (");
cond.dumpExpression(writer);
cond.dumpExpression(writer.EXPL_PAREN, writer);
writer.print(")");
if (needBrace)
writer.openBrace();

@ -140,15 +140,21 @@ public class InstructionBlock extends InstructionContainer {
StoreInstruction store = (StoreInstruction) instr;
LocalInfo local =
((LocalStoreOperator) store.getLValue()).getLocalInfo();
writer.startOp(writer.NO_PAREN, 0);
local.dumpDeclaration(writer);
writer.breakOp();
writer.print(" = ");
store.getSubExpressions()[1].dumpExpression(writer);
store.getSubExpressions()[1].dumpExpression(writer.IMPL_PAREN,
writer);
writer.endOp();
} else {
if (instr.getType() != Type.tVoid)
writer.print("PUSH ");
try {
instr.dumpExpression(writer);
if (instr.getType() != Type.tVoid) {
writer.print("PUSH ");
instr.dumpExpression(writer.IMPL_PAREN, writer);
} else
instr.dumpExpression(writer.NO_PAREN, writer);
} catch (RuntimeException ex) {
writer.print("(RUNTIME ERROR IN EXPRESSION)");
}

@ -313,7 +313,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
writer.print("for (;;)");
else {
writer.print("while (");
cond.dumpExpression(writer);
cond.dumpExpression(writer.EXPL_PAREN, writer);
writer.print(")");
}
break;
@ -322,21 +322,30 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
break;
case FOR:
writer.print("for (");
writer.startOp(writer.EXPL_PAREN, 0);
if (initInstr != null) {
if (isDeclaration) {
writer.printType(((LocalStoreOperator)
((CombineableOperator) initInstr)
.getLValue())
.getLocalInfo().getType().getHint());
writer.print(" ");
}
initInstr.dumpExpression(writer);
StoreInstruction store = (StoreInstruction) initInstr;
LocalInfo local = ((LocalStoreOperator) store
.getLValue()).getLocalInfo();
writer.startOp(writer.NO_PAREN, 1);
local.dumpDeclaration(writer);
writer.breakOp();
writer.print(" = ");
store.getSubExpressions()[1].dumpExpression(writer, 100);
writer.endOp();
} else
initInstr.dumpExpression(writer.NO_PAREN, writer);
} else {
writer.print("/**/");
}
writer.print("; ");
cond.dumpExpression(writer);
writer.breakOp();
cond.dumpExpression(writer.IMPL_PAREN, writer);
writer.print("; ");
incrInstr.dumpExpression(writer);
writer.breakOp();
incrInstr.dumpExpression(writer.NO_PAREN, writer);
writer.endOp();
writer.print(")");
break;
}
@ -351,13 +360,12 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
if (needBrace)
writer.closeBraceContinue();
writer.print("while (");
cond.dumpExpression(writer);
cond.dumpExpression(writer.EXPL_PAREN, writer);
writer.println(");");
} else if (needBrace)
writer.closeBrace();
}
boolean mayChangeJump = true;
/**

@ -77,7 +77,7 @@ public class ReturnBlock extends InstructionContainer {
writer.print("return");
if (instr != null) {
writer.print(" ");
instr.dumpExpression(writer);
instr.dumpExpression(writer.IMPL_PAREN, writer);
}
writer.println(";");
}

@ -195,7 +195,7 @@ implements BreakableBlock {
writer.tab();
}
writer.print("switch (");
instr.dumpExpression(writer);
instr.dumpExpression(writer.EXPL_PAREN, writer);
writer.print(")");
writer.openBrace();
for (int i=0; i < caseBlocks.length; i++)

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

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

Loading…
Cancel
Save