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

Thu, 02 Oct 2008 19:58:40 -0700

author
xdono
date
Thu, 02 Oct 2008 19:58:40 -0700
changeset 117
24a47c3062fe
parent 74
5a9172b251dd
child 184
905e151a185a
permissions
-rw-r--r--

6754988: Update copyright year
Summary: Update for files that have been modified starting July 2008
Reviewed-by: ohair, tbell

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

mercurial