1 cananian 1.1.2.1 // DefaultNameMap.java, created Tue Aug 10 17:47:50 1999 by cananian 2 cananian 1.1.2.1 // Copyright (C) 1999 Felix S. Klock II <pnkfelix@mit.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Backend.Maps; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.ClassFile.HClass; 7 cananian 1.1.2.1 import harpoon.ClassFile.HField; 8 cananian 1.1.2.1 import harpoon.ClassFile.HMethod; 9 cananian 1.1.2.1 import harpoon.Util.Util; 10 cananian 1.1.2.1 11 cananian 1.1.2.1 /** 12 cananian 1.1.2.1 * <code>DefaultNameMap</code> implements a 13 cananian 1.1.2.1 * <A HREF="http://java.sun.com/products/jdk/1.2/docs/guide/jni/index.html" 14 cananian 1.1.2.1 * >JNI</a>-compliant method name mangling, and class and field name mangling 15 cananian 1.1.2.1 * "in the spirit of" the JNI.<p> 16 cananian 1.1.2.1 * The resulting names are C-compliant; that is, they can be referenced 17 cananian 1.1.2.1 * from native code written in C. 18 cananian 1.1.2.1 * 19 cananian 1.1.2.1 * @author Felix S. Klock II <pnkfelix@mit.edu> 20 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 21 cananian 1.4 * @version $Id: DefaultNameMap.java,v 1.4 2002/04/10 03:03:02 cananian Exp $ 22 cananian 1.1.2.1 */ 23 cananian 1.1.2.1 public class DefaultNameMap extends NameMap { 24 cananian 1.1.2.5 private final boolean prependUnderscore; 25 cananian 1.1.2.5 26 cananian 1.1.2.4 private static final String member_prefix = "_Flex_"; 27 cananian 1.1.2.1 private static final String class_prefix = "_Class_"; 28 cananian 1.1.2.3 private static final String primitive_prefix = "_Primitive_"; 29 cananian 1.1.2.1 private static final String string_prefix = "_String_"; 30 cananian 1.1.2.1 private static final String suffix_sep = "_9"; // "$" is another option. 31 cananian 1.1.2.1 32 cananian 1.1.2.5 /** Creates a <code>DefaultNameMap</code>. If 33 cananian 1.1.2.5 * <code>prependUnderscore</code> is <code>true</code>, then 34 cananian 1.1.2.5 * underscores are prepended to c function names. Otherwise, 35 cananian 1.1.2.5 * the appear in the assembly output exactly as they do in C. 36 cananian 1.1.2.5 */ 37 cananian 1.1.2.5 public DefaultNameMap(boolean prependUnderscore) { 38 cananian 1.1.2.5 this.prependUnderscore = prependUnderscore; 39 cananian 1.1.2.5 } 40 cananian 1.1.2.5 41 cananian 1.1.2.5 /* Map C function names to assembly label strings. */ 42 cananian 1.1.2.5 public String c_function_name(String fn) { 43 cananian 1.1.2.5 if (prependUnderscore) return "_"+fn; else return fn; 44 cananian 1.1.2.5 } 45 cananian 1.1.2.1 46 cananian 1.1.2.1 /** Mangle a method name. */ 47 cananian 1.1.2.1 public String mangle(HMethod hm, String suffix) { 48 cananian 1.1.2.1 String desc = hm.getDescriptor(); 49 cananian 1.1.2.1 return member_prefix + 50 cananian 1.1.2.1 encode(hm.getDeclaringClass().getName()) + "_" + 51 cananian 1.1.2.1 encode(hm.getName()) + "__" + 52 cananian 1.1.2.1 encode(desc.substring(1,desc.lastIndexOf(')'))) + 53 cananian 1.1.2.1 (suffix==null?"":(suffix_sep+encode(suffix))); 54 cananian 1.1.2.1 } 55 cananian 1.1.2.1 /** Mangle a field name. */ 56 cananian 1.1.2.1 public String mangle(HField hf, String suffix) { 57 cananian 1.1.2.1 // won't conflict with method names because of "__" in 58 cananian 1.1.2.1 // method name (see above). A field "_" of class "foo" would 59 cananian 1.1.2.1 // be manged as "foo__1", and since there are not type 60 cananian 1.1.2.1 // descriptor strings starting with a number, this can 61 cananian 1.1.2.1 // not be confused with a method named "foo". 62 cananian 1.1.2.1 return member_prefix + 63 cananian 1.1.2.1 encode(hf.getDeclaringClass().getName()) + "_" + 64 cananian 1.1.2.1 encode(hf.getName()) + 65 cananian 1.1.2.1 (suffix==null?"":(suffix_sep+encode(suffix))); 66 cananian 1.1.2.1 } 67 cananian 1.1.2.1 /** Mangle a class name. */ 68 cananian 1.1.2.1 public String mangle(HClass hc, String suffix) { 69 cananian 1.1.2.3 String sufstr = (suffix==null?"":(suffix_sep+encode(suffix))); 70 cananian 1.1.2.3 if (hc.isPrimitive()) 71 cananian 1.1.2.3 return primitive_prefix + hc.getName() + sufstr; 72 cananian 1.1.2.3 else 73 cananian 1.1.2.3 return class_prefix + encode(hc.getName()) + sufstr; 74 cananian 1.1.2.1 } 75 cananian 1.1.2.1 76 cananian 1.1.2.1 /** Mangle a string constant reference. */ 77 cananian 1.1.2.1 public String mangle(String string_constant, String suffix) { 78 cananian 1.1.2.1 String base = string_prefix + toHex(string_constant.hashCode(), 8); 79 cananian 1.1.2.1 String r = base; 80 cananian 1.1.2.1 for (int i=0; 81 cananian 1.1.2.1 strMap.containsKey(r) && !strMap.get(r).equals(string_constant); 82 cananian 1.1.2.1 r = base + "x" + i++) 83 cananian 1.1.2.1 /* do nothing */; 84 cananian 1.3.2.1 assert !strMap.containsKey(r) || 85 cananian 1.3.2.1 strMap.get(r).equals(string_constant); 86 cananian 1.1.2.1 strMap.put(r, string_constant); 87 cananian 1.1.2.1 return r + (suffix==null?"":(suffix_sep+encode(suffix))); 88 cananian 1.1.2.1 } 89 cananian 1.1.2.1 private final java.util.Map strMap = new java.util.HashMap(); 90 cananian 1.1.2.1 91 cananian 1.1.2.1 //---------------------------------------------------------- 92 cananian 1.1.2.1 /** Apply the JNI-standard unicode-to-C encoding. */ 93 cananian 1.1.2.1 private static String encode(String s) { 94 cananian 1.1.2.1 StringBuffer sb = new StringBuffer(); 95 cananian 1.1.2.1 for(int i=0; i<s.length(); i++) { 96 cananian 1.1.2.1 switch(s.charAt(i)) { 97 cananian 1.1.2.1 case '.': 98 cananian 1.1.2.1 case '/': 99 cananian 1.1.2.1 sb.append("_"); 100 cananian 1.1.2.1 break; 101 cananian 1.1.2.1 case '_': 102 cananian 1.1.2.1 sb.append("_1"); 103 cananian 1.1.2.1 break; 104 cananian 1.1.2.1 case ';': 105 cananian 1.1.2.1 sb.append("_2"); 106 cananian 1.1.2.1 break; 107 cananian 1.1.2.1 case '[': 108 cananian 1.1.2.1 sb.append("_3"); 109 cananian 1.1.2.2 break; 110 cananian 1.1.2.1 default: 111 cananian 1.1.2.1 if ((s.charAt(i) >= 'a' && 112 cananian 1.1.2.1 s.charAt(i) <= 'z') || 113 cananian 1.1.2.1 (s.charAt(i) >= 'A' && 114 cananian 1.1.2.1 s.charAt(i) <= 'Z') || 115 cananian 1.1.2.1 (s.charAt(i) >= '0' && 116 cananian 1.1.2.1 s.charAt(i) <= '9')) { 117 cananian 1.1.2.1 sb.append(s.charAt(i)); 118 cananian 1.1.2.1 } else { 119 cananian 1.1.2.1 sb.append("_0" + toHex(s.charAt(i), 4)); 120 cananian 1.1.2.1 } 121 cananian 1.1.2.2 break; 122 cananian 1.1.2.1 } 123 cananian 1.1.2.1 } 124 cananian 1.1.2.1 return sb.toString(); 125 cananian 1.1.2.1 } 126 cananian 1.1.2.1 /** Convert the integer <code>value</code> into a hexadecimal 127 cananian 1.1.2.1 * string with at least <code>num_digits</code> digits. */ 128 cananian 1.1.2.1 private static String toHex(int value, int num_digits) { 129 cananian 1.1.2.1 String hexval= // javah puts all hex vals in lowercase. 130 cananian 1.1.2.1 Integer.toHexString(value).toLowerCase(); 131 cananian 1.1.2.1 while(hexval.length()<num_digits) hexval="0"+hexval; 132 cananian 1.1.2.1 return hexval; 133 cananian 1.1.2.1 } 134 cananian 1.2 }