src/share/classes/com/sun/tools/javah/Gen.java

Tue, 20 Jan 2009 18:23:13 -0800

author
jjg
date
Tue, 20 Jan 2009 18:23:13 -0800
changeset 198
b4b1f7732289
parent 184
905e151a185a
child 229
03bcd66bd8e7
permissions
-rw-r--r--

6795903: fix latent build warnings in langtools repository
Reviewed-by: darcy

     1 /*
     2  * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Sun in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
    23  * have any questions.
    24  */
    26 package com.sun.tools.javah;
    28 import java.io.UnsupportedEncodingException;
    29 import java.io.ByteArrayOutputStream;
    30 import java.io.IOException;
    31 import java.io.OutputStream;
    32 import java.io.PrintWriter;
    33 import com.sun.javadoc.*;
    34 import java.io.*;
    35 import java.util.Stack;
    36 import java.util.Vector;
    37 import java.util.Arrays;
    40 /**
    41  * An abstraction for generating support files required by native methods.
    42  * Subclasses are for specific native interfaces. At the time of its
    43  * original writing, this interface is rich enough to support JNI and the
    44  * old 1.0-style native method interface.
    45  *
    46  * @author  Sucheta Dambalkar(Revised)
    47  */
    50 public abstract class Gen {
    51     protected String lineSep = System.getProperty("line.separator");
    53     RootDoc root;
    54     /*
    55      * List of classes for which we must generate output.
    56      */
    57     protected ClassDoc[] classes;
    58     static private final boolean isWindows =
    59         System.getProperty("os.name").startsWith("Windows");
    61     public Gen(RootDoc root){
    62         this.root = root;
    63     }
    65     /**
    66      * Override this abstract method, generating content for the named
    67      * class into the outputstream.
    68      */
    69     protected abstract void write(OutputStream o, ClassDoc clazz)
    70         throws ClassNotFoundException;
    72     /**
    73      * Override this method to provide a list of #include statements
    74      * required by the native interface.
    75      */
    76     protected abstract String getIncludes();
    78     /*
    79      * Output location.
    80      */
    81     protected String outDir;
    82     protected String outFile;
    84     public void setOutDir(String outDir) {
    85         /* Check important, otherwise concatenation of two null strings
    86          * produces the "nullnull" String.
    87          */
    88         if (outDir != null) {
    89             this.outDir = outDir + System.getProperty("file.separator");
    90             File d = new File(outDir);
    91             if (!d.exists())
    92                 if (!d.mkdirs())
    93                     Util.error("cant.create.dir", d.toString());
    94         }
    95     }
    97     public void setOutFile(String outFile) {
    98         this.outFile = outFile;
    99     }
   102     public void setClasses(ClassDoc[] classes) {
   103         this.classes = classes;
   104     }
   106     /*
   107      * Smartness with generated files.
   108      */
   109     protected boolean force = false;
   111     public void setForce(boolean state) {
   112         force = state;
   113     }
   115     /**
   116      * We explicitly need to write ASCII files because that is what C
   117      * compilers understand.
   118      */
   119     protected PrintWriter wrapWriter(OutputStream o) {
   120         try {
   121             return new
   122             PrintWriter(new OutputStreamWriter(o, "ISO8859_1"), true);
   123         } catch (UnsupportedEncodingException use) {
   124             Util.bug("encoding.iso8859_1.not.found");
   125             return null; /* dead code */
   126         }
   127     }
   129     /**
   130      * After initializing state of an instance, use this method to start
   131      * processing.
   132      *
   133      * Buffer size chosen as an approximation from a single sampling of:
   134      *         expr `du -sk` / `ls *.h | wc -l`
   135      */
   136     public void run() throws IOException, ClassNotFoundException {
   137         int i = 0;
   138         if (outFile != null) {
   139             /* Everything goes to one big file... */
   140             ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
   141             writeFileTop(bout); /* only once */
   143             for (i = 0; i < classes.length; i++) {
   144                 write(bout, classes[i]);
   145             }
   147             writeIfChanged(bout.toByteArray(), outFile);
   148         } else {
   149             /* Each class goes to its own file... */
   150             for (i = 0; i < classes.length; i++) {
   151                 ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
   152                 writeFileTop(bout);
   153                 ClassDoc clazz = classes[i];
   154                 write(bout, clazz);
   155                 writeIfChanged(bout.toByteArray(), getFileName(clazz.qualifiedName()));
   156             }
   157         }
   158     }
   160     /*
   161      * Write the contents of byte[] b to a file named file.  Writing
   162      * is done if either the file doesn't exist or if the contents are
   163      * different.
   164      */
   165     private void writeIfChanged(byte[] b, String file) throws IOException {
   166         File f = new File(file);
   167         boolean mustWrite = false;
   168         String event = "[No need to update file ";
   170         if (force) {
   171             mustWrite = true;
   172             event = "[Forcefully writing file ";
   173         } else {
   174             if (!f.exists()) {
   175                 mustWrite = true;
   176                 event = "[Creating file ";
   177             } else {
   178                 int l = (int)f.length();
   179                 if (b.length != l) {
   180                     mustWrite = true;
   181                     event = "[Overwriting file ";
   182                 } else {
   183                     /* Lengths are equal, so read it. */
   184                     byte[] a = new byte[l];
   185                     FileInputStream in = new FileInputStream(f);
   186                     if (in.read(a) != l) {
   187                         in.close();
   188                         /* This can't happen, we already checked the length. */
   189                         Util.error("not.enough.bytes", Integer.toString(l),
   190                                    f.toString());
   191                     }
   192                     in.close();
   193                     while (--l >= 0) {
   194                         if (a[l] != b[l]) {
   195                             mustWrite = true;
   196                             event = "[Overwriting file ";
   197                         }
   198                     }
   199                 }
   200             }
   201         }
   202         if (Util.verbose)
   203             Util.log(event + file + "]");
   204         if (mustWrite) {
   205             OutputStream out = new FileOutputStream(file);
   206             out.write(b); /* No buffering, just one big write! */
   207             out.close();
   208         }
   209     }
   211     protected String defineForStatic(ClassDoc c, FieldDoc f){
   213         String cnamedoc = c.qualifiedName();
   214         String fnamedoc = f.name();
   216         String cname = Mangle.mangle(cnamedoc, Mangle.Type.CLASS);
   217         String fname = Mangle.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
   219         if (!f.isStatic())
   220             Util.bug("tried.to.define.non.static");
   222         if (f.isFinal()) {
   223             Object value = null;
   225             value = f.constantValue();
   227             if (value != null) { /* so it is a ConstantExpression */
   228                 String constString = null;
   229                 if ((value instanceof Integer)
   230                     || (value instanceof Byte)
   231                     || (value instanceof Character)
   232                     || (value instanceof Short)
   233                     || (value instanceof Boolean)) {
   234                     /* covers byte, boolean, char, short, int */
   235                     if(value instanceof Boolean)
   236                         constString = (value.toString() == "true") ? "1L" : "0L";
   237                     else
   238                         constString = value.toString() + "L";
   239                 } else if (value instanceof Long) {
   240                     // Visual C++ supports the i64 suffix, not LL.
   241                     if (isWindows)
   242                         constString = value.toString() + "i64";
   243                     else
   244                         constString = value.toString() + "LL";
   245                 } else if (value instanceof Float) {
   246                     /* bug for bug */
   247                     float fv = ((Float)value).floatValue();
   248                     if (Float.isInfinite(fv))
   249                         constString = ((fv < 0) ? "-" : "") + "Inff";
   250                     else
   251                         constString = value.toString() + "f";
   252                 } else if (value instanceof Double) {
   253                     /* bug for bug */
   254                     double d = ((Double)value).doubleValue();
   255                     if (Double.isInfinite(d))
   256                         constString = ((d < 0) ? "-" : "") + "InfD";
   257                     else
   258                         constString = value.toString();
   259                 }
   260                 if (constString != null) {
   261                     StringBuffer s = new StringBuffer("#undef ");
   262                     s.append(cname); s.append("_"); s.append(fname); s.append(lineSep);
   263                     s.append("#define "); s.append(cname); s.append("_");
   264                     s.append(fname); s.append(" "); s.append(constString);
   265                     return s.toString();
   266                 }
   268             }
   269         }
   270         return null;
   271     }
   273     /*
   274      * Deal with the C pre-processor.
   275      */
   276     protected String cppGuardBegin() {
   277         return "#ifdef __cplusplus" + lineSep + "extern \"C\" {" + lineSep + "#endif";
   278     }
   280     protected String cppGuardEnd() {
   281         return "#ifdef __cplusplus" + lineSep + "}" + lineSep + "#endif";
   282     }
   284     protected String guardBegin(String cname) {
   285         return "/* Header for class " + cname + " */" + lineSep + lineSep +
   286             "#ifndef _Included_" + cname + lineSep +
   287             "#define _Included_" + cname;
   288     }
   290     protected String guardEnd(String cname) {
   291         return "#endif";
   292     }
   294     /*
   295      * File name and file preamble related operations.
   296      */
   297     protected void writeFileTop(OutputStream o) {
   298         PrintWriter pw = wrapWriter(o);
   299         pw.println("/* DO NOT EDIT THIS FILE - it is machine generated */" + lineSep +
   300                    getIncludes());
   301     }
   303     protected String baseFileName(String clazz) {
   304         StringBuffer f =
   305             new StringBuffer(Mangle.mangle(clazz,
   306                                            Mangle.Type.CLASS));
   307         if (outDir != null) {
   308             f.insert(0, outDir);
   309         }
   310         return f.toString();
   311     }
   313     protected String getFileName(String clazz) {
   314         return baseFileName(clazz) + getFileSuffix();
   315     }
   317     protected String getFileSuffix() {
   318         return ".h";
   319     }
   321     /**
   322      * Including super classes' fields.
   323      */
   325     FieldDoc[] getAllFields(ClassDoc subclazz)
   326                 throws ClassNotFoundException {
   327         Vector<FieldDoc> fields = new Vector<FieldDoc>();
   328         ClassDoc cd = null;
   329         Stack<Object> s = new Stack<Object>();
   331         cd = subclazz;
   332         while (true) {
   333             s.push(cd);
   334             ClassDoc c = cd.superclass();
   335             if (c == null)
   336                 break;
   337             cd = c;
   338         }
   340         while (!s.empty()) {
   341             cd = (ClassDoc)s.pop();
   342             fields.addAll(Arrays.asList(cd.fields()));
   343         }
   345         return fields.toArray(new FieldDoc[fields.size()]);
   346     }
   347 }

mercurial