diff options
| author | 2019-09-04 11:56:09 -0400 | |
|---|---|---|
| committer | 2019-09-04 11:56:09 -0400 | |
| commit | a67627646d8f2ccc39fff624b0a63badc00f0ded (patch) | |
| tree | e525d98d197334ce2bcdd91d7bb81e489ea6ef69 /src | |
| parent | Use name proposal service when exporting deobfuscated jar or decompiled sourc... (diff) | |
| download | enigma-fork-a67627646d8f2ccc39fff624b0a63badc00f0ded.tar.gz enigma-fork-a67627646d8f2ccc39fff624b0a63badc00f0ded.tar.xz enigma-fork-a67627646d8f2ccc39fff624b0a63badc00f0ded.zip | |
Add Proguard format
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java | 3 | ||||
| -rw-r--r-- | src/main/java/cuchaz/enigma/translation/mapping/serde/ProguardMappingsReader.java | 135 |
2 files changed, 137 insertions, 1 deletions
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java index 4799589..c770ddc 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java | |||
| @@ -15,7 +15,8 @@ public enum MappingFormat { | |||
| 15 | ENIGMA_FILE(EnigmaMappingsWriter.FILE, EnigmaMappingsReader.FILE), | 15 | ENIGMA_FILE(EnigmaMappingsWriter.FILE, EnigmaMappingsReader.FILE), |
| 16 | ENIGMA_DIRECTORY(EnigmaMappingsWriter.DIRECTORY, EnigmaMappingsReader.DIRECTORY), | 16 | ENIGMA_DIRECTORY(EnigmaMappingsWriter.DIRECTORY, EnigmaMappingsReader.DIRECTORY), |
| 17 | TINY_FILE(null, TinyMappingsReader.INSTANCE), | 17 | TINY_FILE(null, TinyMappingsReader.INSTANCE), |
| 18 | SRG_FILE(SrgMappingsWriter.INSTANCE, null); | 18 | SRG_FILE(SrgMappingsWriter.INSTANCE, null), |
| 19 | PROGUARD(null, ProguardMappingsReader.INSTANCE); | ||
| 19 | 20 | ||
| 20 | private final MappingsWriter writer; | 21 | private final MappingsWriter writer; |
| 21 | private final MappingsReader reader; | 22 | private final MappingsReader reader; |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/ProguardMappingsReader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/ProguardMappingsReader.java new file mode 100644 index 0000000..76f0923 --- /dev/null +++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/ProguardMappingsReader.java | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde; | ||
| 2 | |||
| 3 | import com.google.common.base.Charsets; | ||
| 4 | import cuchaz.enigma.ProgressListener; | ||
| 5 | import cuchaz.enigma.command.MappingCommandsUtil; | ||
| 6 | import cuchaz.enigma.throwables.MappingParseException; | ||
| 7 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 8 | import cuchaz.enigma.translation.mapping.MappingSaveParameters; | ||
| 9 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 10 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 11 | import cuchaz.enigma.translation.representation.MethodDescriptor; | ||
| 12 | import cuchaz.enigma.translation.representation.TypeDescriptor; | ||
| 13 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 14 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 15 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 16 | |||
| 17 | import java.io.IOException; | ||
| 18 | import java.nio.file.Files; | ||
| 19 | import java.nio.file.Path; | ||
| 20 | import java.util.regex.Matcher; | ||
| 21 | import java.util.regex.Pattern; | ||
| 22 | |||
| 23 | public class ProguardMappingsReader implements MappingsReader { | ||
| 24 | public static final ProguardMappingsReader INSTANCE = new ProguardMappingsReader(); | ||
| 25 | private static final String NAME = "[a-zA-Z0-9_\\-.$<>]+"; | ||
| 26 | private static final String TYPE = NAME + "(?:\\[])*"; | ||
| 27 | private static final String TYPE_LIST = "|(?:(?:" + TYPE + ",)*" + TYPE + ")"; | ||
| 28 | private static final Pattern CLASS = Pattern.compile("(" + NAME + ") -> (" + NAME + "):"); | ||
| 29 | private static final Pattern FIELD = Pattern.compile(" {4}(" + TYPE + ") (" + NAME + ") -> (" + NAME + ")"); | ||
| 30 | private static final Pattern METHOD = Pattern.compile(" {4}(?:[0-9]+:[0-9]+:)?(" + TYPE + ") (" + NAME + ")\\((" + TYPE_LIST + ")\\) -> (" + NAME + ")"); | ||
| 31 | |||
| 32 | public ProguardMappingsReader() {} | ||
| 33 | |||
| 34 | |||
| 35 | @Override | ||
| 36 | public EntryTree<EntryMapping> read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws MappingParseException, IOException { | ||
| 37 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); | ||
| 38 | |||
| 39 | int lineNumber = 0; | ||
| 40 | ClassEntry currentClass = null; | ||
| 41 | for (String line : Files.readAllLines(path, Charsets.UTF_8)) { | ||
| 42 | lineNumber++; | ||
| 43 | |||
| 44 | if (line.startsWith("#") || line.isEmpty()) { | ||
| 45 | continue; | ||
| 46 | } | ||
| 47 | |||
| 48 | Matcher classMatcher = CLASS.matcher(line); | ||
| 49 | Matcher fieldMatcher = FIELD.matcher(line); | ||
| 50 | Matcher methodMatcher = METHOD.matcher(line); | ||
| 51 | |||
| 52 | if (classMatcher.matches()) { | ||
| 53 | String name = classMatcher.group(1); | ||
| 54 | String targetName = classMatcher.group(2); | ||
| 55 | |||
| 56 | mappings.insert(currentClass = new ClassEntry(name.replace('.', '/')), new EntryMapping(ClassEntry.getInnerName(targetName.replace('.', '/')))); | ||
| 57 | } else if (fieldMatcher.matches()) { | ||
| 58 | String type = fieldMatcher.group(1); | ||
| 59 | String name = fieldMatcher.group(2); | ||
| 60 | String targetName = fieldMatcher.group(3); | ||
| 61 | |||
| 62 | if (currentClass == null) { | ||
| 63 | throw new MappingParseException(path::toString, lineNumber, "field mapping not inside class: " + line); | ||
| 64 | } | ||
| 65 | |||
| 66 | mappings.insert(new FieldEntry(currentClass, name, new TypeDescriptor(getDescriptor(type))), new EntryMapping(targetName)); | ||
| 67 | } else if (methodMatcher.matches()) { | ||
| 68 | String returnType = methodMatcher.group(1); | ||
| 69 | String name = methodMatcher.group(2); | ||
| 70 | String[] parameterTypes = methodMatcher.group(3).isEmpty() ? new String[0] : methodMatcher.group(3).split(","); | ||
| 71 | String targetName = methodMatcher.group(4); | ||
| 72 | |||
| 73 | if (currentClass == null) { | ||
| 74 | throw new MappingParseException(path::toString, lineNumber, "method mapping not inside class: " + line); | ||
| 75 | } | ||
| 76 | |||
| 77 | mappings.insert(new MethodEntry(currentClass, name, new MethodDescriptor(getDescriptor(returnType, parameterTypes))), new EntryMapping(targetName)); | ||
| 78 | } else { | ||
| 79 | throw new MappingParseException(path::toString, lineNumber, "invalid mapping line: " + line); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | return MappingCommandsUtil.invert(mappings); | ||
| 84 | } | ||
| 85 | |||
| 86 | private String getDescriptor(String type) { | ||
| 87 | StringBuilder descriptor = new StringBuilder(); | ||
| 88 | |||
| 89 | while (type.endsWith("[]")) { | ||
| 90 | descriptor.append("["); | ||
| 91 | type = type.substring(0, type.length() - 2); | ||
| 92 | } | ||
| 93 | |||
| 94 | switch (type) { | ||
| 95 | case "byte": | ||
| 96 | return descriptor + "B"; | ||
| 97 | case "char": | ||
| 98 | return descriptor + "C"; | ||
| 99 | case "short": | ||
| 100 | return descriptor + "S"; | ||
| 101 | case "int": | ||
| 102 | return descriptor + "I"; | ||
| 103 | case "long": | ||
| 104 | return descriptor + "J"; | ||
| 105 | case "float": | ||
| 106 | return descriptor + "F"; | ||
| 107 | case "double": | ||
| 108 | return descriptor + "D"; | ||
| 109 | case "boolean": | ||
| 110 | return descriptor + "Z"; | ||
| 111 | case "void": | ||
| 112 | return descriptor + "V"; | ||
| 113 | } | ||
| 114 | |||
| 115 | descriptor.append("L"); | ||
| 116 | descriptor.append(type.replace('.', '/')); | ||
| 117 | descriptor.append(";"); | ||
| 118 | |||
| 119 | return descriptor.toString(); | ||
| 120 | } | ||
| 121 | |||
| 122 | private String getDescriptor(String returnType, String[] parameterTypes) { | ||
| 123 | StringBuilder descriptor = new StringBuilder(); | ||
| 124 | descriptor.append('('); | ||
| 125 | |||
| 126 | for (String parameterType : parameterTypes) { | ||
| 127 | descriptor.append(getDescriptor(parameterType)); | ||
| 128 | } | ||
| 129 | |||
| 130 | descriptor.append(')'); | ||
| 131 | descriptor.append(getDescriptor(returnType)); | ||
| 132 | |||
| 133 | return descriptor.toString(); | ||
| 134 | } | ||
| 135 | } | ||