summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorRaif S. Naffah <raif@swiftdsl.com.au>2006-09-26 20:47:09 +0000
committerRaif S. Naffah <raif@swiftdsl.com.au>2006-09-26 20:47:09 +0000
commit7440a3c93a9b483ae90b0ba069643c60a0140600 (patch)
treee04000a2f4c463002f8bc65a09608b99539e3110 /tools
parent2e3d09fe936f35d0bbfcf705cd2d0b76e6ca5bcb (diff)
downloadclasspath-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.java25
-rw-r--r--tools/gnu/classpath/tools/javah/CniStubPrinter.java38
-rw-r--r--tools/gnu/classpath/tools/javah/JniIncludePrinter.java35
-rw-r--r--tools/gnu/classpath/tools/javah/JniStubPrinter.java34
-rw-r--r--tools/gnu/classpath/tools/javah/Main.java87
-rw-r--r--tools/gnu/classpath/tools/javah/Printer.java88
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;
+ }
}