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    }