Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/javah/Gen.java
38899 views
1
/*
2
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package com.sun.tools.javah;
27
28
import java.io.UnsupportedEncodingException;
29
import java.io.ByteArrayOutputStream;
30
import java.io.FileNotFoundException;
31
import java.io.IOException;
32
import java.io.InputStream;
33
import java.io.OutputStream;
34
import java.io.OutputStreamWriter;
35
import java.io.PrintWriter;
36
import java.util.ArrayList;
37
import java.util.Arrays;
38
import java.util.List;
39
import java.util.Set;
40
import java.util.Stack;
41
42
import javax.annotation.processing.ProcessingEnvironment;
43
44
import javax.lang.model.element.ExecutableElement;
45
import javax.lang.model.element.Modifier;
46
import javax.lang.model.element.TypeElement;
47
import javax.lang.model.element.VariableElement;
48
import javax.lang.model.util.ElementFilter;
49
import javax.lang.model.util.Elements;
50
import javax.lang.model.util.Types;
51
52
import javax.tools.FileObject;
53
import javax.tools.JavaFileManager;
54
import javax.tools.JavaFileObject;
55
import javax.tools.StandardLocation;
56
57
/**
58
* An abstraction for generating support files required by native methods.
59
* Subclasses are for specific native interfaces. At the time of its
60
* original writing, this interface is rich enough to support JNI and the
61
* old 1.0-style native method interface.
62
*
63
* <p><b>This is NOT part of any supported API.
64
* If you write code that depends on this, you do so at your own
65
* risk. This code and its internal interfaces are subject to change
66
* or deletion without notice.</b></p>
67
*
68
* @author Sucheta Dambalkar(Revised)
69
*/
70
public abstract class Gen {
71
protected String lineSep = System.getProperty("line.separator");
72
73
protected ProcessingEnvironment processingEnvironment;
74
protected Types types;
75
protected Elements elems;
76
protected Mangle mangler;
77
protected Util util;
78
79
protected Gen(Util util) {
80
this.util = util;
81
}
82
83
/*
84
* List of classes for which we must generate output.
85
*/
86
protected Set<TypeElement> classes;
87
static private final boolean isWindows =
88
System.getProperty("os.name").startsWith("Windows");
89
90
91
/**
92
* Override this abstract method, generating content for the named
93
* class into the outputstream.
94
*/
95
protected abstract void write(OutputStream o, TypeElement clazz) throws Util.Exit;
96
97
/**
98
* Override this method to provide a list of #include statements
99
* required by the native interface.
100
*/
101
protected abstract String getIncludes();
102
103
/*
104
* Output location.
105
*/
106
protected JavaFileManager fileManager;
107
protected JavaFileObject outFile;
108
109
public void setFileManager(JavaFileManager fm) {
110
fileManager = fm;
111
}
112
113
public void setOutFile(JavaFileObject outFile) {
114
this.outFile = outFile;
115
}
116
117
118
public void setClasses(Set<TypeElement> classes) {
119
this.classes = classes;
120
}
121
122
void setProcessingEnvironment(ProcessingEnvironment pEnv) {
123
processingEnvironment = pEnv;
124
elems = pEnv.getElementUtils();
125
types = pEnv.getTypeUtils();
126
mangler = new Mangle(elems, types);
127
}
128
129
/*
130
* Smartness with generated files.
131
*/
132
protected boolean force = false;
133
134
public void setForce(boolean state) {
135
force = state;
136
}
137
138
/**
139
* We explicitly need to write ASCII files because that is what C
140
* compilers understand.
141
*/
142
protected PrintWriter wrapWriter(OutputStream o) throws Util.Exit {
143
try {
144
return new PrintWriter(new OutputStreamWriter(o, "ISO8859_1"), true);
145
} catch (UnsupportedEncodingException use) {
146
util.bug("encoding.iso8859_1.not.found");
147
return null; /* dead code */
148
}
149
}
150
151
/**
152
* After initializing state of an instance, use this method to start
153
* processing.
154
*
155
* Buffer size chosen as an approximation from a single sampling of:
156
* expr `du -sk` / `ls *.h | wc -l`
157
*/
158
public void run() throws IOException, ClassNotFoundException, Util.Exit {
159
int i = 0;
160
if (outFile != null) {
161
/* Everything goes to one big file... */
162
ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
163
writeFileTop(bout); /* only once */
164
165
for (TypeElement t: classes) {
166
write(bout, t);
167
}
168
169
writeIfChanged(bout.toByteArray(), outFile);
170
} else {
171
/* Each class goes to its own file... */
172
for (TypeElement t: classes) {
173
ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
174
writeFileTop(bout);
175
write(bout, t);
176
writeIfChanged(bout.toByteArray(), getFileObject(t.getQualifiedName()));
177
}
178
}
179
}
180
181
/*
182
* Write the contents of byte[] b to a file named file. Writing
183
* is done if either the file doesn't exist or if the contents are
184
* different.
185
*/
186
private void writeIfChanged(byte[] b, FileObject file) throws IOException {
187
boolean mustWrite = false;
188
String event = "[No need to update file ";
189
190
if (force) {
191
mustWrite = true;
192
event = "[Forcefully writing file ";
193
} else {
194
InputStream in;
195
byte[] a;
196
try {
197
// regrettably, there's no API to get the length in bytes
198
// for a FileObject, so we can't short-circuit reading the
199
// file here
200
in = file.openInputStream();
201
a = readBytes(in);
202
if (!Arrays.equals(a, b)) {
203
mustWrite = true;
204
event = "[Overwriting file ";
205
206
}
207
} catch (FileNotFoundException e) {
208
mustWrite = true;
209
event = "[Creating file ";
210
}
211
}
212
213
if (util.verbose)
214
util.log(event + file + "]");
215
216
if (mustWrite) {
217
OutputStream out = file.openOutputStream();
218
out.write(b); /* No buffering, just one big write! */
219
out.close();
220
}
221
}
222
223
protected byte[] readBytes(InputStream in) throws IOException {
224
try {
225
byte[] array = new byte[in.available() + 1];
226
int offset = 0;
227
int n;
228
while ((n = in.read(array, offset, array.length - offset)) != -1) {
229
offset += n;
230
if (offset == array.length)
231
array = Arrays.copyOf(array, array.length * 2);
232
}
233
234
return Arrays.copyOf(array, offset);
235
} finally {
236
in.close();
237
}
238
}
239
240
protected String defineForStatic(TypeElement c, VariableElement f)
241
throws Util.Exit {
242
CharSequence cnamedoc = c.getQualifiedName();
243
CharSequence fnamedoc = f.getSimpleName();
244
245
String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS);
246
String fname = mangler.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
247
248
if (!f.getModifiers().contains(Modifier.STATIC))
249
util.bug("tried.to.define.non.static");
250
251
if (f.getModifiers().contains(Modifier.FINAL)) {
252
Object value = null;
253
254
value = f.getConstantValue();
255
256
if (value != null) { /* so it is a ConstantExpression */
257
String constString = null;
258
if ((value instanceof Integer)
259
|| (value instanceof Byte)
260
|| (value instanceof Short)) {
261
/* covers byte, short, int */
262
constString = value.toString() + "L";
263
} else if (value instanceof Boolean) {
264
constString = ((Boolean) value) ? "1L" : "0L";
265
} else if (value instanceof Character) {
266
Character ch = (Character) value;
267
constString = String.valueOf(((int) ch) & 0xffff) + "L";
268
} else if (value instanceof Long) {
269
// Visual C++ supports the i64 suffix, not LL.
270
if (isWindows)
271
constString = value.toString() + "i64";
272
else
273
constString = value.toString() + "LL";
274
} else if (value instanceof Float) {
275
/* bug for bug */
276
float fv = ((Float)value).floatValue();
277
if (Float.isInfinite(fv))
278
constString = ((fv < 0) ? "-" : "") + "Inff";
279
else
280
constString = value.toString() + "f";
281
} else if (value instanceof Double) {
282
/* bug for bug */
283
double d = ((Double)value).doubleValue();
284
if (Double.isInfinite(d))
285
constString = ((d < 0) ? "-" : "") + "InfD";
286
else
287
constString = value.toString();
288
}
289
if (constString != null) {
290
StringBuilder s = new StringBuilder("#undef ");
291
s.append(cname); s.append("_"); s.append(fname); s.append(lineSep);
292
s.append("#define "); s.append(cname); s.append("_");
293
s.append(fname); s.append(" "); s.append(constString);
294
return s.toString();
295
}
296
297
}
298
}
299
return null;
300
}
301
302
/*
303
* Deal with the C pre-processor.
304
*/
305
protected String cppGuardBegin() {
306
return "#ifdef __cplusplus" + lineSep + "extern \"C\" {" + lineSep + "#endif";
307
}
308
309
protected String cppGuardEnd() {
310
return "#ifdef __cplusplus" + lineSep + "}" + lineSep + "#endif";
311
}
312
313
protected String guardBegin(String cname) {
314
return "/* Header for class " + cname + " */" + lineSep + lineSep +
315
"#ifndef _Included_" + cname + lineSep +
316
"#define _Included_" + cname;
317
}
318
319
protected String guardEnd(String cname) {
320
return "#endif";
321
}
322
323
/*
324
* File name and file preamble related operations.
325
*/
326
protected void writeFileTop(OutputStream o) throws Util.Exit {
327
PrintWriter pw = wrapWriter(o);
328
pw.println("/* DO NOT EDIT THIS FILE - it is machine generated */" + lineSep +
329
getIncludes());
330
}
331
332
protected String baseFileName(CharSequence className) {
333
return mangler.mangle(className, Mangle.Type.CLASS);
334
}
335
336
protected FileObject getFileObject(CharSequence className) throws IOException {
337
String name = baseFileName(className) + getFileSuffix();
338
return fileManager.getFileForOutput(StandardLocation.SOURCE_OUTPUT, "", name, null);
339
}
340
341
protected String getFileSuffix() {
342
return ".h";
343
}
344
345
/**
346
* Including super classes' fields.
347
*/
348
349
List<VariableElement> getAllFields(TypeElement subclazz) {
350
List<VariableElement> fields = new ArrayList<VariableElement>();
351
TypeElement cd = null;
352
Stack<TypeElement> s = new Stack<TypeElement>();
353
354
cd = subclazz;
355
while (true) {
356
s.push(cd);
357
TypeElement c = (TypeElement) (types.asElement(cd.getSuperclass()));
358
if (c == null)
359
break;
360
cd = c;
361
}
362
363
while (!s.empty()) {
364
cd = s.pop();
365
fields.addAll(ElementFilter.fieldsIn(cd.getEnclosedElements()));
366
}
367
368
return fields;
369
}
370
371
// c.f. MethodDoc.signature
372
String signature(ExecutableElement e) {
373
StringBuilder sb = new StringBuilder("(");
374
String sep = "";
375
for (VariableElement p: e.getParameters()) {
376
sb.append(sep);
377
sb.append(types.erasure(p.asType()).toString());
378
sep = ",";
379
}
380
sb.append(")");
381
return sb.toString();
382
}
383
}
384
385
386