diff --git a/jode/src/net/sf/jode/decompiler/ClassAnalyzer.java b/jode/src/net/sf/jode/decompiler/ClassAnalyzer.java
index e25d57c..462d2da 100644
--- a/jode/src/net/sf/jode/decompiler/ClassAnalyzer.java
+++ b/jode/src/net/sf/jode/decompiler/ClassAnalyzer.java
@@ -670,6 +670,7 @@ public class ClassAnalyzer
dumpSource(writer, pl, 0.8, 0.2);
if (pl != null)
pl.updateProgress(1.0, name);
+ writer.close();
}
public boolean isScopeOf(Object obj, int scopeType) {
diff --git a/jode/src/net/sf/jode/decompiler/Main.java b/jode/src/net/sf/jode/decompiler/Main.java
index bd5c4e9..385476f 100644
--- a/jode/src/net/sf/jode/decompiler/Main.java
+++ b/jode/src/net/sf/jode/decompiler/Main.java
@@ -53,6 +53,7 @@ public class Main extends Options {
new LongOpt("debug", LongOpt.OPTIONAL_ARGUMENT, null, 'D'),
new LongOpt("import", LongOpt.REQUIRED_ARGUMENT, null, 'i'),
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,
OPTION_START+0),
new LongOpt("inner", LongOpt.OPTIONAL_ARGUMENT, null,
@@ -94,8 +95,10 @@ public class Main extends Options {
"The directories should be separated by ','.");
err.println(" -d, --dest
"+
"write decompiled files to disk into directory destdir.");
- err.println(" -s, --style {sun|gnu} "+
+ err.println(" -s, --style {sun|gnu|pascal|python} "+
"specify indentation style");
+ err.println(" -l, --chars-per-line "+
+ "specify line length");
err.println(" -i, --import ,");
err.println(" "+
"import classes used more than clslimit times");
@@ -250,12 +253,13 @@ public class Main extends Options {
int importClassLimit = ImportHandler.DEFAULT_CLASS_LIMIT;;
int outputStyle = TabbedPrintWriter.BRACE_AT_EOL;
int indentSize = 4;
+ int outputLineLength = 79;
boolean keepGoing = false;
GlobalOptions.err.println(GlobalOptions.copyright);
boolean errorInParams = false;
- Getopt g = new Getopt("net.sf.jode.decompiler.Main", params, "hVvkc:d:D:i:s:",
+ Getopt g = new Getopt("net.sf.jode.decompiler.Main", params, "hVvkc:d:D:i:s:l:",
longOptions, true);
for (int opt = g.getopt(); opt != -1; opt = g.getopt()) {
switch(opt) {
@@ -309,9 +313,12 @@ public class Main extends Options {
} else if (arg.equals("sun")) {
outputStyle = TabbedPrintWriter.BRACE_AT_EOL;
indentSize = 4;
- } else if (arg.equals("pascal")) {
- outputStyle = 0;
- indentSize = 4;
+ } else if (arg.equals("pascal")) {
+ outputStyle = 0;
+ indentSize = 4;
+ } else if (arg.equals("python") || arg.equals("codd")) {
+ outputStyle = TabbedPrintWriter.BRACE_AT_EOL|TabbedPrintWriter.CODD_FORMATTING;
+ indentSize = 4;
} else {
GlobalOptions.err.println
("net.sf.jode.decompiler.Main: Unknown style `"+arg+"'.");
@@ -319,6 +326,18 @@ public class Main extends Options {
}
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': {
String arg = g.getOptarg();
int comma = arg.indexOf(',');
@@ -365,7 +384,7 @@ public class Main extends Options {
TabbedPrintWriter writer = null;
if (destDir == null)
writer = new TabbedPrintWriter(System.out, imports, true,
- outputStyle, indentSize, 0, 79);
+ outputStyle, indentSize, 0, outputLineLength);
else if (destDir.toLowerCase().endsWith(".zip")
|| destDir.toLowerCase().endsWith(".jar")) {
try {
@@ -377,7 +396,7 @@ public class Main extends Options {
}
writer = new TabbedPrintWriter(new BufferedOutputStream(destZip),
imports, false,
- outputStyle, indentSize, 0, 79);
+ outputStyle, indentSize, 0, outputLineLength);
}
for (int i= g.getOptind(); i< params.length; i++) {
try {
diff --git a/jode/src/net/sf/jode/decompiler/TabbedPrintWriter.java b/jode/src/net/sf/jode/decompiler/TabbedPrintWriter.java
index 2be7843..89cd974 100644
--- a/jode/src/net/sf/jode/decompiler/TabbedPrintWriter.java
+++ b/jode/src/net/sf/jode/decompiler/TabbedPrintWriter.java
@@ -42,6 +42,7 @@ public class TabbedPrintWriter {
public static final int BRACE_AT_EOL = 0x10;
public static final int INDENT_BRACES = 0x20;
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
@@ -72,19 +73,18 @@ public class TabbedPrintWriter {
indent -= tabs * tabWidth;
if (tabs <= FASTINDENT) {
/* The fast way. */
- return tabSpaceString.substring(FASTINDENT - tabs,
+ return tabSpaceString.substring(FASTINDENT - tabs,
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 {
@@ -460,7 +460,10 @@ public class TabbedPrintWriter {
public TabbedPrintWriter (OutputStream os, ImportHandler imports,
boolean autoFlush, int style,
int indentSize, int tabWidth, int lineWidth) {
- pw = new PrintWriter(os, autoFlush);
+ if ((style & CODD_FORMATTING) != 0)
+ pw = new PrintWriter(new NlRemover(new OutputStreamWriter(os), tabWidth), autoFlush);
+ else
+ pw = new PrintWriter(os, autoFlush);
this.imports = imports;
this.style = style;
this.indentsize = indentSize;
@@ -469,10 +472,11 @@ public class TabbedPrintWriter {
init();
}
- public TabbedPrintWriter (Writer os, ImportHandler imports,
- boolean autoFlush, int style,
- int indentSize, int tabWidth, int lineWidth) {
- pw = new PrintWriter(os, autoFlush);
+ public TabbedPrintWriter (Writer os, ImportHandler imports, boolean autoFlush, int style, int indentSize, int tabWidth, int lineWidth) {
+ if ((style & CODD_FORMATTING) != 0)
+ pw = new PrintWriter(new NlRemover(os, tabWidth), autoFlush);
+ else {
+ pw = new PrintWriter(os, autoFlush); }
this.imports = imports;
this.style = style;
this.indentsize = indentSize;
@@ -492,19 +496,19 @@ public class TabbedPrintWriter {
}
public TabbedPrintWriter (OutputStream os, ImportHandler imports) {
- this(os, imports, true, BRACE_AT_EOL, 4, 8, 79);
+ this(os, imports, true);
}
public TabbedPrintWriter (Writer os, ImportHandler imports) {
- this(os, imports, true, BRACE_AT_EOL, 4, 8, 79);
+ this(os, imports, true);
}
public TabbedPrintWriter (OutputStream os) {
- this(os, null, true, BRACE_AT_EOL, 4, 8, 79);
+ this(os, null);
}
public TabbedPrintWriter (Writer os) {
- this(os, null, true, BRACE_AT_EOL, 4, 8, 79);
+ this(os, null);
}
private void init() {
@@ -516,7 +520,7 @@ public class TabbedPrintWriter {
private void initTabString() {
char tabChar = '\t';
- if (tabWidth == 0) {
+ if (tabWidth <= 1) {
/* If tabWidth is 0 use spaces instead of tabs. */
tabWidth = 1;
tabChar = ' ';
@@ -690,8 +694,7 @@ public class TabbedPrintWriter {
if (scope != null)
return "NAME CONFLICT " + className;
- else
- return "UNREACHABLE " + className;
+ return "UNREACHABLE " + className;
}
if (imports != null) {
String importedName = imports.getClassString(clazz);
@@ -791,7 +794,7 @@ public class TabbedPrintWriter {
}
public void closeBraceContinue() {
- if ((style & BRACE_AT_EOL) != 0)
+ if ((style & (BRACE_AT_EOL|CODD_FORMATTING)) == BRACE_AT_EOL)
print("} ");
else
println("}");
@@ -823,3 +826,79 @@ public class TabbedPrintWriter {
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)
+ 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++]);
+ }
+}