diff options
| author | 2015-02-06 00:01:42 -0500 | |
|---|---|---|
| committer | 2015-02-06 00:01:42 -0500 | |
| commit | 5a406268664e7a8db4991f421503afcf64780432 (patch) | |
| tree | ae4b319ac65de40b2c6307a193cbe363b2f80385 /src | |
| parent | explicitly add jre 7 to classpath (diff) | |
| parent | start some translation tests (diff) | |
| download | enigma-5a406268664e7a8db4991f421503afcf64780432.tar.gz enigma-5a406268664e7a8db4991f421503afcf64780432.tar.xz enigma-5a406268664e7a8db4991f421503afcf64780432.zip | |
Merge with a04907514a113e299dc667aa221a67573c5faa1b
Diffstat (limited to 'src')
| -rw-r--r-- | src/cuchaz/enigma/TranslatingTypeLoader.java | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/BehaviorSignature.java | 96 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/Mappings.java | 23 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/Type.java | 179 |
4 files changed, 276 insertions, 24 deletions
diff --git a/src/cuchaz/enigma/TranslatingTypeLoader.java b/src/cuchaz/enigma/TranslatingTypeLoader.java index 9287999b..cfa03a1a 100644 --- a/src/cuchaz/enigma/TranslatingTypeLoader.java +++ b/src/cuchaz/enigma/TranslatingTypeLoader.java | |||
| @@ -167,7 +167,7 @@ public class TranslatingTypeLoader implements ITypeLoader { | |||
| 167 | assertClassName(c, deobfClassEntry); | 167 | assertClassName(c, deobfClassEntry); |
| 168 | 168 | ||
| 169 | // DEBUG | 169 | // DEBUG |
| 170 | Util.writeClass( c ); | 170 | //Util.writeClass( c ); |
| 171 | 171 | ||
| 172 | // we have a transformed class! | 172 | // we have a transformed class! |
| 173 | return c.toBytecode(); | 173 | return c.toBytecode(); |
diff --git a/src/cuchaz/enigma/mapping/BehaviorSignature.java b/src/cuchaz/enigma/mapping/BehaviorSignature.java new file mode 100644 index 00000000..a6371f85 --- /dev/null +++ b/src/cuchaz/enigma/mapping/BehaviorSignature.java | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | package cuchaz.enigma.mapping; | ||
| 2 | |||
| 3 | import java.util.List; | ||
| 4 | |||
| 5 | import com.beust.jcommander.internal.Lists; | ||
| 6 | |||
| 7 | public class BehaviorSignature { | ||
| 8 | |||
| 9 | public static interface ClassReplacer { | ||
| 10 | ClassEntry replace(ClassEntry entry); | ||
| 11 | } | ||
| 12 | |||
| 13 | private List<Type> m_argumentTypes; | ||
| 14 | private Type m_returnType; | ||
| 15 | |||
| 16 | public BehaviorSignature(String signature) { | ||
| 17 | m_argumentTypes = Lists.newArrayList(); | ||
| 18 | int i=0; | ||
| 19 | while (i<signature.length()) { | ||
| 20 | char c = signature.charAt(i); | ||
| 21 | if (c == '(') { | ||
| 22 | assert(m_argumentTypes.isEmpty()); | ||
| 23 | assert(m_returnType == null); | ||
| 24 | i++; | ||
| 25 | } else if (c == ')') { | ||
| 26 | i++; | ||
| 27 | break; | ||
| 28 | } else { | ||
| 29 | String type = Type.parseFirst(signature.substring(i)); | ||
| 30 | m_argumentTypes.add(new Type(type)); | ||
| 31 | i += type.length(); | ||
| 32 | } | ||
| 33 | } | ||
| 34 | m_returnType = new Type(Type.parseFirst(signature.substring(i))); | ||
| 35 | } | ||
| 36 | |||
| 37 | public BehaviorSignature(BehaviorSignature other, ClassReplacer replacer) { | ||
| 38 | m_argumentTypes = Lists.newArrayList(other.m_argumentTypes); | ||
| 39 | for (int i=0; i<m_argumentTypes.size(); i++) { | ||
| 40 | Type type = m_argumentTypes.get(i); | ||
| 41 | if (type.isClass()) { | ||
| 42 | ClassEntry newClassEntry = replacer.replace(type.getClassEntry()); | ||
| 43 | if (newClassEntry != null) { | ||
| 44 | m_argumentTypes.set(i, new Type(newClassEntry)); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | } | ||
| 48 | m_returnType = other.m_returnType; | ||
| 49 | if (other.m_returnType.isClass()) { | ||
| 50 | ClassEntry newClassEntry = replacer.replace(m_returnType.getClassEntry()); | ||
| 51 | if (newClassEntry != null) { | ||
| 52 | m_returnType = new Type(newClassEntry); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | public List<Type> getArgumentTypes() { | ||
| 58 | return m_argumentTypes; | ||
| 59 | } | ||
| 60 | |||
| 61 | public Type getReturnType() { | ||
| 62 | return m_returnType; | ||
| 63 | } | ||
| 64 | |||
| 65 | @Override | ||
| 66 | public String toString() { | ||
| 67 | StringBuilder buf = new StringBuilder(); | ||
| 68 | buf.append("("); | ||
| 69 | for (int i=0; i<m_argumentTypes.size(); i++) { | ||
| 70 | if (i > 0) { | ||
| 71 | buf.append(","); | ||
| 72 | } | ||
| 73 | buf.append(m_argumentTypes.get(i).toString()); | ||
| 74 | } | ||
| 75 | buf.append(")"); | ||
| 76 | buf.append(m_returnType.toString()); | ||
| 77 | return buf.toString(); | ||
| 78 | } | ||
| 79 | |||
| 80 | public Iterable<Type> types() { | ||
| 81 | List<Type> types = Lists.newArrayList(); | ||
| 82 | types.addAll(m_argumentTypes); | ||
| 83 | types.add(m_returnType); | ||
| 84 | return types; | ||
| 85 | } | ||
| 86 | |||
| 87 | public Iterable<ClassEntry> classes() { | ||
| 88 | List<ClassEntry> out = Lists.newArrayList(); | ||
| 89 | for (Type type : types()) { | ||
| 90 | if (type.isClass()) { | ||
| 91 | out.add(type.getClassEntry()); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | return out; | ||
| 95 | } | ||
| 96 | } | ||
diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java index cc560a87..92134edf 100644 --- a/src/cuchaz/enigma/mapping/Mappings.java +++ b/src/cuchaz/enigma/mapping/Mappings.java | |||
| @@ -10,20 +10,15 @@ | |||
| 10 | ******************************************************************************/ | 10 | ******************************************************************************/ |
| 11 | package cuchaz.enigma.mapping; | 11 | package cuchaz.enigma.mapping; |
| 12 | 12 | ||
| 13 | import java.io.IOException; | ||
| 14 | import java.io.InputStream; | ||
| 15 | import java.io.ObjectInputStream; | ||
| 16 | import java.io.Serializable; | 13 | import java.io.Serializable; |
| 17 | import java.util.ArrayList; | 14 | import java.util.ArrayList; |
| 18 | import java.util.Collection; | 15 | import java.util.Collection; |
| 19 | import java.util.Map; | 16 | import java.util.Map; |
| 20 | import java.util.Set; | 17 | import java.util.Set; |
| 21 | import java.util.zip.GZIPInputStream; | ||
| 22 | 18 | ||
| 23 | import com.google.common.collect.Maps; | 19 | import com.google.common.collect.Maps; |
| 24 | import com.google.common.collect.Sets; | 20 | import com.google.common.collect.Sets; |
| 25 | 21 | ||
| 26 | import cuchaz.enigma.Util; | ||
| 27 | import cuchaz.enigma.analysis.TranslationIndex; | 22 | import cuchaz.enigma.analysis.TranslationIndex; |
| 28 | import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; | 23 | import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; |
| 29 | 24 | ||
| @@ -50,16 +45,6 @@ public class Mappings implements Serializable { | |||
| 50 | } | 45 | } |
| 51 | } | 46 | } |
| 52 | 47 | ||
| 53 | public static Mappings newFromResource(String resource) throws IOException { | ||
| 54 | InputStream in = null; | ||
| 55 | try { | ||
| 56 | in = Mappings.class.getResourceAsStream(resource); | ||
| 57 | return newFromStream(in); | ||
| 58 | } finally { | ||
| 59 | Util.closeQuietly(in); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | public Collection<ClassMapping> classes() { | 48 | public Collection<ClassMapping> classes() { |
| 64 | assert (m_classesByObf.size() >= m_classesByDeobf.size()); | 49 | assert (m_classesByObf.size() >= m_classesByDeobf.size()); |
| 65 | return m_classesByObf.values(); | 50 | return m_classesByObf.values(); |
| @@ -134,14 +119,6 @@ public class Mappings implements Serializable { | |||
| 134 | } | 119 | } |
| 135 | } | 120 | } |
| 136 | 121 | ||
| 137 | public static Mappings newFromStream(InputStream in) throws IOException { | ||
| 138 | try { | ||
| 139 | return (Mappings)new ObjectInputStream(new GZIPInputStream(in)).readObject(); | ||
| 140 | } catch (ClassNotFoundException ex) { | ||
| 141 | throw new Error(ex); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | @Override | 122 | @Override |
| 146 | public String toString() { | 123 | public String toString() { |
| 147 | StringBuilder buf = new StringBuilder(); | 124 | StringBuilder buf = new StringBuilder(); |
diff --git a/src/cuchaz/enigma/mapping/Type.java b/src/cuchaz/enigma/mapping/Type.java new file mode 100644 index 00000000..2273e21b --- /dev/null +++ b/src/cuchaz/enigma/mapping/Type.java | |||
| @@ -0,0 +1,179 @@ | |||
| 1 | package cuchaz.enigma.mapping; | ||
| 2 | |||
| 3 | import java.util.Map; | ||
| 4 | |||
| 5 | import com.google.common.collect.Maps; | ||
| 6 | |||
| 7 | public class Type { | ||
| 8 | |||
| 9 | public enum Primitive { | ||
| 10 | Byte('B'), | ||
| 11 | Character('C'), | ||
| 12 | Short('S'), | ||
| 13 | Integer('I'), | ||
| 14 | Long('J'), | ||
| 15 | Float('F'), | ||
| 16 | Double('D'), | ||
| 17 | Boolean('Z'); | ||
| 18 | |||
| 19 | private static final Map<Character,Primitive> m_lookup; | ||
| 20 | |||
| 21 | static { | ||
| 22 | m_lookup = Maps.newTreeMap(); | ||
| 23 | for (Primitive val : values()) { | ||
| 24 | m_lookup.put(val.getCode(), val); | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | public static Primitive get(char code) { | ||
| 29 | return m_lookup.get(code); | ||
| 30 | } | ||
| 31 | |||
| 32 | private char m_code; | ||
| 33 | |||
| 34 | private Primitive(char code) { | ||
| 35 | m_code = code; | ||
| 36 | } | ||
| 37 | |||
| 38 | public char getCode() { | ||
| 39 | return m_code; | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | public static String parseFirst(String in) { | ||
| 44 | |||
| 45 | // read one type from the input | ||
| 46 | |||
| 47 | char c = in.charAt(0); | ||
| 48 | |||
| 49 | // first check for void | ||
| 50 | if (c == 'V') { | ||
| 51 | return "V"; | ||
| 52 | } | ||
| 53 | |||
| 54 | // then check for primitives | ||
| 55 | Primitive primitive = Primitive.get(c); | ||
| 56 | if (primitive != null) { | ||
| 57 | return in.substring(0, 1); | ||
| 58 | } | ||
| 59 | |||
| 60 | // then check for classes | ||
| 61 | if (c == 'L') { | ||
| 62 | return readClass(in); | ||
| 63 | } | ||
| 64 | |||
| 65 | // then check for arrays | ||
| 66 | int dim = countArrayDimension(in); | ||
| 67 | if (dim > 0) { | ||
| 68 | String arrayType = Type.parseFirst(in.substring(dim)); | ||
| 69 | return in.substring(0, dim + arrayType.length()); | ||
| 70 | } | ||
| 71 | |||
| 72 | throw new IllegalArgumentException("don't know how to parse: " + in); | ||
| 73 | } | ||
| 74 | |||
| 75 | private String m_name; | ||
| 76 | |||
| 77 | public Type(String name) { | ||
| 78 | m_name = name; | ||
| 79 | } | ||
| 80 | |||
| 81 | public Type(ClassEntry classEntry) { | ||
| 82 | m_name = "L" + classEntry.getClassName() + ";"; | ||
| 83 | } | ||
| 84 | |||
| 85 | @Override | ||
| 86 | public String toString() { | ||
| 87 | return m_name; | ||
| 88 | } | ||
| 89 | |||
| 90 | public boolean isVoid() { | ||
| 91 | return m_name.length() == 1 && m_name.charAt(0) == 'V'; | ||
| 92 | } | ||
| 93 | |||
| 94 | public boolean isPrimitive() { | ||
| 95 | return m_name.length() == 1 && Primitive.get(m_name.charAt(0)) != null; | ||
| 96 | } | ||
| 97 | |||
| 98 | public Primitive getPrimitive() { | ||
| 99 | if (!isPrimitive()) { | ||
| 100 | throw new IllegalStateException("not a primitive"); | ||
| 101 | } | ||
| 102 | return Primitive.get(m_name.charAt(0)); | ||
| 103 | } | ||
| 104 | |||
| 105 | public boolean isClass() { | ||
| 106 | return m_name.charAt(0) == 'L' && m_name.charAt(m_name.length() - 1) == ';'; | ||
| 107 | } | ||
| 108 | |||
| 109 | public ClassEntry getClassEntry() { | ||
| 110 | if (!isClass()) { | ||
| 111 | throw new IllegalStateException("not a class"); | ||
| 112 | } | ||
| 113 | String name = m_name.substring(1, m_name.length() - 1); | ||
| 114 | |||
| 115 | int pos = name.indexOf('<'); | ||
| 116 | if (pos >= 0) { | ||
| 117 | // remove the parameters from the class name | ||
| 118 | name = name.substring(0, pos); | ||
| 119 | } | ||
| 120 | |||
| 121 | return new ClassEntry(name); | ||
| 122 | } | ||
| 123 | |||
| 124 | public boolean isArray() { | ||
| 125 | return m_name.charAt(0) == '['; | ||
| 126 | } | ||
| 127 | |||
| 128 | public int getArrayDimension() { | ||
| 129 | if (!isArray()) { | ||
| 130 | throw new IllegalStateException("not an array"); | ||
| 131 | } | ||
| 132 | return countArrayDimension(m_name); | ||
| 133 | } | ||
| 134 | |||
| 135 | public Type getArrayType() { | ||
| 136 | if (!isArray()) { | ||
| 137 | throw new IllegalStateException("not an array"); | ||
| 138 | } | ||
| 139 | return new Type(m_name.substring(getArrayDimension(), m_name.length())); | ||
| 140 | } | ||
| 141 | |||
| 142 | @Override | ||
| 143 | public boolean equals(Object other) { | ||
| 144 | if (other instanceof Type) { | ||
| 145 | return equals((Type)other); | ||
| 146 | } | ||
| 147 | return false; | ||
| 148 | } | ||
| 149 | |||
| 150 | public boolean equals(Type other) { | ||
| 151 | return m_name.equals(other.m_name); | ||
| 152 | } | ||
| 153 | |||
| 154 | private static int countArrayDimension(String in) { | ||
| 155 | int i=0; | ||
| 156 | for(; i < in.length() && in.charAt(i) == '['; i++); | ||
| 157 | return i; | ||
| 158 | } | ||
| 159 | |||
| 160 | private static String readClass(String in) { | ||
| 161 | // read all the characters in the buffer until we hit a ';' | ||
| 162 | // remember to treat parameters correctly | ||
| 163 | StringBuilder buf = new StringBuilder(); | ||
| 164 | int depth = 0; | ||
| 165 | for (int i=0; i<in.length(); i++) { | ||
| 166 | char c = in.charAt(i); | ||
| 167 | buf.append(c); | ||
| 168 | |||
| 169 | if (c == '<') { | ||
| 170 | depth++; | ||
| 171 | } else if (c == '>') { | ||
| 172 | depth--; | ||
| 173 | } else if (depth == 0 && c == ';') { | ||
| 174 | return buf.toString(); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | return null; | ||
| 178 | } | ||
| 179 | } | ||