001 /*
002 * Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026
027 package com.sun.tools.javah;
028
029 import com.sun.javadoc.*;
030
031 /**
032 * A utility for mangling java identifiers into C names. Should make
033 * this more fine grained and distribute the functionality to the
034 * generators.
035 *
036 * @author Sucheta Dambalkar(Revised)
037 */
038 class Mangle {
039
040 public static class Type {
041
042 public static final int CLASS = 1;
043 public static final int FIELDSTUB = 2;
044 public static final int FIELD = 3;
045 public static final int JNI = 4;
046 public static final int SIGNATURE = 5;
047 public static final int METHOD_JDK_1 = 6;
048 public static final int METHOD_JNI_SHORT = 7;
049 public static final int METHOD_JNI_LONG = 8;
050 };
051
052
053 public static final String mangle(String name, int mtype) {
054 StringBuffer result = new StringBuffer(100);
055 int length = name.length();
056
057 for (int i = 0; i < length; i++) {
058 char ch = name.charAt(i);
059 if (isalnum(ch)) {
060 result.append(ch);
061 } else if ((ch == '.') &&
062 mtype == Mangle.Type.CLASS) {
063 result.append('_');
064 } else if (( ch == '$') &&
065 mtype == Mangle.Type.CLASS) {
066 result.append('_');
067 result.append('_');
068 } else if (ch == '_' && mtype == Mangle.Type.FIELDSTUB) {
069 result.append('_');
070 } else if (ch == '_' && mtype == Mangle.Type.CLASS) {
071 result.append('_');
072 } else if (mtype == Mangle.Type.JNI) {
073 String esc = null;
074 if (ch == '_')
075 esc = "_1";
076 else if (ch == '.')
077 esc = "_";
078 else if (ch == ';')
079 esc = "_2";
080 else if (ch == '[')
081 esc = "_3";
082 if (esc != null) {
083 result.append(esc);
084 } else {
085 result.append(mangleChar(ch));
086 }
087 } else if (mtype == Mangle.Type.SIGNATURE) {
088 if (isprint(ch)) {
089 result.append(ch);
090 } else {
091 result.append(mangleChar(ch));
092 }
093 } else {
094 result.append(mangleChar(ch));
095 }
096 }
097
098 return result.toString();
099 }
100
101 public static String mangleMethod(MethodDoc method, RootDoc root, ClassDoc clazz,
102 int mtype) {
103 StringBuffer result = new StringBuffer(100);
104 result.append("Java_");
105
106 if (mtype == Mangle.Type.METHOD_JDK_1) {
107 result.append(mangle(clazz.qualifiedName(), Mangle.Type.CLASS));
108 result.append('_');
109 result.append(mangle(method.name(),
110 Mangle.Type.FIELD));
111 result.append("_stub");
112 return result.toString();
113 }
114
115 /* JNI */
116 result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI));
117 result.append('_');
118 result.append(mangle(method.name(),
119 Mangle.Type.JNI));
120 if (mtype == Mangle.Type.METHOD_JNI_LONG) {
121 result.append("__");
122 String typesig = method.signature();
123 TypeSignature newTypeSig = new TypeSignature(root);
124 String sig = newTypeSig.getTypeSignature(typesig, method.returnType());
125 sig = sig.substring(1);
126 sig = sig.substring(0, sig.lastIndexOf(')'));
127 sig = sig.replace('/', '.');
128 result.append(mangle(sig, Mangle.Type.JNI));
129 }
130
131 return result.toString();
132 }
133 //where
134 private static String getInnerQualifiedName(ClassDoc clazz) {
135 ClassDoc encl = clazz.containingClass();
136 if (encl == null)
137 return clazz.qualifiedName();
138 else
139 return getInnerQualifiedName(encl) + '$' + clazz.simpleTypeName();
140 }
141
142 public static final String mangleChar(char ch) {
143 String s = Integer.toHexString(ch);
144 int nzeros = 5 - s.length();
145 char[] result = new char[6];
146 result[0] = '_';
147 for (int i = 1; i <= nzeros; i++)
148 result[i] = '0';
149 for (int i = nzeros+1, j = 0; i < 6; i++, j++)
150 result[i] = s.charAt(j);
151 return new String(result);
152 }
153
154 /* Warning: Intentional ASCII operation. */
155 private static final boolean isalnum(char ch) {
156 return ch <= 0x7f && /* quick test */
157 ((ch >= 'A' && ch <= 'Z') ||
158 (ch >= 'a' && ch <= 'z') ||
159 (ch >= '0' && ch <= '9'));
160 }
161
162 /* Warning: Intentional ASCII operation. */
163 private static final boolean isprint(char ch) {
164 return ch >= 32 && ch <= 126;
165 }
166 }