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();
   }
-
 }

Reply via email to