001: /*
002: * @(#)JNIHeader.java 1.21 06/10/22
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package runtime;
029:
030: import consts.Const;
031: import jcc.Util;
032: import util.*;
033: import components.*;
034: import vm.*;
035: import java.io.PrintStream;
036: import java.util.Enumeration;
037: import java.util.Vector;
038: import java.util.Hashtable;
039:
040: public class JNIHeader extends HeaderDump {
041:
042: public JNIHeader() {
043: super ('_');
044: }
045:
046: class ParamTypeGenerator extends util.SignatureIterator {
047: String returnType;
048: Vector paramTypes = new Vector();
049:
050: ParamTypeGenerator(String s) {
051: super (s);
052: }
053:
054: private void put(String typestring) {
055: if (isReturnType)
056: returnType = typestring;
057: else
058: paramTypes.addElement(typestring);
059: }
060:
061: public void do_boolean() {
062: put("jboolean");
063: }
064:
065: public void do_byte() {
066: put("jbyte");
067: }
068:
069: public void do_short() {
070: put("jshort");
071: }
072:
073: public void do_char() {
074: put("jchar");
075: }
076:
077: public void do_int() {
078: put("jint");
079: }
080:
081: public void do_long() {
082: put("jlong");
083: }
084:
085: public void do_float() {
086: put("jfloat");
087: }
088:
089: public void do_double() {
090: put("jdouble");
091: }
092:
093: public void do_void() {
094: put("void");
095: }
096:
097: public void do_array(int depth, int start, int end) {
098: if (depth > 1) {
099: put("jobjectArray");
100: } else
101: switch (sig.charAt(start)) {
102: case Const.SIGC_BYTE:
103: put("jbyteArray");
104: break;
105: case Const.SIGC_CHAR:
106: put("jcharArray");
107: break;
108: case Const.SIGC_SHORT:
109: put("jshortArray");
110: break;
111: case Const.SIGC_BOOLEAN:
112: put("jbooleanArray");
113: break;
114: case Const.SIGC_INT:
115: put("jintArray");
116: break;
117: case Const.SIGC_LONG:
118: put("jlongArray");
119: break;
120: case Const.SIGC_FLOAT:
121: put("jfloatArray");
122: break;
123: case Const.SIGC_DOUBLE:
124: put("jdoubleArray");
125: break;
126: case Const.SIGC_CLASS:
127: case Const.SIGC_ARRAY:
128: put("jobjectArray");
129: break;
130: default:
131: put("void *");
132: break;
133: }
134: }
135:
136: public void do_object(int start, int end) {
137: String name = className(start, end);
138: if (name.equals("java/lang/String")) {
139: put("jstring");
140: } else if (name.equals("java/lang/Class")) {
141: put("jclass");
142: } else if (isThrowable(name)) {
143: put("jthrowable");
144: } else {
145: put("jobject");
146: }
147: }
148:
149: }
150:
151: boolean isThrowable(String classname) {
152: ClassInfo c = ClassTable.lookupClass(classname);
153: if (c == null) {
154: System.err.println(Localizer.getString(
155: "jniheader.cannot_find_class", classname));
156: return false;
157: }
158: while (c != null) {
159: if (c.className.equals("java/lang/Throwable"))
160: return true;
161: c = c.super ClassInfo;
162: }
163: return false;
164: }
165:
166: private boolean generateNatives(MethodInfo methods[],
167: boolean cplusplusguard) {
168: if (methods == null)
169: return false;
170: boolean anyMethods = false;
171: for (int i = 0; i < methods.length; i++) {
172: MethodInfo m = methods[i];
173: if ((m.access & Const.ACC_NATIVE) == 0)
174: continue;
175: if (cplusplusguard && !anyMethods) {
176: o.println("#ifdef __cplusplus\nextern \"C\"{\n#endif");
177: anyMethods = true;
178: }
179: String methodsig = m.type.string;
180: o.println("/*");
181: o.println(" * Class: " + className);
182: o.println(" * Method: " + m.name.string);
183: o.println(" * Signature: " + methodsig);
184: o.println(" */");
185: ParamTypeGenerator ptg;
186: try {
187: ptg = new ParamTypeGenerator(methodsig);
188: ptg.iterate();
189: } catch (Exception e) {
190: e.printStackTrace();
191: return anyMethods;
192: }
193: //
194: // decide whether to use long name or short.
195: // we use the long name only if we find another
196: // native method with the same short name.
197: //
198: String nameParams = null;
199: for (int j = 0; j < methods.length; j++) {
200: MethodInfo other = methods[j];
201: if ((other.access & Const.ACC_NATIVE) == 0)
202: continue;
203: if (other == m)
204: continue; // don't compare with self!
205: if (other.name.string.equals(m.name.string)) {
206: nameParams = methodsig;
207: break;
208: }
209: }
210: // print return type and name.
211: o.print("JNIEXPORT ");
212: o.print(ptg.returnType);
213: o.print(" JNICALL ");
214: o.println(Util.convertToJNIName(className, m.name.string,
215: nameParams));
216: // print parameter list
217: o.print(" (JNIEnv *,");
218: Enumeration tlist = ptg.paramTypes.elements();
219: // implicit first parameter of "this"
220: // or class pointer
221: if (m.isStaticMember()) {
222: o.print(" jclass");
223: } else {
224: o.print(" jobject");
225: }
226: while (tlist.hasMoreElements()) {
227: o.print(", ");
228: o.print(tlist.nextElement());
229: }
230: o.println(");\n");
231: }
232: if (cplusplusguard && anyMethods) {
233: o.println("#ifdef __cplusplus\n}\n#endif");
234: return true;
235: }
236: return false;
237: }
238:
239: private void prolog() {
240: o
241: .println("/* DO NOT EDIT THIS FILE - it is machine generated */\n"
242: + "#include \"javavm/export/jni.h\"");
243: o.println("/* Header for class " + className + " */\n");
244: String includeName = "_CVM_JNI_" + strsub(className, CDelim);
245: o.println("#ifndef " + includeName);
246: o.println("#define " + includeName);
247: }
248:
249: private void epilog() {
250: o.println("#endif");
251: }
252:
253: synchronized public boolean dumpHeader(ClassInfo c,
254: PrintStream outfile) {
255: boolean didWork;
256: o = outfile;
257: className = c.className;
258: prolog();
259: didWork = generateConsts(Util.convertToClassName(c.className),
260: c.fields);
261: didWork |= generateNatives(c.methods, true);
262: epilog();
263: return didWork;
264: }
265:
266: synchronized public boolean dumpExternals(ClassInfo c,
267: PrintStream outfile) {
268: boolean didWork;
269: o = outfile;
270: className = c.className;
271: didWork = generateNatives(c.methods, false);
272: return didWork;
273: }
274: }
|