duke@1: /* ohair@554: * Copyright (c) 2002, 2008, Oracle and/or its affiliates. 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 ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle 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: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: duke@1: package com.sun.tools.javah; duke@1: jjg@416: import javax.lang.model.element.ExecutableElement; jjg@416: import javax.lang.model.element.TypeElement; jjg@416: import javax.lang.model.element.VariableElement; jjg@416: import javax.lang.model.util.Elements; jjg@416: import javax.lang.model.util.Types; 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: * jjg@416: *

This is NOT part of any API supported by Sun Microsystems. jjg@416: * If you write code that depends on this, you do so at your own jjg@416: * risk. This code and its internal interfaces are subject to change jjg@416: * or deletion without notice.

jjg@416: * duke@1: * @author Sucheta Dambalkar(Revised) duke@1: */ jjg@416: public class Mangle { duke@1: duke@1: public static class Type { duke@1: public static final int CLASS = 1; duke@1: public static final int FIELDSTUB = 2; jjg@416: 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: jjg@416: private Elements elems; jjg@416: private Types types; duke@1: jjg@416: Mangle(Elements elems, Types types) { jjg@416: this.elems = elems; jjg@416: this.types = types; jjg@416: } jjg@416: jjg@416: public final String mangle(CharSequence 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: jjg@416: public String mangleMethod(ExecutableElement method, TypeElement 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) { jjg@416: result.append(mangle(clazz.getQualifiedName(), Mangle.Type.CLASS)); duke@1: result.append('_'); jjg@416: result.append(mangle(method.getSimpleName(), 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('_'); jjg@416: result.append(mangle(method.getSimpleName(), duke@1: Mangle.Type.JNI)); duke@1: if (mtype == Mangle.Type.METHOD_JNI_LONG) { duke@1: result.append("__"); jjg@416: String typesig = signature(method); jjg@416: TypeSignature newTypeSig = new TypeSignature(elems); jjg@416: String sig = newTypeSig.getTypeSignature(typesig, method.getReturnType()); 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 jjg@416: private String getInnerQualifiedName(TypeElement clazz) { jjg@416: return elems.getBinaryName(clazz).toString(); duke@1: } duke@1: jjg@416: public 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: jjg@416: // Warning: duplicated in Gen jjg@416: private String signature(ExecutableElement e) { jjg@416: StringBuffer sb = new StringBuffer(); jjg@416: String sep = "("; jjg@416: for (VariableElement p: e.getParameters()) { jjg@416: sb.append(sep); jjg@416: sb.append(types.erasure(p.asType()).toString()); jjg@416: sep = ","; jjg@416: } jjg@416: sb.append(")"); jjg@416: return sb.toString(); jjg@416: } jjg@416: 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: }