diff options
author | Raif S. Naffah <raif@swiftdsl.com.au> | 2006-09-26 20:47:09 +0000 |
---|---|---|
committer | Raif S. Naffah <raif@swiftdsl.com.au> | 2006-09-26 20:47:09 +0000 |
commit | 7440a3c93a9b483ae90b0ba069643c60a0140600 (patch) | |
tree | e04000a2f4c463002f8bc65a09608b99539e3110 /tools | |
parent | 2e3d09fe936f35d0bbfcf705cd2d0b76e6ca5bcb (diff) | |
download | classpath-7440a3c93a9b483ae90b0ba069643c60a0140600.tar.gz |
2006-09-27 Raif S. Naffah <raif@swiftdsl.com.au>
* tools/gnu/classpath/tools/javah/CniIncludePrinter.java (CniIncludePrinter):
Accept three additional arguments.
(writePreambleImpl): New method.
(getPrintStreamImpl): Likewise.
(printClass): Adapted to use new methods in Printer superclass.
* tools/gnu/classpath/tools/javah/CniStubPrinter.java: Likewise.
* tools/gnu/classpath/tools/javah/JniIncludePrinter.java: Likewise.
* tools/gnu/classpath/tools/javah/JniStubPrinter.java: Likewise.
* tools/gnu/classpath/tools/javah/Main.java (outFileName): New field.
(force): Likewise.
(getParser): Add support for -o option.
Check that only one of -d or -o is defined.
Add support for -jni option.
Add support for -force option.
(makeOutputFile): New method.
(writeHeaders): Removed File argument from signature.
(run): Take into account newly added fields.
Invoke concrete PrintStream implementations with augmented constructors.
* tools/gnu/classpath/tools/javah/Printer.java (outputFileObject): New field.
(isDirectory): Likewise.
(force): Likewise.
(wrotePreamble): Likewise.
(Printer): Changed ctor to accept three additional arguments.
(printClass): Changed signature to accept one ClassWrapper argument.
(writePreambleImpl): New abstract method.
(getPrintStreamImpl): Likewise.
(getPrintStream): New method.
(writePreamble): Likewise.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/gnu/classpath/tools/javah/CniIncludePrinter.java | 25 | ||||
-rw-r--r-- | tools/gnu/classpath/tools/javah/CniStubPrinter.java | 38 | ||||
-rw-r--r-- | tools/gnu/classpath/tools/javah/JniIncludePrinter.java | 35 | ||||
-rw-r--r-- | tools/gnu/classpath/tools/javah/JniStubPrinter.java | 34 | ||||
-rw-r--r-- | tools/gnu/classpath/tools/javah/Main.java | 87 | ||||
-rw-r--r-- | tools/gnu/classpath/tools/javah/Printer.java | 88 |
6 files changed, 247 insertions, 60 deletions
diff --git a/tools/gnu/classpath/tools/javah/CniIncludePrinter.java b/tools/gnu/classpath/tools/javah/CniIncludePrinter.java index 6561169bb..fb007b131 100644 --- a/tools/gnu/classpath/tools/javah/CniIncludePrinter.java +++ b/tools/gnu/classpath/tools/javah/CniIncludePrinter.java @@ -46,24 +46,35 @@ import java.io.PrintStream; public class CniIncludePrinter extends Printer { + protected CniIncludePrinter(Main classpath, File outFile, boolean isDir, + boolean force) + { + super(classpath, outFile, isDir, force); + } - protected CniIncludePrinter(Main classpath) + protected void writePreambleImpl(PrintStream ps) { - super(classpath); + // does nothing } - public void printClass(File outputDir, ClassWrapper klass) throws IOException + protected PrintStream getPrintStreamImpl(FileOutputStream fos, + ClassWrapper klass) + { + return new PrintStream(fos); + } + + public void printClass(ClassWrapper klass) throws IOException { // Never write Object or Class. This is a hack, maybe // the user would like to see what they look like... if (klass.name.equals("java/lang/Object") || klass.name.equals("java/lang/Class")) return; - File klassFile = new File(outputDir, klass.name + ".h"); - klassFile.getParentFile().mkdirs(); - PrintStream ps = new PrintStream(new FileOutputStream(klassFile)); + PrintStream ps = getPrintStream(klass.name + ".h", klass); + if (ps == null) + return; + ps.println(); klass.printFully(ps); ps.close(); } - } diff --git a/tools/gnu/classpath/tools/javah/CniStubPrinter.java b/tools/gnu/classpath/tools/javah/CniStubPrinter.java index 9732e2941..d91f367c4 100644 --- a/tools/gnu/classpath/tools/javah/CniStubPrinter.java +++ b/tools/gnu/classpath/tools/javah/CniStubPrinter.java @@ -41,6 +41,7 @@ package gnu.classpath.tools.javah; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Modifier; import java.util.Iterator; @@ -50,10 +51,10 @@ import org.objectweb.asm.tree.MethodNode; public class CniStubPrinter extends Printer { - - protected CniStubPrinter(Main classpath) + protected CniStubPrinter(Main classpath, File outFile, boolean isDir, + boolean force) { - super(classpath); + super(classpath, outFile, isDir, force); } private void printDecl(CniPrintStream out, String className, MethodNode method) @@ -72,24 +73,34 @@ public class CniStubPrinter out.print(")"); } - public void printClass(File outputDir, ClassWrapper klass) throws IOException + protected void writePreambleImpl(PrintStream out) { - if (! klass.hasNativeMethod()) - return; - File klassFile = new File(outputDir, klass.name + ".cc"); - klassFile.getParentFile().mkdirs(); - String className = klass.name.replaceAll("/", "::"); - - CniPrintStream out = new CniPrintStream(new FileOutputStream(klassFile)); out.println("// This file is intended to give you a head start on implementing native"); out.println("// methods using CNI."); out.println("// Be aware: running 'gcjh -stubs' once more for this class may"); out.println("// overwrite any edits you have made to this file."); out.println(); - - out.println("#include <" + klass.name + ".h>"); out.println("#include <gcj/cni.h>"); out.println("#include <java/lang/UnsupportedOperationException.h>"); + } + + protected PrintStream getPrintStreamImpl(FileOutputStream fos, + ClassWrapper klass) + { + return new CniPrintStream(fos); + } + + public void printClass(ClassWrapper klass) throws IOException + { + if (! klass.hasNativeMethod()) + return; + String className = klass.name.replaceAll("/", "::"); + CniPrintStream out = (CniPrintStream) getPrintStream(klass.name + ".cc", + klass); + if (out == null) + return; + out.println(); + out.println("#include <" + klass.name + ".h>"); out.println(); Iterator i = klass.methods.iterator(); @@ -115,5 +126,4 @@ public class CniStubPrinter } out.close(); } - } diff --git a/tools/gnu/classpath/tools/javah/JniIncludePrinter.java b/tools/gnu/classpath/tools/javah/JniIncludePrinter.java index c01634007..3d88650c1 100644 --- a/tools/gnu/classpath/tools/javah/JniIncludePrinter.java +++ b/tools/gnu/classpath/tools/javah/JniIncludePrinter.java @@ -41,6 +41,7 @@ package gnu.classpath.tools.javah; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Modifier; import java.util.Iterator; @@ -51,10 +52,10 @@ import org.objectweb.asm.tree.MethodNode; public class JniIncludePrinter extends Printer { - - protected JniIncludePrinter(Main classpath) + protected JniIncludePrinter(Main classpath, File outFile, boolean isDir, + boolean force) { - super(classpath); + super(classpath, outFile, isDir, force); } private void writeFields(ClassWrapper klass, JniPrintStream out) @@ -93,17 +94,27 @@ public class JniIncludePrinter out.println(); } - public void printClass(File outputDir, ClassWrapper klass) throws IOException + protected void writePreambleImpl(PrintStream out) + { + out.println("/* DO NOT EDIT THIS FILE - it is machine generated */"); + out.println(); + out.println("#include <jni.h>"); + } + + protected PrintStream getPrintStreamImpl(FileOutputStream fos, + ClassWrapper klass) + { + return new JniPrintStream(classpath, fos, klass); + } + + public void printClass(ClassWrapper klass) throws IOException { if (! klass.hasNativeMethod()) return; String xname = JniHelper.mangle(klass.name); - File outFile = new File(outputDir, xname + ".h"); - - JniPrintStream out = new JniPrintStream(classpath, - new FileOutputStream(outFile), - klass); - out.println("/* DO NOT EDIT THIS FILE - it is machine generated */"); + JniPrintStream out = (JniPrintStream) getPrintStream(xname + ".h", klass); + if (out == null) + return; out.println(); out.print("#ifndef __"); out.print(xname); @@ -112,8 +123,6 @@ public class JniIncludePrinter out.print(xname); out.println("__"); out.println(); - out.println("#include <jni.h>"); - out.println(); out.println("#ifdef __cplusplus"); out.println("extern \"C\""); out.println("{"); @@ -144,8 +153,6 @@ public class JniIncludePrinter out.print("#endif /* __"); out.print(xname); out.println("__ */"); - out.close(); } - } diff --git a/tools/gnu/classpath/tools/javah/JniStubPrinter.java b/tools/gnu/classpath/tools/javah/JniStubPrinter.java index d590a5cd1..0bc11873f 100644 --- a/tools/gnu/classpath/tools/javah/JniStubPrinter.java +++ b/tools/gnu/classpath/tools/javah/JniStubPrinter.java @@ -41,6 +41,7 @@ package gnu.classpath.tools.javah; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Modifier; import java.util.Iterator; @@ -50,26 +51,34 @@ import org.objectweb.asm.tree.MethodNode; public class JniStubPrinter extends Printer { + protected JniStubPrinter(Main classpath, File outFile, boolean isDir, + boolean force) + { + super(classpath, outFile, isDir, force); + } + + protected void writePreambleImpl(PrintStream out) + { + out.println("/* This file is intended to give you a head start on implementing native"); + out.println(" methods using JNI."); + out.println(" Be aware: running gcjh or compatible tool with '-stubs' option once more"); + out.println(" for the same input may overwrite any edits you have made to this file. */"); + } - protected JniStubPrinter(Main classpath) + protected PrintStream getPrintStreamImpl(FileOutputStream fos, + ClassWrapper klass) { - super(classpath); + return new JniPrintStream(classpath, fos, klass); } - public void printClass(File outputDir, ClassWrapper klass) throws IOException + public void printClass(ClassWrapper klass) throws IOException { if (! klass.hasNativeMethod()) return; String xname = JniHelper.mangle(klass.name); - File outFile = new File(outputDir, xname + ".c"); - - JniPrintStream out = new JniPrintStream(classpath, - new FileOutputStream(outFile), - klass); - out.println("/* This file is intended to give you a head start on implementing native"); - out.println(" methods using CNI."); - out.println(" Be aware: running 'gcjh -stubs' once more for this class may"); - out.println(" overwrite any edits you have made to this file. */"); + JniPrintStream out = (JniPrintStream) getPrintStream(xname + ".c", klass); + if (out == null) + return; out.println(); out.print("#include <"); out.print(xname); @@ -94,5 +103,4 @@ public class JniStubPrinter } out.close(); } - } diff --git a/tools/gnu/classpath/tools/javah/Main.java b/tools/gnu/classpath/tools/javah/Main.java index 21e872a83..14c381bbb 100644 --- a/tools/gnu/classpath/tools/javah/Main.java +++ b/tools/gnu/classpath/tools/javah/Main.java @@ -70,6 +70,9 @@ public class Main // The output directory. String outputDir; + // The output file name used if/when -o option is used. + String outFileName; + // The loader that we use to load class files. URLClassLoader loader; @@ -85,6 +88,9 @@ public class Main // True if we're emitting CNI code. boolean cni; + // True if output files should always be written. + boolean force; + // Map class names to class wrappers. HashMap classMap = new HashMap(); @@ -184,9 +190,24 @@ public class Main { if (outputDir != null) throw new OptionException("-d already seen"); + if (outFileName != null) + throw new OptionException("only one of -d or -o may be used"); outputDir = dir; } }); + result.add(new Option('o', + "Set output file (only one of -d or -o may be used)", + "FILE") + { + public void parsed(String fileName) throws OptionException + { + if (outFileName != null) + throw new OptionException("-o already seen"); + if (outputDir != null) + throw new OptionException("only one of -d or -o may be used"); + outFileName = fileName; + } + }); result.add(new Option("cmdfile", "Read command file", "FILE") { public void parsed(String file) throws OptionException @@ -212,6 +233,15 @@ public class Main stubs = true; } }); + result.add(new Option("jni", "Emit JNI stubs or header (default)") + { + public void parsed(String arg0) throws OptionException + { + if (cni) + throw new OptionException("only one of -jni or -cni may be used"); + cni = false; + } + }); result.add(new Option("cni", "Emit CNI stubs or header (default JNI)") { public void parsed(String arg0) throws OptionException @@ -226,6 +256,13 @@ public class Main verbose = true; } }); + result.add(new Option("force", "Output files should always be written") + { + public void parsed(String arg0) throws OptionException + { + force = true; + } + }); return result; } @@ -242,8 +279,36 @@ public class Main return outputFile; } - private void writeHeaders(ArrayList klasses, Printer printer, - File outputDirFile) throws IOException + /** + * @return The {@link File} object where the generated code will be written. + * Returns <code>null</code> if the option <code>-force</code> was + * specified on the command line and the designated file already + * exists. + * @throws IOException if <code>outFileName</code> is not a writable file. + */ + private File makeOutputFile() throws IOException + { + File result = new File(outFileName); + if (result.exists()) + { + if (! result.isFile()) + throw new IOException("'" + outFileName + "' is not a file"); + if (! force) + { + if (verbose) + System.err.println("["+ outFileName + + " already exists. Use -force to overwrite]"); + return null; + } + if (! result.delete()) + throw new IOException("Was unable to delete existing file: " + + outFileName); + } + return result; + } + + private void writeHeaders(ArrayList klasses, Printer printer) + throws IOException { Iterator i = klasses.iterator(); while (i.hasNext()) @@ -251,7 +316,7 @@ public class Main ClassWrapper klass = (ClassWrapper) i.next(); if (verbose) System.err.println("[writing " + klass + "]"); - printer.printClass(outputDirFile, klass); + printer.printClass(klass); } } @@ -261,21 +326,25 @@ public class Main String[] classNames = p.parse(args); loader = classpath.getLoader(); - File outputFile = makeOutputDirectory(); + boolean isDirectory = outFileName == null; + File outputFile = isDirectory ? makeOutputDirectory() : makeOutputFile(); + if (outputFile == null) + return; + Printer printer; if (! cni) { if (stubs) - printer = new JniStubPrinter(this); + printer = new JniStubPrinter(this, outputFile, isDirectory, force); else - printer = new JniIncludePrinter(this); + printer = new JniIncludePrinter(this, outputFile, isDirectory, force); } else { if (stubs) - printer = new CniStubPrinter(this); + printer = new CniStubPrinter(this, outputFile, isDirectory, force); else - printer = new CniIncludePrinter(this); + printer = new CniIncludePrinter(this, outputFile, isDirectory, force); } // First we load all of the files. That way if @@ -324,7 +393,7 @@ public class Main results.add(klass); } - writeHeaders(results, printer, outputFile); + writeHeaders(results, printer); } public ArrayList getClassTextList(String name) diff --git a/tools/gnu/classpath/tools/javah/Printer.java b/tools/gnu/classpath/tools/javah/Printer.java index 0c25934e2..f84f53c52 100644 --- a/tools/gnu/classpath/tools/javah/Printer.java +++ b/tools/gnu/classpath/tools/javah/Printer.java @@ -39,17 +39,99 @@ package gnu.classpath.tools.javah; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.PrintStream; public abstract class Printer { protected Main classpath; - protected Printer(Main classpath) + /** + * The {@link File} object that denotes either a directory (when the + * <code>-d</code> option was used), or a file (when the <code>-o</code> + * option was used) on the command line. + */ + protected File outputFileObject; + + /** + * Set to <code>true</code> if the field <code>outputFileObject</code> denotes + * a directory; i.e. for each input class file, one JNI header file will be + * generated in that directory. + * <p> + * Set to <code>false</code> if the field <code>outputFileObject</code> + * denotes a file; i.e. all generated headers will be written to that file. + */ + protected boolean isDirectory; + + /** + * Set to <code>true</code> if the output file(s) should always be written. + * <p> + * When set to <code>false</code>, the contents of the header/stub are only + * written to the file if it does not already exist. + */ + protected boolean force; + + /** + * Set to <code>true</code> if all output is directed to one file, and the + * common preamble text has already been generated. + */ + protected boolean wrotePreamble; + + protected Printer(Main classpath, File outFile, boolean isDir, boolean force) { this.classpath = classpath; + if (outFile == null) + throw new IllegalArgumentException("File argument MUST NOT be null"); + outputFileObject = outFile; + isDirectory = isDir; + if (isDirectory) + outputFileObject.mkdirs(); + else + { + File parent = outputFileObject.getParentFile(); + if (parent != null) + parent.mkdirs(); + } + this.force = force; + } + + public abstract void printClass(ClassWrapper klass) throws IOException; + + protected abstract void writePreambleImpl(PrintStream ps); + + protected abstract PrintStream getPrintStreamImpl(FileOutputStream fos, + ClassWrapper klass); + + protected PrintStream getPrintStream(String fullName, ClassWrapper klass) + throws FileNotFoundException + { + PrintStream result; + FileOutputStream fos; + if (isDirectory) + { + File outFile = new File(outputFileObject, fullName); + if (outFile.exists() && ! force) + return null; + fos = new FileOutputStream(outFile); + result = getPrintStreamImpl(fos, klass); + writePreamble(result); + } + else + { + // the first time we open this file, wrotePreamble is false + fos = new FileOutputStream(outputFileObject, wrotePreamble); + result = getPrintStreamImpl(fos, klass); + if (! wrotePreamble) + writePreamble(result); + } + return result; } - public abstract void printClass(File outputDir, ClassWrapper klass) - throws IOException; + protected void writePreamble(PrintStream out) + { + writePreambleImpl(out); + wrotePreamble = true; + } } |