duke@1: /* duke@1: * Copyright 2002-2006 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 com.sun.javadoc.*; duke@1: duke@1: /** duke@1: * A utility for mangling java identifiers into C names. Should make duke@1: * this more fine grained and distribute the functionality to the duke@1: * generators. duke@1: * duke@1: * @author Sucheta Dambalkar(Revised) duke@1: */ duke@1: class Mangle { duke@1: duke@1: public static class Type { duke@1: duke@1: public static final int CLASS = 1; duke@1: public static final int FIELDSTUB = 2; duke@1: public static final int FIELD = 3; duke@1: public static final int JNI = 4; duke@1: public static final int SIGNATURE = 5; duke@1: public static final int METHOD_JDK_1 = 6; duke@1: public static final int METHOD_JNI_SHORT = 7; duke@1: public static final int METHOD_JNI_LONG = 8; duke@1: }; duke@1: duke@1: duke@1: public static final String mangle(String name, int mtype) { duke@1: StringBuffer result = new StringBuffer(100); duke@1: int length = name.length(); duke@1: duke@1: for (int i = 0; i < length; i++) { duke@1: char ch = name.charAt(i); duke@1: if (isalnum(ch)) { duke@1: result.append(ch); duke@1: } else if ((ch == '.') && duke@1: mtype == Mangle.Type.CLASS) { duke@1: result.append('_'); duke@1: } else if (( ch == '$') && duke@1: mtype == Mangle.Type.CLASS) { duke@1: result.append('_'); duke@1: result.append('_'); duke@1: } else if (ch == '_' && mtype == Mangle.Type.FIELDSTUB) { duke@1: result.append('_'); duke@1: } else if (ch == '_' && mtype == Mangle.Type.CLASS) { duke@1: result.append('_'); duke@1: } else if (mtype == Mangle.Type.JNI) { duke@1: String esc = null; duke@1: if (ch == '_') duke@1: esc = "_1"; duke@1: else if (ch == '.') duke@1: esc = "_"; duke@1: else if (ch == ';') duke@1: esc = "_2"; duke@1: else if (ch == '[') duke@1: esc = "_3"; duke@1: if (esc != null) { duke@1: result.append(esc); duke@1: } else { duke@1: result.append(mangleChar(ch)); duke@1: } duke@1: } else if (mtype == Mangle.Type.SIGNATURE) { duke@1: if (isprint(ch)) { duke@1: result.append(ch); duke@1: } else { duke@1: result.append(mangleChar(ch)); duke@1: } duke@1: } else { duke@1: result.append(mangleChar(ch)); duke@1: } duke@1: } duke@1: duke@1: return result.toString(); duke@1: } duke@1: duke@1: public static String mangleMethod(MethodDoc method, RootDoc root, ClassDoc clazz, duke@1: int mtype) { duke@1: StringBuffer result = new StringBuffer(100); duke@1: result.append("Java_"); duke@1: duke@1: if (mtype == Mangle.Type.METHOD_JDK_1) { duke@1: result.append(mangle(clazz.qualifiedName(), Mangle.Type.CLASS)); duke@1: result.append('_'); duke@1: result.append(mangle(method.name(), duke@1: Mangle.Type.FIELD)); duke@1: result.append("_stub"); duke@1: return result.toString(); duke@1: } duke@1: duke@1: /* JNI */ duke@1: result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI)); duke@1: result.append('_'); duke@1: result.append(mangle(method.name(), duke@1: Mangle.Type.JNI)); duke@1: if (mtype == Mangle.Type.METHOD_JNI_LONG) { duke@1: result.append("__"); duke@1: String typesig = method.signature(); duke@1: TypeSignature newTypeSig = new TypeSignature(root); duke@1: String sig = newTypeSig.getTypeSignature(typesig, method.returnType()); duke@1: sig = sig.substring(1); duke@1: sig = sig.substring(0, sig.lastIndexOf(')')); duke@1: sig = sig.replace('/', '.'); duke@1: result.append(mangle(sig, Mangle.Type.JNI)); duke@1: } duke@1: duke@1: return result.toString(); duke@1: } duke@1: //where duke@1: private static String getInnerQualifiedName(ClassDoc clazz) { duke@1: ClassDoc encl = clazz.containingClass(); duke@1: if (encl == null) duke@1: return clazz.qualifiedName(); duke@1: else duke@1: return getInnerQualifiedName(encl) + '$' + clazz.simpleTypeName(); duke@1: } duke@1: duke@1: public static final String mangleChar(char ch) { duke@1: String s = Integer.toHexString(ch); duke@1: int nzeros = 5 - s.length(); duke@1: char[] result = new char[6]; duke@1: result[0] = '_'; duke@1: for (int i = 1; i <= nzeros; i++) duke@1: result[i] = '0'; duke@1: for (int i = nzeros+1, j = 0; i < 6; i++, j++) duke@1: result[i] = s.charAt(j); duke@1: return new String(result); duke@1: } duke@1: duke@1: /* Warning: Intentional ASCII operation. */ duke@1: private static final boolean isalnum(char ch) { duke@1: return ch <= 0x7f && /* quick test */ duke@1: ((ch >= 'A' && ch <= 'Z') || duke@1: (ch >= 'a' && ch <= 'z') || duke@1: (ch >= '0' && ch <= '9')); duke@1: } duke@1: duke@1: /* Warning: Intentional ASCII operation. */ duke@1: private static final boolean isprint(char ch) { duke@1: return ch >= 32 && ch <= 126; duke@1: } duke@1: }