diff --git a/install/fml.py b/install/fml.py index de4d31821b..be3d225bb5 100644 --- a/install/fml.py +++ b/install/fml.py @@ -190,6 +190,7 @@ def reset_logger(): count = 0 def cleanup_source(path): + from rename_vars import rename_class path = os.path.normpath(path) regex_cases_before = re.compile(r'((case|default).+\r?\n)\r?\n', re.MULTILINE) #Fixes newline after case before case body regex_cases_after = re.compile(r'\r?\n(\r?\n[ \t]+(case|default))', re.MULTILINE) #Fixes newline after case body before new case @@ -205,10 +206,13 @@ def cleanup_source(path): global count count += 1 return match.group(1) - + buf = regex_cases_before.sub(fix_cases, buf) buf = regex_cases_after.sub(fix_cases, buf) - if count > 0: + old = buf.replace('\r', '') + buf = rename_class(old, MCP=True) + + if count > 0 or buf != old: with open(tmp_file, 'w') as fh: fh.write(buf) shutil.move(tmp_file, src_file) diff --git a/install/rename_vars.py b/install/rename_vars.py new file mode 100644 index 0000000000..b639131073 --- /dev/null +++ b/install/rename_vars.py @@ -0,0 +1,167 @@ +import os, os.path, sys, csv, re, fnmatch, shutil, zipfile, pprint +from optparse import OptionParser +from pprint import pprint + +#This script attempts to rename local variables in a Fernflower decompiled Java source file to jad style names. +#Script originally written by Grum in perl, Converted to Python by monoxide, and bug fixes/cleanup by LexManos + +class VarNamer: + # Seems this is needed to keep these variables confined to the instance + def __init__(self): + self.last = { + 'byte': [0, 0, ['b']], + 'char': [0, 0, ['c']], + 'short': [1, 0, ['short']], + 'int': [0, 1, ['i', 'j', 'k', 'l']], + 'boolean': [0, 1, ['flag']], + 'double': [0, 0, ['d']], + 'float': [0, 1, ['f']], + 'File': [1, 1, ['file']], + 'String': [0, 1, ['s']], + 'Class': [0, 1, ['oclass']], + 'Long': [0, 1, ['olong']], + 'Byte': [0, 1, ['obyte']], + 'Short': [0, 1, ['oshort']], + 'Boolean': [0, 1, ['obool']], + 'Package': [0, 1, ['opackage']] + } + self.remap = { + 'long': 'int', + } + + def get_name(self, type, var): + index = type if self.last.has_key(type) else (self.remap[type] if self.remap.has_key(type) else None) + if (not index) and (re.search('^[A-Z]', type) or re.search(r'(\[|\.\.\.)', type)): + type = type.replace('...', '[]') + while type.find('[][]') != -1: + type = type.replace('[][]', '[]') + + name = type.lower() + skip = 1 + + if re.search(r'\[', type): + skip = 1 + name = "a" + name + name = name.replace('[', '').replace(']', '').replace('...', '') + + self.last[type] = [0, skip, [name]] + index = type + + if not index: + print "No data for type: %s '%s'\n" % (type, var) + return type + + id = self.last[index][0] + skip_zero = self.last[index][1] + data = self.last[index][2] + self.last[index][0] += 1 + + amount = len(data) + + if amount == 1: + return data[0] + ('' if ((not id) and skip_zero) else ('%d' % id)) + else: + num = id / amount + return data[id % amount] + ('' if ((not num) and skip_zero) else ('%d' % num)) + +def rename_file(file, indent='3', MCP=False): + tmp = file + '.tmp' + with open(file, 'rb') as in_file: + data = rename_class(in_file.read().replace('\r', ''), indent, MCP) + with open(tmp, 'wb') as out_file: + out_file.write(data) + shutil.move(tmp, file) + +def rename_class(data, indent='3', MCP=False): + METHOD_REG = r'^ {%s}(\w+\s+\S.*\.*(|static )(?:\{|\);|})$' % indent + CATCH_REG = r'catch \((.*)\) {' + if MCP: + if indent == '3': + indent = '4' + METHOD_REG = r'^ {%s}(\w+\s+\S.*\(.*|static)$' % indent + CATCH_REG = r'catch \((.*)\)$' + + lines = data.split('\n') + output = '' + + inside_method = False + method = '' + method_variables = [] + skip = False + + for line in lines: + line += '\n' + if re.search(METHOD_REG, line) and not re.search('=', line) and not re.search(r'\(.*\(', line): + if re.search(r'\(.+\)', line): + method_variables += [s.strip() for s in re.search(r'\((.+)\)', line).group(1).split(',')] + + method += line + + # Could be a single-line method + skip = True + if not re.search(r'(}|\);|throws .+?;)$', line): + inside_method = True + + elif re.search(r'^ {%s}}$' % indent, line): + inside_method = False + + if inside_method: + if skip: + skip = False + continue + + method += line + + m = re.search(CATCH_REG, line) + if m: + method_variables += [m.group(1)] + else: + method_variables += map(lambda x: x.group(0), filter( + lambda x: not re.match(r'^(return)', x.group(0)) and not re.match(r'^(throw)', x.group(0)), + re.finditer(r'([a-z_$][a-z0-9_\[\]]+ var\d+)', line, re.I))) + + else: + if method: + namer = VarNamer() + todo = map(lambda x: [x, namer.get_name(x.split(' ')[0], x)], method_variables) + + todo.reverse() + for mapping in todo: + if not ' ' in mapping[0]: + continue + original = mapping[0].split(' ')[1] + to = mapping[1] + + #Don't rename already renamed things. + if not re.match('var\d+', original): + continue + + method = method.replace(original, to) + + output += method + + method = '' + method_variables = [] + + if skip: + skip = False + continue + + output += line + + return output[:-1] + +def main(options, args): + for arg in args: + for path, _, filelist in os.walk(arg, followlinks=True): + for cur_file in fnmatch.filter(filelist, '*.java'): + file = os.path.normpath(os.path.join(path, cur_file)) + rename_file(file, options.indent, options.mcp) + +if __name__ == '__main__': + parser = OptionParser() + parser.add_option('-m', '--mcp', action='store_true', dest='mcp', help='Use MCP regexs', default=False) + parser.add_option('-i', '--indent', action='store', dest='indent', help='Custom indent to use', default='3') + options, args = parser.parse_args() + + main(options, args) \ No newline at end of file