Tue, 20 Jan 2009 18:23:13 -0800
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 }