hello Tom,
On Wednesday 27 September 2006 03:56, Tom Tromey wrote:
> >>>>> "Raif" == Raif S Naffah <[EMAIL PROTECTED]> writes:
>
> Raif> the attached proposed patch adds support for the above options
> Raif> in an attempt to make gjavah compatible (options-wise) with the
> Raif> RI.
>
> Looks pretty good, thanks. Just 1 nit...
> Please put a blank line between field declarations that have javadoc
> comments. There's a few instances of this. Thanks!
done and committed. here is the ChangeLog entry and attached is the patch:
2006-09-27 Raif S. Naffah <[EMAIL PROTECTED]>
* 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.
thanks + cheers;
rsn
Index: Printer.java
===================================================================
RCS file: /cvsroot/classpath/classpath/tools/gnu/classpath/tools/javah/Printer.java,v
retrieving revision 1.1
diff -u -r1.1 Printer.java
--- Printer.java 28 Jul 2006 15:22:29 -0000 1.1
+++ Printer.java 26 Sep 2006 20:25:23 -0000
@@ -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 [EMAIL PROTECTED] 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;
+ }
}
Index: Main.java
===================================================================
RCS file: /cvsroot/classpath/classpath/tools/gnu/classpath/tools/javah/Main.java,v
retrieving revision 1.3
diff -u -r1.3 Main.java
--- Main.java 22 Sep 2006 01:01:26 -0000 1.3
+++ Main.java 26 Sep 2006 20:33:51 -0000
@@ -70,6 +70,9 @@
// 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 @@
// 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 @@
{
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 @@
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 @@
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 @@
return outputFile;
}
- private void writeHeaders(ArrayList klasses, Printer printer,
- File outputDirFile) throws IOException
+ /**
+ * @return The [EMAIL PROTECTED] 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 @@
ClassWrapper klass = (ClassWrapper) i.next();
if (verbose)
System.err.println("[writing " + klass + "]");
- printer.printClass(outputDirFile, klass);
+ printer.printClass(klass);
}
}
@@ -261,21 +326,25 @@
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 @@
results.add(klass);
}
- writeHeaders(results, printer, outputFile);
+ writeHeaders(results, printer);
}
public ArrayList getClassTextList(String name)
Index: JniStubPrinter.java
===================================================================
RCS file: /cvsroot/classpath/classpath/tools/gnu/classpath/tools/javah/JniStubPrinter.java,v
retrieving revision 1.1
diff -u -r1.1 JniStubPrinter.java
--- JniStubPrinter.java 28 Jul 2006 15:22:29 -0000 1.1
+++ JniStubPrinter.java 26 Sep 2006 20:38:18 -0000
@@ -41,6 +41,7 @@
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 @@
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 @@
}
out.close();
}
-
}
Index: JniIncludePrinter.java
===================================================================
RCS file: /cvsroot/classpath/classpath/tools/gnu/classpath/tools/javah/JniIncludePrinter.java,v
retrieving revision 1.2
diff -u -r1.2 JniIncludePrinter.java
--- JniIncludePrinter.java 9 Aug 2006 17:18:31 -0000 1.2
+++ JniIncludePrinter.java 26 Sep 2006 20:39:42 -0000
@@ -41,6 +41,7 @@
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 @@
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 @@
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 @@
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 @@
out.print("#endif /* __");
out.print(xname);
out.println("__ */");
-
out.close();
}
-
}
Index: CniStubPrinter.java
===================================================================
RCS file: /cvsroot/classpath/classpath/tools/gnu/classpath/tools/javah/CniStubPrinter.java,v
retrieving revision 1.1
diff -u -r1.1 CniStubPrinter.java
--- CniStubPrinter.java 28 Jul 2006 15:22:29 -0000 1.1
+++ CniStubPrinter.java 26 Sep 2006 20:40:43 -0000
@@ -41,6 +41,7 @@
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 @@
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 @@
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 @@
}
out.close();
}
-
}
Index: CniIncludePrinter.java
===================================================================
RCS file: /cvsroot/classpath/classpath/tools/gnu/classpath/tools/javah/CniIncludePrinter.java,v
retrieving revision 1.1
diff -u -r1.1 CniIncludePrinter.java
--- CniIncludePrinter.java 28 Jul 2006 15:22:29 -0000 1.1
+++ CniIncludePrinter.java 26 Sep 2006 20:43:55 -0000
@@ -46,24 +46,35 @@
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();
}
-
}