duke@1: /* duke@1: * Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as duke@1: * published by the Free Software Foundation. Sun designates this duke@1: * particular file as subject to the "Classpath" exception as provided duke@1: * by Sun in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * duke@1: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@1: * CA 95054 USA or visit www.sun.com if you need additional information or duke@1: * have any questions. duke@1: */ duke@1: duke@1: duke@1: package com.sun.tools.javah; duke@1: duke@1: import java.io.File; duke@1: import java.io.OutputStream; duke@1: import java.io.PrintWriter; duke@1: import java.util.Hashtable; duke@1: import com.sun.javadoc.*; duke@1: duke@1: /* duke@1: * @author Sucheta Dambalkar(Revised) duke@1: */ duke@1: public class LLNI extends Gen { duke@1: duke@1: protected final char pathChar = File.separatorChar; duke@1: protected final char innerDelim = '$'; /* For inner classes */ duke@1: protected Hashtable doneHandleTypes; duke@1: MemberDoc []fields; duke@1: MemberDoc [] methods; duke@1: private boolean doubleAlign; duke@1: private int padFieldNum = 0; duke@1: duke@1: duke@1: LLNI(boolean doubleAlign, RootDoc root) { duke@1: super(root); duke@1: this.doubleAlign = doubleAlign; duke@1: } duke@1: duke@1: duke@1: protected String getIncludes() { duke@1: return ""; duke@1: } duke@1: duke@1: protected void write(OutputStream o, ClassDoc clazz) duke@1: throws ClassNotFoundException { duke@1: String cname = mangleClassName(clazz.qualifiedName()); duke@1: PrintWriter pw = wrapWriter(o); duke@1: fields = clazz.fields(); duke@1: methods = clazz.methods(); duke@1: generateDeclsForClass(pw, clazz, cname); duke@1: } duke@1: duke@1: protected void generateDeclsForClass(PrintWriter pw, duke@1: ClassDoc clazz, String cname) duke@1: throws ClassNotFoundException { duke@1: doneHandleTypes = new Hashtable(); duke@1: /* The following handle types are predefined in "typedefs.h". Suppress duke@1: inclusion in the output by generating them "into the blue" here. */ duke@1: genHandleType(null, "java.lang.Class"); duke@1: genHandleType(null, "java.lang.ClassLoader"); duke@1: genHandleType(null, "java.lang.Object"); duke@1: genHandleType(null, "java.lang.String"); duke@1: genHandleType(null, "java.lang.Thread"); duke@1: genHandleType(null, "java.lang.ThreadGroup"); duke@1: genHandleType(null, "java.lang.Throwable"); duke@1: duke@1: pw.println("/* LLNI Header for class " + clazz.qualifiedName() + " */" + lineSep); duke@1: pw.println("#ifndef _Included_" + cname); duke@1: pw.println("#define _Included_" + cname); duke@1: pw.println("#include \"typedefs.h\""); duke@1: pw.println("#include \"llni.h\""); duke@1: pw.println("#include \"jni.h\"" + lineSep); duke@1: duke@1: forwardDecls(pw, clazz); duke@1: structSectionForClass(pw, clazz, cname); duke@1: methodSectionForClass(pw, clazz, cname); duke@1: pw.println("#endif"); duke@1: } duke@1: duke@1: protected void genHandleType(PrintWriter pw, String clazzname) { duke@1: String cname = mangleClassName(clazzname); duke@1: if (!doneHandleTypes.containsKey(cname)) { duke@1: doneHandleTypes.put(cname, cname); duke@1: if (pw != null) { duke@1: pw.println("#ifndef DEFINED_" + cname); duke@1: pw.println(" #define DEFINED_" + cname); duke@1: pw.println(" GEN_HANDLE_TYPES(" + cname + ");"); duke@1: pw.println("#endif" + lineSep); duke@1: } duke@1: } duke@1: } duke@1: duke@1: protected String mangleClassName(String s) { duke@1: return s.replace('.', '_') duke@1: .replace(pathChar, '_') duke@1: .replace(innerDelim, '_'); duke@1: } duke@1: duke@1: protected void forwardDecls(PrintWriter pw, ClassDoc clazz) duke@1: throws ClassNotFoundException { duke@1: ClassDoc clazzfield = null; duke@1: duke@1: if (clazz.qualifiedName().equals("java.lang.Object")) duke@1: return; duke@1: genHandleType(pw, clazz.qualifiedName()); duke@1: ClassDoc superClass = clazz.superclass(); duke@1: duke@1: if(superClass != null){ duke@1: String superClassName = superClass.qualifiedName(); duke@1: forwardDecls(pw, superClass); duke@1: } duke@1: duke@1: for (int i = 0; i < fields.length; i++) { duke@1: FieldDoc field = (FieldDoc)fields[i]; duke@1: duke@1: if (!field.isStatic()) { duke@1: Type t = field.type(); duke@1: String tname = t.qualifiedTypeName(); duke@1: TypeSignature newTypeSig = new TypeSignature(root); duke@1: String sig = newTypeSig.getTypeSignature(tname); duke@1: duke@1: if (sig.charAt(0) != '[') duke@1: forwardDeclsFromSig(pw, sig); duke@1: } duke@1: } duke@1: duke@1: for (int i = 0; i < methods.length; i++) { duke@1: MethodDoc method = (MethodDoc)methods[i]; duke@1: duke@1: if (method.isNative()) { duke@1: Type retType = method.returnType(); duke@1: String typesig = method.signature(); duke@1: TypeSignature newTypeSig = new TypeSignature(root); duke@1: String sig = newTypeSig.getTypeSignature(typesig, retType); duke@1: duke@1: if (sig.charAt(0) != '[') duke@1: forwardDeclsFromSig(pw, sig); duke@1: duke@1: } duke@1: } duke@1: } duke@1: duke@1: protected void forwardDeclsFromSig(PrintWriter pw, String sig) { duke@1: int len = sig.length(); duke@1: int i = sig.charAt(0) == '(' ? 1 : 0; duke@1: duke@1: /* Skip the initial "(". */ duke@1: while (i < len) { duke@1: if (sig.charAt(i) == 'L') { duke@1: int j = i + 1; duke@1: while (sig.charAt(j) != ';') j++; duke@1: genHandleType(pw, sig.substring(i + 1, j)); duke@1: i = j + 1; duke@1: } else { duke@1: i++; duke@1: } duke@1: } duke@1: } duke@1: duke@1: protected void structSectionForClass(PrintWriter pw, duke@1: ClassDoc jclazz, String cname) duke@1: throws ClassNotFoundException { duke@1: duke@1: String jname = jclazz.qualifiedName(); duke@1: duke@1: if (cname.equals("java_lang_Object")) { duke@1: pw.println("/* struct java_lang_Object is defined in typedefs.h. */"); duke@1: pw.println(); duke@1: return; duke@1: } duke@1: pw.println("#if !defined(__i386)"); duke@1: pw.println("#pragma pack(4)"); duke@1: pw.println("#endif"); duke@1: pw.println(); duke@1: pw.println("struct " + cname + " {"); duke@1: pw.println(" ObjHeader h;"); duke@1: pw.print(fieldDefs(jclazz, cname)); duke@1: duke@1: if (jname.equals("java.lang.Class")) duke@1: pw.println(" Class *LLNI_mask(cClass);" + duke@1: " /* Fake field; don't access (see oobj.h) */"); duke@1: pw.println("};" + lineSep + lineSep + "#pragma pack()"); duke@1: pw.println(); duke@1: return; duke@1: } duke@1: duke@1: private static class FieldDefsRes { duke@1: public String className; /* Name of the current class. */ duke@1: public FieldDefsRes parent; duke@1: public String s; duke@1: public int byteSize; duke@1: public boolean bottomMost; duke@1: public boolean printedOne = false; duke@1: duke@1: FieldDefsRes(ClassDoc clazz, FieldDefsRes parent, boolean bottomMost) { duke@1: this.className = clazz.qualifiedName(); duke@1: this.parent = parent; duke@1: this.bottomMost = bottomMost; duke@1: int byteSize = 0; duke@1: if (parent == null) this.s = ""; duke@1: else this.s = parent.s; duke@1: } duke@1: } duke@1: duke@1: /* Returns "true" iff added a field. */ duke@1: private boolean doField(FieldDefsRes res, FieldDoc field, duke@1: String cname, boolean padWord) duke@1: throws ClassNotFoundException { duke@1: duke@1: String fieldDef = addStructMember(field, cname, padWord); duke@1: if (fieldDef != null) { duke@1: if (!res.printedOne) { /* add separator */ duke@1: if (res.bottomMost) { duke@1: if (res.s.length() != 0) duke@1: res.s = res.s + " /* local members: */" + lineSep; duke@1: } else { duke@1: res.s = res.s + " /* inherited members from " + duke@1: res.className + ": */" + lineSep; duke@1: } duke@1: res.printedOne = true; duke@1: } duke@1: res.s = res.s + fieldDef; duke@1: return true; duke@1: } duke@1: duke@1: // Otherwise. duke@1: return false; duke@1: } duke@1: duke@1: private int doTwoWordFields(FieldDefsRes res, ClassDoc clazz, duke@1: int offset, String cname, boolean padWord) duke@1: throws ClassNotFoundException { duke@1: boolean first = true; duke@1: FieldDoc[] fields = clazz.fields(); duke@1: duke@1: for (int i = 0; i = 'A') && (c <= 'Z')) || duke@1: ((c >= 'a') && (c <= 'z')) || duke@1: ((c >= '0') && (c <= '9'))) duke@1: return true; duke@1: else duke@1: return false; duke@1: } duke@1: }