From b82bd3605874753a3571c3a5dfdf27ccd6f23df4 Mon Sep 17 00:00:00 2001 From: Honfika Date: Mon, 14 Oct 2013 23:47:26 +0200 Subject: [PATCH] more stringbuilders 2 --- .../com/jpexs/decompiler/flash/TagNode.java | 6 +- .../decompiler/flash/abc/ScriptPack.java | 9 +- .../decompiler/flash/abc/avm2/AVM2Code.java | 256 ++++++++---------- .../instructions/InstructionDefinition.java | 4 +- .../construction/NewFunctionIns.java | 17 +- .../flash/abc/avm2/model/AVM2Item.java | 6 - .../abc/avm2/model/NewFunctionAVM2Item.java | 53 +++- .../avm2/model/operations/IsTypeAVM2Item.java | 2 +- .../flash/abc/types/MethodBody.java | 47 ++-- .../flash/abc/types/MethodInfo.java | 33 +-- .../flash/abc/types/ScriptInfo.java | 5 +- .../flash/abc/types/traits/Trait.java | 37 ++- .../flash/abc/types/traits/TraitClass.java | 140 +++------- .../flash/abc/types/traits/TraitFunction.java | 33 ++- .../types/traits/TraitMethodGetterSetter.java | 30 +- .../abc/types/traits/TraitSlotConst.java | 99 +++---- .../flash/abc/types/traits/Traits.java | 56 ++-- .../abc/usages/ConstVarMultinameUsage.java | 19 +- .../abc/usages/MethodMultinameUsage.java | 32 ++- .../jpexs/decompiler/flash/action/Action.java | 150 +++++----- .../action/model/FunctionActionItem.java | 2 +- .../clauses/IfFrameLoadedActionItem.java | 2 +- .../flash/action/swf4/ActionPush.java | 37 +-- .../action/swf5/ActionDefineFunction.java | 6 +- .../action/swf7/ActionDefineFunction2.java | 6 +- .../flash/gui/abc/ASMSourceEditorPane.java | 5 +- .../flash/gui/abc/DecompiledEditorPane.java | 10 +- .../gui/abc/SlotConstTraitDetailPanel.java | 15 +- .../flash/gui/abc/TraitsListItem.java | 9 +- .../flash/gui/action/ActionPanel.java | 6 +- .../flash/helpers/HilightedTextWriter.java | 143 +++++++++- .../flash/helpers/hilight/Highlighting.java | 61 ----- .../flash/tags/DefineButtonTag.java | 5 +- .../decompiler/flash/tags/DoActionTag.java | 5 +- .../flash/tags/DoInitActionTag.java | 5 +- .../decompiler/flash/tags/base/ASMSource.java | 3 +- .../flash/types/BUTTONCONDACTION.java | 5 +- .../flash/types/CLIPACTIONRECORD.java | 5 +- .../decompiler/flash/xfl/XFLConverter.java | 6 +- .../src/com/jpexs/decompiler/graph/Graph.java | 2 +- .../decompiler/graph/model/BlockItem.java | 2 +- 41 files changed, 737 insertions(+), 637 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/TagNode.java b/trunk/src/com/jpexs/decompiler/flash/TagNode.java index ff8ef5977..07e825bf8 100644 --- a/trunk/src/com/jpexs/decompiler/flash/TagNode.java +++ b/trunk/src/com/jpexs/decompiler/flash/TagNode.java @@ -298,11 +298,13 @@ public class TagNode { String res; ASMSource asm = ((ASMSource) node.tag); if (isPcode) { - res = asm.getActionSourcePrefix() + Helper.indentRows(asm.getActionSourceIndent(), asm.getASMSource(SWF.DEFAULT_VERSION, false, false, null), HilightedTextWriter.INDENT_STRING) + asm.getActionSourceSuffix(); + HilightedTextWriter writer = new HilightedTextWriter(false, asm.getActionSourceIndent()); + asm.getASMSource(SWF.DEFAULT_VERSION, false, writer, null); + res = asm.getActionSourcePrefix() + writer.toString() + asm.getActionSourceSuffix(); } else { List as = asm.getActions(SWF.DEFAULT_VERSION); Action.setActionsAddresses(as, 0, SWF.DEFAULT_VERSION); - res = asm.getActionSourcePrefix() + Helper.indentRows(asm.getActionSourceIndent(), Action.actionsToSource(as, SWF.DEFAULT_VERSION, ""/*FIXME*/, false), HilightedTextWriter.INDENT_STRING) + asm.getActionSourceSuffix(); + res = asm.getActionSourcePrefix() + Action.actionsToSource(as, SWF.DEFAULT_VERSION, ""/*FIXME*/, false, asm.getActionSourceIndent()) + asm.getActionSourceSuffix(); } try (FileOutputStream fos = new FileOutputStream(f)) { fos.write(res.getBytes("utf-8")); diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/trunk/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index 33d95dbd7..c09bbce14 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -18,7 +18,9 @@ package com.jpexs.decompiler.flash.abc; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.graph.Graph; import com.jpexs.helpers.Helper; import java.io.File; import java.io.FileOutputStream; @@ -118,11 +120,14 @@ public class ScriptPack { for (int t : traitIndices) { Multiname name = abc.script_info[scriptIndex].traits.traits[t].getName(abc); Namespace ns = name.getNamespace(abc.constants); + HilightedTextWriter writer = new HilightedTextWriter(false); if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { - fos.write(abc.script_info[scriptIndex].traits.traits[t].convertPackaged(null, "", abcList, abc, false, pcode, scriptIndex, -1, false, new ArrayList(), parallel).getBytes("utf-8")); + abc.script_info[scriptIndex].traits.traits[t].convertPackaged(null, "", abcList, abc, false, pcode, scriptIndex, -1, writer, new ArrayList(), parallel); } else { - fos.write(abc.script_info[scriptIndex].traits.traits[t].convert(null, "", abcList, abc, false, pcode, scriptIndex, -1, false, new ArrayList(), parallel).getBytes("utf-8")); + abc.script_info[scriptIndex].traits.traits[t].convert(null, "", abcList, abc, false, pcode, scriptIndex, -1, writer, new ArrayList(), parallel); } + String s = Graph.removeNonRefenrencedLoopLabels(writer.toString()); + fos.write(s.getBytes("utf-8")); } } return file; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index c5a81e632..7ce5fe1b5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -718,169 +718,167 @@ public class AVM2Code implements Serializable { return writer; } - public String toASMSource(ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, boolean hex, boolean highlight) { - return toASMSource(constants, trait, info, body, new ArrayList(), hex, highlight); + public HilightedTextWriter toASMSource(ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, boolean hex, HilightedTextWriter writer) { + return toASMSource(constants, trait, info, body, new ArrayList(), hex, writer); } - public String toASMSource(ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, List outputMap, boolean hex, boolean highlight) { + public HilightedTextWriter toASMSource(ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, List outputMap, boolean hex, HilightedTextWriter writer) { invalidateCache(); - StringBuilder ret = new StringBuilder(); - String t = ""; if (trait != null) { if (trait instanceof TraitFunction) { TraitFunction tf = (TraitFunction) trait; - ret.append("trait "); - ret.append(Highlighting.hilighSpecial(highlight, "function ", "traittype")); - ret.append(Highlighting.hilighSpecial(highlight, constants.multinameToString(tf.name_index), "traitname")); - ret.append(" slotid "); - ret.append(Highlighting.hilighSpecial(highlight, "" + tf.slot_index, "slotid")); - ret.append("\n"); + writer.appendNoHilight("trait "); + writer.hilightSpecial("function ", "traittype"); + writer.hilightSpecial(constants.multinameToString(tf.name_index), "traitname"); + writer.appendNoHilight(" slotid "); + writer.hilightSpecial("" + tf.slot_index, "slotid"); + writer.newLine(); } if (trait instanceof TraitMethodGetterSetter) { TraitMethodGetterSetter tm = (TraitMethodGetterSetter) trait; - ret.append("trait "); + writer.appendNoHilight("trait "); switch (tm.kindType) { case Trait.TRAIT_METHOD: - ret.append(Highlighting.hilighSpecial(highlight, "method ", "traittype")); + writer.hilightSpecial("method ", "traittype"); break; case Trait.TRAIT_GETTER: - ret.append(Highlighting.hilighSpecial(highlight, "getter ", "traittype")); + writer.hilightSpecial("getter ", "traittype"); break; case Trait.TRAIT_SETTER: - ret.append(Highlighting.hilighSpecial(highlight, "setter ", "traittype")); + writer.hilightSpecial("setter ", "traittype"); break; } - ret.append(Highlighting.hilighSpecial(highlight, constants.multinameToString(tm.name_index), "traitname")); - ret.append(" dispid "); - ret.append(Highlighting.hilighSpecial(highlight, "" + tm.disp_id, "dispid")); - ret.append("\n"); + writer.hilightSpecial(constants.multinameToString(tm.name_index), "traitname"); + writer.appendNoHilight(" dispid "); + writer.hilightSpecial("" + tm.disp_id, "dispid"); + writer.newLine(); } } if (info != null) { - ret.append("method\n"); - ret.append("name "); - ret.append(Highlighting.hilighSpecial(highlight, info.name_index == 0 ? "null" : "\"" + Helper.escapeString(info.getName(constants)) + "\"", "methodname")); - ret.append("\n"); + writer.appendNoHilight("method").newLine(); + writer.appendNoHilight("name "); + writer.hilightSpecial(info.name_index == 0 ? "null" : "\"" + Helper.escapeString(info.getName(constants)) + "\"", "methodname"); + writer.newLine(); if (info.flagExplicit()) { - ret.append("flag "); - ret.append(Highlighting.hilighSpecial(highlight, "EXPLICIT", "flag.EXPLICIT")); - ret.append("\n"); + writer.appendNoHilight("flag "); + writer.hilightSpecial("EXPLICIT", "flag.EXPLICIT"); + writer.newLine(); } if (info.flagHas_optional()) { - ret.append("flag "); - ret.append(Highlighting.hilighSpecial(highlight, "HAS_OPTIONAL", "flag.HAS_OPTIONAL")); - ret.append("\n"); - ret.append("flag HAS_OPTIONAL\n"); + writer.appendNoHilight("flag "); + writer.hilightSpecial("HAS_OPTIONAL", "flag.HAS_OPTIONAL"); + writer.newLine(); + writer.appendNoHilight("flag HAS_OPTIONAL").newLine(); } if (info.flagHas_paramnames()) { - ret.append("flag "); - ret.append(Highlighting.hilighSpecial(highlight, "HAS_PARAM_NAMES", "flag.HAS_PARAM_NAMES")); - ret.append("\n"); + writer.appendNoHilight("flag "); + writer.hilightSpecial("HAS_PARAM_NAMES", "flag.HAS_PARAM_NAMES"); + writer.newLine(); } if (info.flagIgnore_rest()) { - ret.append("flag "); - ret.append(Highlighting.hilighSpecial(highlight, "EXPLICIT", "flag.IGNORE_REST")); - ret.append("\n"); + writer.appendNoHilight("flag "); + writer.hilightSpecial("EXPLICIT", "flag.IGNORE_REST"); + writer.newLine(); } if (info.flagNeed_activation()) { - ret.append("flag "); - ret.append(Highlighting.hilighSpecial(highlight, "NEED_ACTIVATION", "flag.NEED_ACTIVATION")); - ret.append("\n"); + writer.appendNoHilight("flag "); + writer.hilightSpecial("NEED_ACTIVATION", "flag.NEED_ACTIVATION"); + writer.newLine(); } if (info.flagNeed_arguments()) { - ret.append("flag "); - ret.append(Highlighting.hilighSpecial(highlight, "NEED_ARGUMENTS", "flag.NEED_ARGUMENTS")); - ret.append("\n"); + writer.appendNoHilight("flag "); + writer.hilightSpecial("NEED_ARGUMENTS", "flag.NEED_ARGUMENTS"); + writer.newLine(); } if (info.flagNeed_rest()) { - ret.append("flag "); - ret.append(Highlighting.hilighSpecial(highlight, "NEED_REST", "flag.NEED_REST")); - ret.append("\n"); + writer.appendNoHilight("flag "); + writer.hilightSpecial("NEED_REST", "flag.NEED_REST"); + writer.newLine(); } if (info.flagSetsdxns()) { - ret.append("flag "); - ret.append(Highlighting.hilighSpecial(highlight, "SET_DXNS", "flag.SET_DXNS")); - ret.append("\n"); + writer.appendNoHilight("flag "); + writer.hilightSpecial("SET_DXNS", "flag.SET_DXNS"); + writer.newLine(); } for (int p = 0; p < info.param_types.length; p++) { - ret.append("param "); - ret.append(Highlighting.hilighSpecial(highlight, constants.multinameToString(info.param_types[p]), "param", p)); - ret.append("\n"); + writer.appendNoHilight("param "); + writer.hilightSpecial(constants.multinameToString(info.param_types[p]), "param", p); + writer.newLine(); } if (info.flagHas_paramnames()) { for (int n : info.paramNames) { - ret.append("paramname "); + writer.appendNoHilight("paramname "); if (n == 0) { - ret.append("null"); + writer.appendNoHilight("null"); } else { - ret.append("\""); - ret.append(constants.constant_string[n]); - ret.append("\""); + writer.appendNoHilight("\""); + writer.appendNoHilight(constants.constant_string[n]); + writer.appendNoHilight("\""); } - ret.append("\n"); + writer.newLine(); } } if (info.flagHas_optional()) { for (int i = 0; i < info.optional.length; i++) { ValueKind vk = info.optional[i]; - ret.append("optional "); - ret.append(Highlighting.hilighSpecial(highlight, vk.toString(constants), "optional", i)); - ret.append("\n"); + writer.appendNoHilight("optional "); + writer.hilightSpecial(vk.toString(constants), "optional", i); + writer.newLine(); } } - ret.append("returns "); - ret.append(Highlighting.hilighSpecial(highlight, constants.multinameToString(info.ret_type), "returns")); - ret.append("\n"); + writer.appendNoHilight("returns "); + writer.hilightSpecial(constants.multinameToString(info.ret_type), "returns"); + writer.newLine(); } - ret.append("\n"); - ret.append("body\n"); + writer.newLine(); + writer.appendNoHilight("body").newLine(); - ret.append("maxstack "); - ret.append(body.max_stack); - ret.append("\n"); + writer.appendNoHilight("maxstack "); + writer.appendNoHilight(body.max_stack); + writer.newLine(); - ret.append("localcount "); - ret.append(body.max_regs); - ret.append("\n"); + writer.appendNoHilight("localcount "); + writer.appendNoHilight(body.max_regs); + writer.newLine(); - ret.append("initscopedepth "); - ret.append(body.init_scope_depth); - ret.append("\n"); + writer.appendNoHilight("initscopedepth "); + writer.appendNoHilight(body.init_scope_depth); + writer.newLine(); - ret.append("maxscopedepth "); - ret.append(body.max_scope_depth); - ret.append("\n"); + writer.appendNoHilight("maxscopedepth "); + writer.appendNoHilight(body.max_scope_depth); + writer.newLine(); List offsets = new ArrayList<>(); for (int e = 0; e < body.exceptions.length; e++) { - ret.append("try"); + writer.appendNoHilight("try"); - ret.append(" from "); - ret.append("ofs"); - ret.append(Helper.formatAddress(body.exceptions[e].start)); + writer.appendNoHilight(" from "); + writer.appendNoHilight("ofs"); + writer.appendNoHilight(Helper.formatAddress(body.exceptions[e].start)); offsets.add((long) body.exceptions[e].start); - ret.append(" to "); - ret.append("ofs"); - ret.append(Helper.formatAddress(body.exceptions[e].end)); + writer.appendNoHilight(" to "); + writer.appendNoHilight("ofs"); + writer.appendNoHilight(Helper.formatAddress(body.exceptions[e].end)); offsets.add((long) body.exceptions[e].end); - ret.append(" target "); - ret.append("ofs"); - ret.append(Helper.formatAddress(body.exceptions[e].target)); + writer.appendNoHilight(" target "); + writer.appendNoHilight("ofs"); + writer.appendNoHilight(Helper.formatAddress(body.exceptions[e].target)); offsets.add((long) body.exceptions[e].target); - ret.append(" type "); - ret.append(Highlighting.hilighSpecial(highlight, body.exceptions[e].type_index == 0 ? "null" : constants.constant_multiname[body.exceptions[e].type_index].toString(constants, new ArrayList()), "try.type", e)); + writer.appendNoHilight(" type "); + writer.hilightSpecial(body.exceptions[e].type_index == 0 ? "null" : constants.constant_multiname[body.exceptions[e].type_index].toString(constants, new ArrayList()), "try.type", e); - ret.append(" name "); - ret.append(Highlighting.hilighSpecial(highlight, body.exceptions[e].name_index == 0 ? "null" : constants.constant_multiname[body.exceptions[e].name_index].toString(constants, new ArrayList()), "try.name", e)); - ret.append("\n"); + writer.appendNoHilight(" name "); + writer.hilightSpecial(body.exceptions[e].name_index == 0 ? "null" : constants.constant_multiname[body.exceptions[e].name_index].toString(constants, new ArrayList()), "try.name", e); + writer.newLine(); } - ret.append("\n"); - ret.append("code\n"); + writer.newLine(); + writer.appendNoHilight("code").newLine(); for (AVM2Instruction ins : code) { offsets.addAll(ins.getOffsets()); @@ -903,14 +901,14 @@ public class AVM2Code implements Serializable { boolean markOffsets = code.size() <= largeLimit; for (AVM2Instruction ins : code) { if (hex) { - ret.append(""); - ret.append(Helper.bytesToHexString(ins.getBytes())); - ret.append("\n"); + writer.appendNoHilight(""); + writer.appendNoHilight(Helper.bytesToHexString(ins.getBytes())); + writer.appendNoHilight("\n"); } if (ins.labelname != null) { - ret.append(ins.labelname + ":"); + writer.appendNoHilight(ins.labelname + ":"); } else if (offsets.contains(ofs)) { - ret.append("ofs" + Helper.formatAddress(ofs) + ":"); + writer.appendNoHilight("ofs" + Helper.formatAddress(ofs) + ":"); } /*for (int e = 0; e < body.exceptions.length; e++) { if (body.exceptions[e].start == ofs) { @@ -930,58 +928,54 @@ public class AVM2Code implements Serializable { if (ins2.isIgnored()) { continue; } - t = highlight ? Highlighting.hilighOffset("", ins2.mappedOffset > -1 ? ins2.mappedOffset : ofs) : ""; - t += ins2.toStringNoAddress(constants, new ArrayList()) + " ;copy from " + Helper.formatAddress(pos2adr((Integer) o)) + "\n"; - ret.append(t); + writer.append("", ins2.mappedOffset > -1 ? ins2.mappedOffset : ofs); + writer.appendNoHilight(ins2.toStringNoAddress(constants, new ArrayList()) + " ;copy from " + Helper.formatAddress(pos2adr((Integer) o))); + writer.newLine(); outputMap.add((Integer) o); } else if (o instanceof ControlFlowTag) { ControlFlowTag cft = (ControlFlowTag) o; if (cft.name.equals("appendjump")) { - t = "jump ofs" + Helper.formatAddress(pos2adr(cft.value)) + "\n"; - ret.append(t); + writer.appendNoHilight("jump ofs" + Helper.formatAddress(pos2adr(cft.value))).newLine(); outputMap.add(-1); } if (cft.name.equals("mark")) { - ret.append("ofs" + Helper.formatAddress(pos2adr(cft.value)) + ":"); + writer.appendNoHilight("ofs" + Helper.formatAddress(pos2adr(cft.value)) + ":"); } } } } else { if (!ins.isIgnored()) { + if (markOffsets) { + writer.append("", ins.mappedOffset > -1 ? ins.mappedOffset : ofs); + } int fixBranch = ins.getFixBranch(); if (fixBranch > -1) { if (ins.definition instanceof IfTypeIns) { - t = ""; for (int i = 0; i < -ins.definition.getStackDelta(ins, null/*IfTypeIns do not require ABCs*/); i++) { - t += new DeobfuscatePopIns().instructionName + "\n"; + writer.appendNoHilight(new DeobfuscatePopIns().instructionName).newLine(); } if (fixBranch == 0) { //jump - t += new JumpIns().instructionName + " ofs" + Helper.formatAddress(ofs + ins.getBytes().length + ins.operands[0]); + writer.appendNoHilight(new JumpIns().instructionName + " ofs" + Helper.formatAddress(ofs + ins.getBytes().length + ins.operands[0])); } else { //nojump, ignore } } //TODO: lookupswitch ? } else { - t = ins.toStringNoAddress(constants, new ArrayList()); if (ins.changeJumpTo > -1) { - t = ins.definition.instructionName + " ofs" + Helper.formatAddress(pos2adr(ins.changeJumpTo)); + writer.appendNoHilight(ins.definition.instructionName + " ofs" + Helper.formatAddress(pos2adr(ins.changeJumpTo))); + } else { + writer.appendNoHilight(ins.toStringNoAddress(constants, new ArrayList())); } } - if (markOffsets) { - t = (highlight ? Highlighting.hilighOffset("", ins.mappedOffset > -1 ? ins.mappedOffset : ofs) : "") + t + "\n"; - } else { - t = t + "\n"; - } - ret.append(t); + writer.newLine(); outputMap.add(ip); } } ofs += ins.getBytes().length; ip++; } - String r = ret.toString(); - return r; + return writer; } private boolean cacheActual = false; private List posCache; @@ -1338,20 +1332,6 @@ public class AVM2Code implements Serializable { } } - public String tabString(int len) { - StringBuilder ret = new StringBuilder(); - for (int i = 0; i < len; i++) { - ret.append(HilightedTextWriter.INDENT_STRING); - } - return ret.toString(); - } - - public String toSource(String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, ConstantPool constants, MethodInfo[] method_info, MethodBody body, HashMap localRegNames, Stack scopeStack, boolean isStaticInitializer, List fullyQualifiedNames, Traits initTraits, int staticOperation, HashMap localRegAssigmentIps, HashMap> refs) { - HilightedTextWriter writer = new HilightedTextWriter(false); - toSource(path, isStatic, scriptIndex, classIndex, abc, constants, method_info, body, writer, true, localRegNames, scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits, staticOperation, localRegAssigmentIps, refs); - return writer.toString(); - } - public int getRegisterCount() { int maxRegister = -1; for (AVM2Instruction ins : code) { @@ -1419,7 +1399,7 @@ public class AVM2Code implements Serializable { ignoredIns = new ArrayList<>(); } - public HilightedTextWriter toSource(String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, ConstantPool constants, MethodInfo[] method_info, MethodBody body, HilightedTextWriter writer, boolean replaceIndents, HashMap localRegNames, Stack scopeStack, boolean isStaticInitializer, List fullyQualifiedNames, Traits initTraits, int staticOperation, HashMap localRegAssigmentIps, HashMap> refs) { + public HilightedTextWriter toSource(String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, ConstantPool constants, MethodInfo[] method_info, MethodBody body, HilightedTextWriter writer, HashMap localRegNames, Stack scopeStack, boolean isStaticInitializer, List fullyQualifiedNames, Traits initTraits, int staticOperation, HashMap localRegAssigmentIps, HashMap> refs) { initToSource(); List list; String s; @@ -1534,7 +1514,7 @@ public class AVM2Code implements Serializable { list.remove(lastPos); } - Graph.graphToString(list, writer, replaceIndents, LocalData.create(constants, localRegNames, fullyQualifiedNames)); + Graph.graphToString(list, writer, LocalData.create(constants, localRegNames, fullyQualifiedNames)); return writer; } @@ -2115,7 +2095,9 @@ public class AVM2Code implements Serializable { invalidateCache(); try { List outputMap = new ArrayList<>(); - String src = toASMSource(constants, trait, info, body, outputMap, false, false); + HilightedTextWriter writer = new HilightedTextWriter(false); + toASMSource(constants, trait, info, body, outputMap, false, writer); + String src = writer.toString(); AVM2Code acode = ASM3Parser.parse(new ByteArrayInputStream(src.getBytes("UTF-8")), constants, null, body, info); for (int i = 0; i < acode.code.size(); i++) { @@ -2155,7 +2137,9 @@ public class AVM2Code implements Serializable { public void removeIgnored(ConstantPool constants, Trait trait, MethodInfo info, MethodBody body) { try { List outputMap = new ArrayList<>(); - String src = toASMSource(constants, trait, info, body, outputMap, false, false); + HilightedTextWriter writer = new HilightedTextWriter(false); + toASMSource(constants, trait, info, body, outputMap, false, writer); + String src = writer.toString(); AVM2Code acode = ASM3Parser.parse(new ByteArrayInputStream(src.getBytes("UTF-8")), constants, trait, body, info); for (int i = 0; i < acode.code.size(); i++) { if (outputMap.size() > i) { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java index 19e49748f..cd325c9ab 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java @@ -29,7 +29,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.graph.GraphTargetItem; import java.io.Serializable; import java.util.HashMap; @@ -117,7 +117,7 @@ public class InstructionDefinition implements Serializable { if (constants.constant_multiname[multinameIndex].needsName()) { name = stack.get(pos).toString(); } else { - name = Highlighting.hilighOffset(constants.constant_multiname[multinameIndex].getName(constants, fullyQualifiedNames), ins.offset); + name = HilightedTextWriter.hilighOffset(constants.constant_multiname[multinameIndex].getName(constants, fullyQualifiedNames), ins.offset); } return name + ns; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewFunctionIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewFunctionIns.java index e0e16b2f8..96883f52c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewFunctionIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewFunctionIns.java @@ -28,8 +28,6 @@ import com.jpexs.decompiler.graph.GraphTargetItem; import java.util.HashMap; import java.util.List; import java.util.Stack; -import java.util.logging.Level; -import java.util.logging.Logger; public class NewFunctionIns extends InstructionDefinition { @@ -40,19 +38,8 @@ public class NewFunctionIns extends InstructionDefinition { @Override public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap localRegs, Stack stack, java.util.Stack scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { int methodIndex = ins.operands[0]; - MethodBody mybody = abc.findBody(methodIndex); - String bodyStr = ""; - String paramStr = ""; - if (mybody != null) { - try { - bodyStr = mybody.toString(path + "/inner", false, isStatic, scriptIndex, classIndex, abc, null, constants, method_info, new Stack()/*scopeStack*/, false, true, false, fullyQualifiedNames, null); - } catch (Exception ex) { - Logger.getLogger(NewFunctionIns.class.getName()).log(Level.SEVERE, "error during newfunction", ex); - } - paramStr = method_info[methodIndex].getParamStr(true, constants, mybody, abc, fullyQualifiedNames); - } - - stack.push(new NewFunctionAVM2Item(ins, "", paramStr, method_info[methodIndex].getReturnTypeStr(true, constants, fullyQualifiedNames), bodyStr, methodIndex)); + NewFunctionAVM2Item function = new NewFunctionAVM2Item(ins, "", path, isStatic, scriptIndex, classIndex, abc, fullyQualifiedNames, constants, method_info, methodIndex); + stack.push(function); } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java index 356a057dc..ee02fde05 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java @@ -33,12 +33,6 @@ public abstract class AVM2Item extends GraphTargetItem { super(instruction, precedence); } - public String toStringNoH(LocalData localData) { - HilightedTextWriter writer = new HilightedTextWriter(false); - toString(writer, localData); - return writer.toString(); - } - @Override public boolean needsSemicolon() { return true; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java index 8a5b37d06..cb7a6a746 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java @@ -16,38 +16,67 @@ */ package com.jpexs.decompiler.flash.abc.avm2.model; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.model.LocalData; +import java.util.List; +import java.util.Stack; +import java.util.logging.Level; +import java.util.logging.Logger; public class NewFunctionAVM2Item extends AVM2Item { - public String paramStr; - public String returnStr; - public String functionBody; public String functionName; + public String path; + public boolean isStatic; + public int scriptIndex; + public int classIndex; + public ABC abc; + public List fullyQualifiedNames; + public ConstantPool constants; + public MethodInfo[] methodInfo; public int methodIndex; - public NewFunctionAVM2Item(AVM2Instruction instruction, String functionName, String paramStr, String returnStr, String functionBody, int methodIndex) { + public NewFunctionAVM2Item(AVM2Instruction instruction, String functionName, String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, List fullyQualifiedNames, ConstantPool constants, MethodInfo[] methodInfo, int methodIndex) { super(instruction, PRECEDENCE_PRIMARY); - this.paramStr = paramStr; - this.returnStr = returnStr; - this.functionBody = functionBody; this.functionName = functionName; + this.path = path; + this.isStatic = isStatic; + this.scriptIndex = scriptIndex; + this.classIndex = classIndex; + this.abc = abc; + this.fullyQualifiedNames = fullyQualifiedNames; + this.constants = constants; + this.methodInfo = methodInfo; this.methodIndex = methodIndex; } @Override protected HilightedTextWriter appendTo(HilightedTextWriter writer, LocalData localData) { + MethodBody body = abc.findBody(methodIndex); writer.append("function" + (!functionName.equals("") ? " " + functionName : "")); - boolean highlight = writer.getIsHighlighted(); - String mhead = "(" + (highlight ? paramStr : Highlighting.stripHilights(paramStr)) + "):" + (highlight ? returnStr : Highlighting.stripHilights(returnStr)); - writer.appendNoHilight(writer.getIsHighlighted() ? Highlighting.hilighMethod(mhead, methodIndex) : mhead); + writer.startMethod(methodIndex); + writer.appendNoHilight("("); + methodInfo[methodIndex].getParamStr(writer, constants, body, abc, fullyQualifiedNames); + writer.appendNoHilight("):"); + methodInfo[methodIndex].getReturnTypeStr(writer, constants, fullyQualifiedNames); + writer.endMethod(); writer.newLine(); writer.append("{").newLine(); writer.indent(); - writer.appendNoHilight((writer.getIsHighlighted() ? functionBody : Highlighting.stripHilights(functionBody))); + if (body != null) { + try { + body.toString(path + "/inner", false, isStatic, scriptIndex, classIndex, abc, null, constants, methodInfo, new Stack()/*scopeStack*/, false, writer, fullyQualifiedNames, null); + } catch (Exception ex) { + Logger.getLogger(NewFunctionIns.class.getName()).log(Level.SEVERE, "error during newfunction", ex); + } + } writer.newLine(); writer.unindent(); writer.append("}"); diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/IsTypeAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/IsTypeAVM2Item.java index 60b67830d..930770697 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/IsTypeAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/IsTypeAVM2Item.java @@ -23,6 +23,6 @@ import com.jpexs.decompiler.graph.model.BinaryOpItem; public class IsTypeAVM2Item extends BinaryOpItem { public IsTypeAVM2Item(AVM2Instruction instruction, GraphTargetItem value, GraphTargetItem type) { - super(instruction, PRECEDENCE_RELATIONAL, value, type, " is "); + super(instruction, PRECEDENCE_RELATIONAL, value, type, "is"); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 6de396e59..fbdab1f35 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -25,7 +25,6 @@ import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.Traits; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.helpers.Helper; @@ -110,44 +109,48 @@ public class MethodBody implements Cloneable, Serializable { return ret; } - public String toString(final String path, boolean pcode, final boolean isStatic, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ConstantPool constants, final MethodInfo[] method_info, final Stack scopeStack, final boolean isStaticInitializer, final boolean hilight, final boolean replaceIndents, final List fullyQualifiedNames, final Traits initTraits) { + public HilightedTextWriter toString(final String path, boolean pcode, final boolean isStatic, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ConstantPool constants, final MethodInfo[] method_info, final Stack scopeStack, final boolean isStaticInitializer, final HilightedTextWriter writer, final List fullyQualifiedNames, final Traits initTraits) { if (debugMode) { System.err.println("Decompiling " + path); } - String s = ""; if (pcode) { - s += code.toASMSource(constants, trait, method_info[this.method_info], this, false, hilight); + writer.indent(); + code.toASMSource(constants, trait, method_info[this.method_info], this, false, writer); + writer.unindent(); } else { if (!Configuration.getConfig("decompile", true)) { - s = "//Decompilation skipped"; - if (hilight) { - s = Highlighting.hilighMethod(s, this.method_info); - } - return s; + writer.indent(); + writer.startMethod(this.method_info); + writer.appendNoHilight("//Decompilation skipped"); + writer.endMethod(); + writer.unindent(); + return writer; } + writer.indent(); int timeout = Configuration.getConfig("decompilationTimeoutSingleMethod", 60); + int writerPos = writer.getLength(); try { - s += Helper.timedCall(new Callable() { + Helper.timedCall(new Callable() { @Override - public String call() throws Exception { - HilightedTextWriter writer = new HilightedTextWriter(hilight); - toSource(path, isStatic, scriptIndex, classIndex, abc, trait, constants, method_info, scopeStack, isStaticInitializer, writer, replaceIndents, fullyQualifiedNames, initTraits); - String s = writer.toString(); - if (replaceIndents) { - s = Graph.removeNonRefenrencedLoopLabels(s); - } - return s; + public Void call() throws Exception { + toSource(path, isStatic, scriptIndex, classIndex, abc, trait, constants, method_info, scopeStack, isStaticInitializer, writer, fullyQualifiedNames, initTraits); + return null; } }, timeout, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException ex) { Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error", ex); - s += "/*\r\n * Decompilation error\r\n * Timeout (" + Helper.formatTimeToText(timeout) + ") was reached\r\n */"; + writer.setLength(writerPos); // remove already rendered code + writer.appendNoHilight("/*").newLine(); + writer.appendNoHilight(" * Decompilation error").newLine(); + writer.appendNoHilight(" * Timeout (" + Helper.formatTimeToText(timeout) + ") was reached").newLine(); + writer.appendNoHilight(" */"); } + writer.unindent(); } - return s; + return writer; } - public HilightedTextWriter toSource(String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, Trait trait, ConstantPool constants, MethodInfo[] method_info, Stack scopeStack, boolean isStaticInitializer, HilightedTextWriter writer, boolean replaceIndents, List fullyQualifiedNames, Traits initTraits) { + public HilightedTextWriter toSource(String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, Trait trait, ConstantPool constants, MethodInfo[] method_info, Stack scopeStack, boolean isStaticInitializer, HilightedTextWriter writer, List fullyQualifiedNames, Traits initTraits) { AVM2Code deobfuscated = null; MethodBody b = (MethodBody) Helper.deepCopy(this); deobfuscated = b.code; @@ -162,7 +165,7 @@ public class MethodBody implements Cloneable, Serializable { //deobfuscated.restoreControlFlow(constants, b); writer.startMethod(this.method_info); - deobfuscated.toSource(path, isStatic, scriptIndex, classIndex, abc, constants, method_info, b, writer, replaceIndents, getLocalRegNames(abc), scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap(), deobfuscated.visitCode(b)); + deobfuscated.toSource(path, isStatic, scriptIndex, classIndex, abc, constants, method_info, b, writer, getLocalRegNames(abc), scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap(), deobfuscated.visitCode(b)); writer.endMethod(); return writer; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java index 7c645c933..4752dcb27 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java @@ -19,7 +19,7 @@ package com.jpexs.decompiler.flash.abc.types; import com.jpexs.decompiler.flash.Configuration; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.ConstantPool; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.helpers.Helper; import java.util.HashMap; import java.util.List; @@ -242,33 +242,33 @@ public class MethodInfo { return constants.constant_string[name_index]; } - public String getParamStr(boolean highlight, ConstantPool constants, MethodBody body, ABC abc, List fullyQualifiedNames) { + public HilightedTextWriter getParamStr(HilightedTextWriter writer, ConstantPool constants, MethodBody body, ABC abc, List fullyQualifiedNames) { HashMap localRegNames = new HashMap<>(); if (body != null) { localRegNames = body.code.getLocalRegNamesFromDebug(abc); } - String paramStr = ""; for (int i = 0; i < param_types.length; i++) { if (i > 0) { - paramStr += ", "; + writer.appendNoHilight(", "); } if (!localRegNames.isEmpty()) { - paramStr += localRegNames.get(i + 1); + writer.appendNoHilight(localRegNames.get(i + 1)); } else if ((paramNames.length > i) && (paramNames[i] != 0) && Configuration.PARAM_NAMES_ENABLE) { - paramStr += constants.constant_string[paramNames[i]]; + writer.appendNoHilight(constants.constant_string[paramNames[i]]); } else { - paramStr += "param" + (i + 1); + writer.appendNoHilight("param" + (i + 1)); } - paramStr += ":"; + writer.appendNoHilight(":"); if (param_types[i] == 0) { - paramStr += Highlighting.hilighSpecial(highlight, "*", "param", i); + writer.hilightSpecial("*", "param", i); } else { - paramStr += Highlighting.hilighSpecial(highlight, constants.constant_multiname[param_types[i]].getName(constants, fullyQualifiedNames), "param", i); + writer.hilightSpecial(constants.constant_multiname[param_types[i]].getName(constants, fullyQualifiedNames), "param", i); } if (optional != null) { if (i >= param_types.length - optional.length) { int optionalIndex = i - (param_types.length - optional.length); - paramStr += "=" + Highlighting.hilighSpecial(highlight, optional[optionalIndex].toString(constants), "optional", optionalIndex); + writer.appendNoHilight("="); + writer.hilightSpecial(optional[optionalIndex].toString(constants), "optional", optionalIndex); } } } @@ -283,16 +283,13 @@ public class MethodInfo { } else { restAdd += "rest"; } - paramStr += Highlighting.hilighSpecial(highlight, restAdd, "flag.NEED_REST"); + writer.hilightSpecial(restAdd, "flag.NEED_REST"); } - return paramStr; + return writer; } - public String getReturnTypeStr(boolean highlight, ConstantPool constants, List fullyQualifiedNames) { - if (ret_type == 0) { - return Highlighting.hilighSpecial(highlight, "*", "returns"); - } - return Highlighting.hilighSpecial(highlight, constants.constant_multiname[ret_type].getName(constants, fullyQualifiedNames), "returns"); + public HilightedTextWriter getReturnTypeStr(HilightedTextWriter writer, ConstantPool constants, List fullyQualifiedNames) { + return writer.hilightSpecial(ret_type == 0 ? "*" : constants.constant_multiname[ret_type].getName(constants, fullyQualifiedNames), "returns"); } public void setBody(MethodBody body) { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java index 671f7633f..920dc6aca 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.abc.ClassPath; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.helpers.collections.MyEntry; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import java.util.ArrayList; @@ -79,7 +80,7 @@ public class ScriptInfo { return "method_index=" + init_index + "\r\n" + traits.toString(abc, fullyQualifiedNames); } - public String convert(List abcTags, ABC abc, boolean pcode, boolean highlighting, int scriptIndex, boolean parallel) { - return traits.convert(null, "", abcTags, abc, false, pcode, true, scriptIndex, -1, highlighting, new ArrayList(), parallel); + public HilightedTextWriter convert(List abcTags, ABC abc, boolean pcode, HilightedTextWriter writer, int scriptIndex, boolean parallel) { + return traits.convert(null, "", abcTags, abc, false, pcode, true, scriptIndex, -1, writer, new ArrayList(), parallel); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index 87ef856cb..d36e5d27e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -19,7 +19,9 @@ package com.jpexs.decompiler.flash.abc.types.traits; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.graph.Graph; import com.jpexs.helpers.Helper; import java.io.File; import java.io.FileOutputStream; @@ -113,25 +115,29 @@ public abstract class Trait implements Serializable { return abc.constants.constant_multiname[name_index].toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); } - public String convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, boolean highlight, List fullyQualifiedNames, boolean parallel) { - return abc.constants.constant_multiname[name_index].toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); + public HilightedTextWriter convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { + writer.appendNoHilight(abc.constants.constant_multiname[name_index].toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata)); + return writer; } - public String convertPackaged(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcod, int scriptIndex, int classIndex, boolean highlight, List fullyQualifiedNames, boolean parallel) { - return makePackageFromIndex(abc, name_index, convert(parent, path, abcTags, abc, isStatic, pcod, scriptIndex, classIndex, highlight, fullyQualifiedNames, parallel)); - } - - public String convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, boolean highlight, List fullyQualifiedNames, boolean parallel) { - return convert(parent, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, highlight, fullyQualifiedNames, parallel).trim(); - } - - protected String makePackageFromIndex(ABC abc, int name_index, String value) { + public HilightedTextWriter convertPackaged(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcod, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { Namespace ns = abc.constants.constant_multiname[name_index].getNamespace(abc.constants); if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { String nsname = ns.getName(abc.constants); - return "package " + nsname + "\r\n{\r\n" + value + "\r\n}"; + writer.appendNoHilight("package " + nsname).newLine(); + writer.appendNoHilight("{").newLine(); + writer.indent(); + convert(parent, path, abcTags, abc, isStatic, pcod, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + writer.newLine(); + writer.unindent(); + writer.appendNoHilight("}"); } - return value; + return writer; + } + + public HilightedTextWriter convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { + convert(parent, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + return writer; } public Multiname getName(ABC abc) { @@ -167,7 +173,10 @@ public abstract class Trait implements Serializable { } String fileName = outDir.toString() + File.separator + objectName + ".as"; try (FileOutputStream fos = new FileOutputStream(fileName)) { - fos.write(convertPackaged(parent, "", abcList, abc, isStatic, pcode, scriptIndex, classIndex, false, new ArrayList(), parallel).getBytes()); + HilightedTextWriter writer = new HilightedTextWriter(false); + convertPackaged(parent, "", abcList, abc, isStatic, pcode, scriptIndex, classIndex, writer, new ArrayList(), parallel); + String s = Graph.removeNonRefenrencedLoopLabels(writer.toString()); + fos.write(s.getBytes()); } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index 80c53f7d8..fcb237904 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -32,19 +32,12 @@ import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.NamespaceSet; import com.jpexs.decompiler.flash.abc.types.ScriptInfo; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.helpers.Helper; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import java.util.Stack; -import java.util.logging.Level; -import java.util.logging.Logger; public class TraitClass extends Trait implements TraitWithSlot { @@ -329,26 +322,15 @@ public class TraitClass extends Trait implements TraitWithSlot { } @Override - public String convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, boolean highlight, List fullyQualifiedNames, boolean parallel) { + public HilightedTextWriter convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { String classHeader = abc.instance_info[class_info].getClassHeaderStr(abc, fullyQualifiedNames); - return classHeader; + return writer.appendNoHilight(classHeader); } @Override - public String convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, boolean highlight, List fullyQualifiedNames, boolean parallel) { - - if (!highlight) { - //Highlighting.doHighlight = false; - } - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PrintStream out = null; - try { - out = new PrintStream(baos, true, "UTF-8"); - } catch (UnsupportedEncodingException ex) { - Logger.getLogger(TraitClass.class.getName()).log(Level.SEVERE, null, ex); - return ""; - } + public HilightedTextWriter convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { + writer.startClass(class_info); String packageName = abc.instance_info[class_info].getName(abc.constants).getNamespace(abc.constants).getName(abc.constants); List namesInThisPackage = new ArrayList<>(); for (ABCContainerTag tag : abcTags) { @@ -420,43 +402,41 @@ public class TraitClass extends Trait implements TraitWithSlot { for (String imp : imports) { if (!imp.startsWith(".")) { - out.println(HilightedTextWriter.INDENT_STRING + "import " + imp + ";"); + writer.appendNoHilight("import " + imp + ";").newLine(); } } - out.println(); + writer.newLine(); for (String us : uses) { - out.println(HilightedTextWriter.INDENT_STRING + "use namespace " + us + ";"); + writer.appendNoHilight("use namespace " + us + ";").newLine(); } - out.println(); + writer.newLine(); //class header String classHeader = abc.instance_info[class_info].getClassHeaderStr(abc, fullyQualifiedNames); if (classHeader.startsWith("private ")) { classHeader = classHeader.substring("private ".length()); } - out.println(HilightedTextWriter.INDENT_STRING + classHeader); - out.println(HilightedTextWriter.INDENT_STRING + "{"); + writer.appendNoHilight(classHeader).newLine(); + writer.appendNoHilight("{").newLine(); + writer.indent(); - String toPrint; - List outTraits = new LinkedList<>(); - - - int bodyIndex; - String bodyStr = ""; - bodyIndex = abc.findBodyIndex(abc.class_info[class_info].cinit_index); + int bodyIndex = abc.findBodyIndex(abc.class_info[class_info].cinit_index); if (bodyIndex != -1) { - bodyStr = abc.bodies[bodyIndex].toString(path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames) + ".staticinitializer", pcode, true, scriptIndex, class_info, abc, this, abc.constants, abc.method_info, new Stack(), true, highlight, true, fullyQualifiedNames, abc.class_info[class_info].static_traits); - } - if (Highlighting.stripHilights(bodyStr).trim().equals("")) { - toPrint = ABC.addTabs(bodyStr + "/*classInitializer*/", 3); + int writerPos = writer.getLength(); + writer.startTrait(abc.class_info[class_info].static_traits.traits.length + abc.instance_info[class_info].instance_traits.traits.length + 1); + writer.appendNoHilight("{").newLine(); + writer.mark(); + abc.bodies[bodyIndex].toString(path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames) + ".staticinitializer", pcode, true, scriptIndex, class_info, abc, this, abc.constants, abc.method_info, new Stack(), true, writer, fullyQualifiedNames, abc.class_info[class_info].static_traits); + boolean empty = !writer.getMark(); + writer.appendNoHilight("}").newLine(); + writer.endTrait(); + writer.newLine(); + if (empty) { + writer.setLength(writerPos); + } } else { - toPrint = HilightedTextWriter.INDENT_STRING + HilightedTextWriter.INDENT_STRING + "{\r\n" + ABC.addTabs(bodyStr, 3) + "\r\n" + HilightedTextWriter.INDENT_STRING + HilightedTextWriter.INDENT_STRING + "}"; + //"/*classInitializer*/"; } - if (highlight) { - toPrint = Highlighting.hilighTrait(toPrint, abc.class_info[class_info].static_traits.traits.length + abc.instance_info[class_info].instance_traits.traits.length + 1); - } - outTraits.add(toPrint); - //} //constructor if (!abc.instance_info[class_info].isInterface()) { @@ -474,68 +454,36 @@ public class TraitClass extends Trait implements TraitWithSlot { } } } - String constructorParams; - bodyStr = ""; + writer.startTrait(abc.class_info[class_info].static_traits.traits.length + abc.instance_info[class_info].instance_traits.traits.length); + writer.appendNoHilight(modifier); + writer.appendNoHilight("function "); + writer.appendNoHilight(abc.constants.constant_multiname[abc.instance_info[class_info].name_index].getName(abc.constants, new ArrayList()/*do not want full names here*/)); + writer.appendNoHilight("("); bodyIndex = abc.findBodyIndex(abc.instance_info[class_info].iinit_index); if (bodyIndex != -1) { - bodyStr = ABC.addTabs(abc.bodies[bodyIndex].toString(path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames) + ".initializer", pcode, false, scriptIndex, class_info, abc, this, abc.constants, abc.method_info, new Stack(), false, highlight, true, fullyQualifiedNames, abc.instance_info[class_info].instance_traits), 3); - constructorParams = abc.method_info[abc.instance_info[class_info].iinit_index].getParamStr(highlight, abc.constants, abc.bodies[bodyIndex], abc, fullyQualifiedNames); + abc.method_info[abc.instance_info[class_info].iinit_index].getParamStr(writer, abc.constants, abc.bodies[bodyIndex], abc, fullyQualifiedNames); } else { - constructorParams = abc.method_info[abc.instance_info[class_info].iinit_index].getParamStr(highlight, abc.constants, null, abc, fullyQualifiedNames); + abc.method_info[abc.instance_info[class_info].iinit_index].getParamStr(writer, abc.constants, null, abc, fullyQualifiedNames); } - toPrint = HilightedTextWriter.INDENT_STRING + HilightedTextWriter.INDENT_STRING + modifier + "function " + abc.constants.constant_multiname[abc.instance_info[class_info].name_index].getName(abc.constants, new ArrayList()/*do not want full names here*/) + "(" + constructorParams + ") {\r\n" + bodyStr + "\r\n" + HilightedTextWriter.INDENT_STRING + HilightedTextWriter.INDENT_STRING + "}"; - if (highlight) { - toPrint = Highlighting.hilighTrait(toPrint, abc.class_info[class_info].static_traits.traits.length + abc.instance_info[class_info].instance_traits.traits.length); + writer.appendNoHilight(") {").newLine(); + if (bodyIndex != -1) { + abc.bodies[bodyIndex].toString(path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames) + ".initializer", pcode, false, scriptIndex, class_info, abc, this, abc.constants, abc.method_info, new Stack(), false, writer, fullyQualifiedNames, abc.instance_info[class_info].instance_traits); } - outTraits.add(toPrint); + writer.appendNoHilight("}").newLine(); + writer.endTrait(); + writer.newLine(); } - //} //static variables,constants & methods - outTraits.add(abc.class_info[class_info].static_traits.convert(this, path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames), abcTags, abc, true, pcode, false, scriptIndex, class_info, highlight, fullyQualifiedNames, parallel)); + abc.class_info[class_info].static_traits.convert(this, path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames), abcTags, abc, true, pcode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel); - outTraits.add(abc.instance_info[class_info].instance_traits.convert(this, path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames), abcTags, abc, false, pcode, false, scriptIndex, class_info, highlight, fullyQualifiedNames, parallel)); + abc.instance_info[class_info].instance_traits.convert(this, path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames), abcTags, abc, false, pcode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel); - - StringBuilder bui = new StringBuilder(); - boolean first = true; - String glue = "\r\n\r\n"; - for (String s : outTraits) { - String stripped = highlight ? Highlighting.stripHilights(s) : s; - if (!stripped.trim().equals("")) { - if (s.contains("/*classInitializer*/")) { - s = s.replace("/*classInitializer*/", ""); - s = s + "\r\n"; - } else { - if (!first) { - bui.append(glue); - } else { - first = false; - } - } - } else { - s = s.replace(HilightedTextWriter.INDENT_STRING, ""); - } - bui.append(s); - } - - - //out.println(Helper.joinStrings(outTraits, "\r\n\r\n")); - out.println(bui.toString()); - out.println(HilightedTextWriter.INDENT_STRING + "}");//class - out.flush(); - //Highlighting.doHighlight = true; - try { - if (highlight) { - return Highlighting.hilighClass(new String(baos.toByteArray(), "UTF-8"), class_info); - } else { - return new String(baos.toByteArray(), "UTF-8"); - } - } catch (UnsupportedEncodingException ex) { - Logger.getLogger(TraitClass.class.getName()).log(Level.SEVERE, null, ex); - return ""; - } + writer.unindent(); + writer.appendNoHilight("}"); // class + writer.endClass(); + return writer; } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java index d8d561923..a00c19856 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java @@ -19,7 +19,6 @@ package com.jpexs.decompiler.flash.abc.types.traits; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.helpers.Helper; @@ -42,7 +41,7 @@ public class TraitFunction extends Trait implements TraitWithSlot { } @Override - public String convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, boolean highlight, List fullyQualifiedNames, boolean parallel) { + public HilightedTextWriter convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { String modifier = getModifiers(abcTags, abc, isStatic) + " "; MethodBody body = abc.findBody(method_info); if (body == null) { @@ -51,19 +50,31 @@ public class TraitFunction extends Trait implements TraitWithSlot { if (modifier.equals(" ")) { modifier = ""; } - return modifier + Highlighting.hilighSpecial(highlight, "function ", "traittype") + Highlighting.hilighSpecial(highlight, abc.constants.constant_multiname[name_index].getName(abc.constants, fullyQualifiedNames), "traitname") + "(" + abc.method_info[method_info].getParamStr(highlight, abc.constants, body, abc, fullyQualifiedNames) + ") : " + abc.method_info[method_info].getReturnTypeStr(highlight, abc.constants, fullyQualifiedNames); + writer.appendNoHilight(modifier); + writer.hilightSpecial("function ", "traittype"); + writer.hilightSpecial(abc.constants.constant_multiname[name_index].getName(abc.constants, fullyQualifiedNames), "traitname"); + writer.appendNoHilight("("); + abc.method_info[method_info].getParamStr(writer, abc.constants, body, abc, fullyQualifiedNames); + writer.appendNoHilight(") : "); + abc.method_info[method_info].getReturnTypeStr(writer, abc.constants, fullyQualifiedNames); + return writer; } @Override - public String convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, boolean highlight, List fullyQualifiedNames, boolean parallel) { - String header = convertHeader(parent, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, highlight, fullyQualifiedNames, parallel); - String bodyStr = ""; - int bodyIndex = abc.findBodyIndex(method_info); - if (bodyIndex != -1) { - bodyStr = ABC.addTabs(abc.bodies[bodyIndex].toString(path + "." + abc.constants.constant_multiname[name_index].getName(abc.constants, fullyQualifiedNames), pcode, isStatic, scriptIndex, classIndex, abc, this, abc.constants, abc.method_info, new Stack(), false, highlight, true, fullyQualifiedNames, null), 3); + public HilightedTextWriter convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { + convertHeader(parent, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + if (abc.instance_info[classIndex].isInterface()) { + writer.appendNoHilight(";"); + } else { + writer.appendNoHilight(" {").newLine(); + int bodyIndex = abc.findBodyIndex(method_info); + if (bodyIndex != -1) { + abc.bodies[bodyIndex].toString(path + "." + abc.constants.constant_multiname[name_index].getName(abc.constants, fullyQualifiedNames), pcode, isStatic, scriptIndex, classIndex, abc, this, abc.constants, abc.method_info, new Stack(), false, writer, fullyQualifiedNames, null); + } + writer.newLine(); + writer.appendNoHilight("}"); } - return HilightedTextWriter.INDENT_STRING + HilightedTextWriter.INDENT_STRING + header + (abc.instance_info[classIndex].isInterface() ? ";" : " {\r\n" + bodyStr + "\r\n" + HilightedTextWriter.INDENT_STRING + HilightedTextWriter.INDENT_STRING + "}"); - + return writer; } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java index 6dbff8d65..a0abbe34e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java @@ -19,7 +19,6 @@ package com.jpexs.decompiler.flash.abc.types.traits; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.helpers.Helper; @@ -37,7 +36,7 @@ public class TraitMethodGetterSetter extends Trait { } @Override - public String convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, boolean highlight, List fullyQualifiedNames, boolean parallel) { + public HilightedTextWriter convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { String modifier = getModifiers(abcTags, abc, isStatic) + " "; if (modifier.equals(" ")) { modifier = ""; @@ -55,19 +54,30 @@ public class TraitMethodGetterSetter extends Trait { modifier = "native " + modifier; } - return modifier + Highlighting.hilighSpecial(highlight, "function " + addKind, "traittype") + Highlighting.hilighSpecial(highlight, getName(abc).getName(abc.constants, fullyQualifiedNames), "traitname") + "(" + abc.method_info[method_info].getParamStr(highlight, abc.constants, body, abc, fullyQualifiedNames) + ") : " + abc.method_info[method_info].getReturnTypeStr(highlight, abc.constants, fullyQualifiedNames); - + writer.appendNoHilight(modifier); + writer.hilightSpecial("function " + addKind, "traittype"); + writer.hilightSpecial(getName(abc).getName(abc.constants, fullyQualifiedNames), "traitname"); + writer.appendNoHilight("("); + abc.method_info[method_info].getParamStr(writer, abc.constants, body, abc, fullyQualifiedNames); + writer.appendNoHilight(") : "); + abc.method_info[method_info].getReturnTypeStr(writer, abc.constants, fullyQualifiedNames); + return writer; } @Override - public String convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, boolean highlight, List fullyQualifiedNames, boolean parallel) { - String header = convertHeader(parent, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, highlight, fullyQualifiedNames, parallel); - String bodyStr = ""; + public HilightedTextWriter convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { + convertHeader(parent, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); int bodyIndex = abc.findBodyIndex(method_info); - if (bodyIndex != -1) { - bodyStr = ABC.addTabs(abc.bodies[bodyIndex].toString(path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames), pcode, isStatic, scriptIndex, classIndex, abc, this, abc.constants, abc.method_info, new Stack(), false, highlight, true, fullyQualifiedNames, null), 3); + if (classIndex != -1 && abc.instance_info[classIndex].isInterface() || bodyIndex == -1) { + writer.appendNoHilight(";"); + } else { + writer.appendNoHilight(" {").newLine(); + if (bodyIndex != -1) { + abc.bodies[bodyIndex].toString(path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames), pcode, isStatic, scriptIndex, classIndex, abc, this, abc.constants, abc.method_info, new Stack(), false, writer, fullyQualifiedNames, null); + } + writer.appendNoHilight("}"); } - return HilightedTextWriter.INDENT_STRING + HilightedTextWriter.INDENT_STRING + header + ((classIndex != -1 && abc.instance_info[classIndex].isInterface() || bodyIndex == -1) ? ";" : " {\r\n" + bodyStr + "\r\n" + HilightedTextWriter.INDENT_STRING + HilightedTextWriter.INDENT_STRING + "}"); + return writer; } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java index 04f28d339..5aaaf1c97 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java @@ -22,9 +22,7 @@ import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.ValueKind; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.helpers.Helper; @@ -61,7 +59,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { return typeStr; } - public String getNameStr(boolean highlight, ABC abc, List fullyQualifiedNames) { + public HilightedTextWriter getNameStr(HilightedTextWriter writer, ABC abc, List fullyQualifiedNames) { String typeStr = getType(abc.constants, fullyQualifiedNames); if (typeStr.equals("*")) { typeStr = ""; @@ -80,36 +78,49 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { if (val != null && val.isNamespace()) { slotconst = "namespace"; } - return Highlighting.hilighSpecial(highlight, slotconst, "traittype") + " " + Highlighting.hilighSpecial(highlight, getName(abc).getName(abc.constants, fullyQualifiedNames), "traitname") + Highlighting.hilighSpecial(highlight, typeStr, "traittypename"); - + writer.hilightSpecial(slotconst + " ", "traittype"); + writer.hilightSpecial(getName(abc).getName(abc.constants, fullyQualifiedNames), "traitname"); + writer.hilightSpecial(typeStr, "traittypename"); + return writer; } - public String getValueStr(Trait parent, boolean highlight, ABC abc, List fullyQualifiedNames) { - String valueStr = null; - ValueKind val = null; - if (value_kind != 0) { - val = new ValueKind(value_index, value_kind); - valueStr = val.toString(abc.constants); - valueStr = Highlighting.hilighSpecial(highlight, valueStr, "traitvalue"); - } - + public boolean getValueStr(Trait parent, HilightedTextWriter writer, ABC abc, List fullyQualifiedNames) { if (assignedValue != null) { - valueStr = Highlighting.trim(assignedValue.toString(highlight, LocalData.create(abc.constants, new HashMap(), fullyQualifiedNames))); - if (highlight && (parent instanceof TraitClass)) { + if (parent instanceof TraitClass) { TraitClass tc = (TraitClass) parent; int traitInitId = abc.class_info[tc.class_info].static_traits.traits.length + abc.instance_info[tc.class_info].instance_traits.traits.length + 1; int initMethod = abc.class_info[tc.class_info].cinit_index; - valueStr = Highlighting.hilighMethod(valueStr, initMethod); - valueStr = Highlighting.hilighTrait(valueStr, traitInitId); + writer.startTrait(traitInitId); + writer.startMethod(initMethod); } + assignedValue.toString(writer, LocalData.create(abc.constants, new HashMap(), fullyQualifiedNames)); + if (parent instanceof TraitClass) { + writer.endMethod(); + writer.endTrait(); + } + return true; } - return valueStr; + + if (value_kind != 0) { + ValueKind val = new ValueKind(value_index, value_kind); + writer.hilightSpecial(val.toString(abc.constants), "traitvalue"); + return true; + } + + return false; } public String getNameValueStr(Trait parent, ABC abc, List fullyQualifiedNames) { - String valueStr = getValueStr(parent, false, abc, fullyQualifiedNames); - return getNameStr(false, abc, fullyQualifiedNames) + (valueStr == null ? "" : " = " + valueStr) + ";"; + HilightedTextWriter writer = new HilightedTextWriter(false); + getNameStr(writer, abc, fullyQualifiedNames); + writer.appendNoHilight(" = "); + boolean hasValue = getValueStr(parent, writer, abc, fullyQualifiedNames); + if (!hasValue) { + writer.removeFromEnd(3); + } + writer.appendNoHilight(";"); + return writer.toString(); } public boolean isNamespace() { @@ -121,7 +132,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { } @Override - public String convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, boolean highlight, List fullyQualifiedNames, boolean parallel) { + public HilightedTextWriter convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { String modifier = getModifiers(abcTags, abc, isStatic) + " "; if (modifier.equals(" ")) { modifier = ""; @@ -141,44 +152,14 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { if (!showModifier) { modifier = ""; } - String ret = modifier + getNameStr(highlight, abc, fullyQualifiedNames); - String valueStr = getValueStr(parent, highlight, abc, fullyQualifiedNames); - - if (valueStr != null) { - ret += " = "; - int befLen = Highlighting.stripHilights(HilightedTextWriter.INDENT_STRING + HilightedTextWriter.INDENT_STRING + ret).length(); - String[] valueStrParts = valueStr.split("\r\n"); - boolean first = true; - for (int i = 0; i < valueStrParts.length; i++) { - if (valueStrParts[i].equals("")) { - continue; - } - if (Highlighting.stripHilights(valueStrParts[i]).equals(Graph.INDENTOPEN)) { - if (!first) { - befLen += HilightedTextWriter.INDENT_STRING.length(); - } - ret += valueStrParts[i].replace(Graph.INDENTOPEN, ""); //there can be highlights! - continue; - } - if (Highlighting.stripHilights(valueStrParts[i]).equals(Graph.INDENTCLOSE)) { - if (!first) { - befLen -= HilightedTextWriter.INDENT_STRING.length(); - } - ret += valueStrParts[i].replace(Graph.INDENTCLOSE, ""); //there can be highlights! - continue; - } - if (!first) { - for (int j = 0; j < befLen; j++) { - ret += " "; - } - } - ret += valueStrParts[i]; - ret += "\r\n"; - first = false; - } + writer.appendNoHilight(modifier); + getNameStr(writer, abc, fullyQualifiedNames); + writer.appendNoHilight(" = "); + boolean hasValue = getValueStr(parent, writer, abc, fullyQualifiedNames); + if (!hasValue) { + writer.removeFromEnd(3); } - ret = HilightedTextWriter.INDENT_STRING + HilightedTextWriter.INDENT_STRING + Highlighting.trim(ret) + ";"; - return ret; + return writer.appendNoHilight(";"); } public boolean isConst() { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java index 0d859ff58..df076baa0 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.abc.types.traits; import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import java.io.Serializable; import java.util.ArrayList; @@ -83,13 +83,13 @@ public class Traits implements Serializable { boolean pcode; int scriptIndex; int classIndex; - boolean highlighting; + HilightedTextWriter writer; List fullyQualifiedNames; int traitIndex; boolean parallel; Trait parent; - public TraitConvertTask(Trait trait, Trait parent, boolean makePackages, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, boolean highlighting, List fullyQualifiedNames, int traitIndex, boolean parallel) { + public TraitConvertTask(Trait trait, Trait parent, boolean makePackages, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, int traitIndex, boolean parallel) { this.trait = trait; this.parent = parent; this.makePackages = makePackages; @@ -100,7 +100,7 @@ public class Traits implements Serializable { this.pcode = pcode; this.scriptIndex = scriptIndex; this.classIndex = classIndex; - this.highlighting = highlighting; + this.writer = writer; this.fullyQualifiedNames = fullyQualifiedNames; this.traitIndex = traitIndex; this.parallel = parallel; @@ -108,31 +108,32 @@ public class Traits implements Serializable { @Override public String call() { - String plus; - if (makePackages) { - plus = trait.convertPackaged(parent, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, highlighting, fullyQualifiedNames, parallel); + int h = traitIndex; + if (classIndex != -1) { + if (!isStatic) { + h = h + abc.class_info[classIndex].static_traits.traits.length; + } + } + if (trait instanceof TraitClass) { + writer.startClass(((TraitClass) trait).class_info); } else { - plus = trait.convert(parent, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, highlighting, fullyQualifiedNames, parallel); + writer.startTrait(h); } - if (highlighting) { - int h = traitIndex; - if (classIndex != -1) { - if (!isStatic) { - h = h + abc.class_info[classIndex].static_traits.traits.length; - } - } - if (trait instanceof TraitClass) { - plus = Highlighting.hilighClass(plus, ((TraitClass) trait).class_info); - } else { - plus = Highlighting.hilighTrait(plus, h); - } + if (makePackages) { + trait.convertPackaged(parent, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + } else { + trait.convert(parent, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); } - return plus; + if (trait instanceof TraitClass) { + writer.endClass(); + } else { + writer.endTrait(); + } + return writer.toString(); } } - public String convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, boolean makePackages, int scriptIndex, int classIndex, boolean highlighting, List fullyQualifiedNames, boolean parallel) { - StringBuilder sb = new StringBuilder(); + public HilightedTextWriter convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, boolean makePackages, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { ExecutorService executor = null; List> futureResults = null; List traitConvertTasks = null; @@ -144,7 +145,8 @@ public class Traits implements Serializable { traitConvertTasks = new ArrayList<>(); } for (int t = 0; t < traits.length; t++) { - TraitConvertTask task = new TraitConvertTask(traits[t], parent, makePackages, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, highlighting, fullyQualifiedNames, t, parallel); + HilightedTextWriter writer2 = new HilightedTextWriter(writer.getIsHighlighted(), writer.getIndent()); + TraitConvertTask task = new TraitConvertTask(traits[t], parent, makePackages, path, abcTags, abc, isStatic, pcode, scriptIndex, classIndex, writer2, fullyQualifiedNames, t, parallel); if (parallel) { Future future = executor.submit(task); futureResults.add(future); @@ -156,11 +158,11 @@ public class Traits implements Serializable { int taskCount = parallel ? futureResults.size() : traitConvertTasks.size(); for (int f = 0; f < taskCount; f++) { if (f > 0) { - sb.append("\r\n\r\n"); + writer.newLine(); } try { String taskResult = parallel ? futureResults.get(f).get() : traitConvertTasks.get(f).call(); - sb.append(taskResult); + writer.appendWithoutIndent(taskResult); } catch (InterruptedException | ExecutionException ex) { Logger.getLogger(Traits.class.getName()).log(Level.SEVERE, "Error during traits converting", ex); } @@ -168,6 +170,6 @@ public class Traits implements Serializable { if (parallel) { executor.shutdown(); } - return sb.toString(); + return writer; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java b/trunk/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java index 7c2a36f70..1f49f9bbb 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import java.util.ArrayList; import java.util.List; @@ -36,13 +37,17 @@ public abstract class ConstVarMultinameUsage extends TraitMultinameUsage { @Override public String toString(List abcTags, ABC abc) { - return super.toString(abcTags, abc) + " " - + (parentTraitIndex > -1 - ? (isStatic - ? (((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, false, new ArrayList(), false)) - : (((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, false, new ArrayList(), false))) - : "") - + ((TraitSlotConst) traits.traits[traitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, false, new ArrayList(), false); + HilightedTextWriter writer = new HilightedTextWriter(false); + writer.appendNoHilight(super.toString(abcTags, abc) + " "); + if (parentTraitIndex > -1) { + if (isStatic) { + ((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, writer, new ArrayList(), false); + } else { + ((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, writer, new ArrayList(), false); + } + } + ((TraitSlotConst) traits.traits[traitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, writer, new ArrayList(), false); + return writer.toString(); } public int getTraitIndex() { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java b/trunk/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java index 1eb5ddab0..c054453e3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.usages; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import java.util.ArrayList; import java.util.List; @@ -42,16 +43,27 @@ public abstract class MethodMultinameUsage extends TraitMultinameUsage { @Override public String toString(List abcTags, ABC abc) { - return super.toString(abcTags, abc) + " " + (isInitializer - ? (isStatic - ? "class initializer" - : "instance initializer") - : ((parentTraitIndex > -1 - ? (isStatic - ? (((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, false, new ArrayList(), false)) - : (((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, false, new ArrayList(), false))) + " " - : "") - + (((TraitMethodGetterSetter) traits.traits[traitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, false, new ArrayList(), false)))); + HilightedTextWriter writer = new HilightedTextWriter(false); + writer.appendNoHilight(super.toString(abcTags, abc)); + writer.appendNoHilight(" "); + if (isInitializer) { + if (isStatic) { + writer.appendNoHilight("class initializer"); + } else { + writer.appendNoHilight("instance initializer"); + } + } else { + if (parentTraitIndex > -1) { + if (isStatic){ + ((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, writer, new ArrayList(), false); + } else { + ((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, writer, new ArrayList(), false); + } + writer.appendNoHilight(" "); + } + ((TraitMethodGetterSetter) traits.traits[traitIndex]).convertHeader(null, "", abcTags, abc, isStatic, false, -1/*FIXME*/, classIndex, writer, new ArrayList(), false); + } + return writer.toString(); } public int getTraitIndex() { diff --git a/trunk/src/com/jpexs/decompiler/flash/action/Action.java b/trunk/src/com/jpexs/decompiler/flash/action/Action.java index 9515b04d6..8d8d42154 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/Action.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/Action.java @@ -49,7 +49,6 @@ import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; import com.jpexs.decompiler.flash.ecma.Null; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.helpers.collections.MyEntry; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphSource; import com.jpexs.decompiler.graph.GraphSourceItem; @@ -394,10 +393,10 @@ public class Action implements GraphSourceItem { * @param hex Add hexadecimal? * @param swfPos * @param path - * @return ASM source as String + * @return HilightedTextWriter */ - public static String actionsToString(List listeners, long address, List list, List importantOffsets, int version, boolean hex, boolean highlight, long swfPos, String path) { - return actionsToString(listeners, address, list, importantOffsets, new ArrayList(), version, hex, highlight, swfPos, path); + public static HilightedTextWriter actionsToString(List listeners, long address, List list, List importantOffsets, int version, boolean hex, HilightedTextWriter writer, long swfPos, String path) { + return actionsToString(listeners, address, list, importantOffsets, new ArrayList(), version, hex, writer, swfPos, path); } /** @@ -412,9 +411,9 @@ public class Action implements GraphSourceItem { * @param hex Add hexadecimal? * @param swfPos * @param path - * @return ASM source as String + * @return HilightedTextWriter */ - private static String actionsToString(List listeners, long address, List list, List importantOffsets, List constantPool, int version, boolean hex, boolean highlight, long swfPos, String path) { + private static HilightedTextWriter actionsToString(List listeners, long address, List list, List importantOffsets, List constantPool, int version, boolean hex, HilightedTextWriter writer, long swfPos, String path) { long offset; if (importantOffsets == null) { //setActionsAddresses(list, 0, version); @@ -429,7 +428,6 @@ public class Action implements GraphSourceItem { offset = address; int pos = -1; boolean lastPush = false; - StringBuilder ret = new StringBuilder(); for (GraphSourceItem s : list) { for (int i = 0; i < listeners.size(); i++) { listeners.get(i).progress("toString", pos + 2, list.size()); @@ -441,12 +439,12 @@ public class Action implements GraphSourceItem { pos++; if (hex) { if (lastPush) { - ret.append("\r\n"); + writer.newLine(); lastPush = false; } - ret.append("");/* +"0x"+Helper.formatAddress(a.getFileAddress())+": "+*/; - ret.append(Helper.bytesToHexString(a.getBytes(version))); - ret.append("\r\n"); + writer.appendNoHilight("");/* +"0x"+Helper.formatAddress(a.getFileAddress())+": "+*/; + writer.appendNoHilight(Helper.bytesToHexString(a.getBytes(version))); + writer.appendNoHilight("").newLine(); } offset = a.getAddress(); @@ -469,10 +467,10 @@ public class Action implements GraphSourceItem { if (containers.containsKey(offset)) { for (int i = 0; i < containers.get(offset).size(); i++) { - ret.append("}\r\n"); + writer.appendNoHilight("}").newLine(); GraphSourceItemContainer cnt = containers.get(offset).get(i); int cntPos = containersPos.get(cnt); - ret.append(cnt.getASMSourceBetween(cntPos)); + writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); cntPos++; containersPos.put(cnt, cntPos); } @@ -480,27 +478,27 @@ public class Action implements GraphSourceItem { if (importantOffsets.contains(offset)) { if (lastPush) { - ret.append("\r\n"); + writer.newLine(); lastPush = false; } - ret.append("loc"); - ret.append(Helper.formatAddress(offset)); - ret.append(":"); + writer.appendNoHilight("loc"); + writer.appendNoHilight(Helper.formatAddress(offset)); + writer.appendNoHilight(":"); } if (a.replaceWith != null) { if (lastPush) { - ret.append("\r\n"); + writer.newLine(); lastPush = false; } - ret.append(highlight ? Highlighting.hilighOffset("", offset) : ""); - ret.append(a.replaceWith.getASMSource(list, importantOffsets, constantPool, version, hex)); - ret.append("\r\n"); + writer.append("", offset); + writer.appendNoHilight(a.replaceWith.getASMSource(list, importantOffsets, constantPool, version, hex)); + writer.newLine(); } else if (a.isIgnored()) { if (lastPush) { - ret.append("\r\n"); + writer.newLine(); lastPush = false; } int len = 0; @@ -511,17 +509,17 @@ public class Action implements GraphSourceItem { } if (!(a instanceof ActionEnd)) { for (int i = 0; i < len; i++) { - ret.append("Nop\r\n"); + writer.appendNoHilight("Nop").newLine(); } } } else { if (a.beforeInsert != null) { if (lastPush) { - ret.append("\r\n"); + writer.newLine(); lastPush = false; } - ret.append(a.beforeInsert.getASMSource(list, importantOffsets, constantPool, version, hex)); - ret.append("\r\n"); + writer.appendNoHilight(a.beforeInsert.getASMSource(list, importantOffsets, constantPool, version, hex)); + writer.newLine(); } //if (!(a instanceof ActionNop)) { String add = ""; @@ -534,16 +532,15 @@ public class Action implements GraphSourceItem { add = "; ofs" + Helper.formatAddress(offset) + add; add = ""; if ((a instanceof ActionPush) && lastPush) { - ret.append(" "); - ret.append(((ActionPush) a).paramsToStringReplaced(list, importantOffsets, constantPool, version, hex, highlight)); + writer.appendNoHilight(" "); + ((ActionPush) a).paramsToStringReplaced(list, importantOffsets, constantPool, version, hex, writer); } else { if (lastPush) { - ret.append("\r\n"); + writer.newLine(); lastPush = false; } - - ret.append(highlight ? Highlighting.hilighOffset("", offset) : ""); + writer.append("", offset); if (a instanceof ActionIf) { ActionIf aif = (ActionIf) a; @@ -558,20 +555,22 @@ public class Action implements GraphSourceItem { int fixBranch = a.getFixBranch(); if (fixBranch > -1) { if (a instanceof ActionIf) { - ret.append("ffdec_deobfuscatepop\r\n"); + writer.appendNoHilight("ffdec_deobfuscatepop").newLine(); if (fixBranch == 0) { //jump - ret.append("jump loc"); - ret.append(Helper.formatAddress(a.getAddress() + a.getBytes(version).length + ((ActionIf) a).getJumpOffset())); + writer.appendNoHilight("jump loc"); + writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getBytes(version).length + ((ActionIf) a).getJumpOffset())); } else { //nojump, ignore } } } else { - ret.append(a.getASMSourceReplaced(list, importantOffsets, constantPool, version, hex, highlight)); + a.getASMSourceReplaced(list, importantOffsets, constantPool, version, hex, writer); } - ret.append(a.isIgnored() ? "; ignored" : ""); - ret.append(add); - ret.append((a instanceof ActionPush) ? "" : "\r\n"); + writer.appendNoHilight(a.isIgnored() ? "; ignored" : ""); + writer.appendNoHilight(add); + if (!(a instanceof ActionPush)) { + writer.newLine(); + }; } if (a instanceof ActionPush) { lastPush = true; @@ -581,34 +580,36 @@ public class Action implements GraphSourceItem { //} if (a.afterInsert != null) { if (lastPush) { - ret.append("\r\n"); + writer.newLine(); lastPush = false; } - ret.append(a.afterInsert.getASMSource(list, importantOffsets, constantPool, version, hex)); - ret.append("\r\n"); + writer.appendNoHilight(a.afterInsert.getASMSource(list, importantOffsets, constantPool, version, hex)); + writer.newLine(); } } offset += a.getBytes(version).length; } if (lastPush) { - ret.append("\r\n"); + writer.newLine(); } if (containers.containsKey(offset)) { for (int i = 0; i < containers.get(offset).size(); i++) { - ret.append("}\r\n"); + writer.appendNoHilight("}"); + writer.newLine(); GraphSourceItemContainer cnt = containers.get(offset).get(i); int cntPos = containersPos.get(cnt); - ret.append(cnt.getASMSourceBetween(cntPos)); + writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); cntPos++; containersPos.put(cnt, cntPos); } } if (importantOffsets.contains(offset)) { - ret.append("loc"); - ret.append(Helper.formatAddress(offset)); - ret.append(":\r\n"); + writer.appendNoHilight("loc"); + writer.appendNoHilight(Helper.formatAddress(offset)); + writer.appendNoHilight(":"); + writer.newLine(); } - return ret.toString(); + return writer; } /** @@ -715,34 +716,58 @@ public class Action implements GraphSourceItem { * @param actions List of actions * @param version SWF version * @param path - * @return String with Source code + * @return HilightedTextWriter with Source code */ - public static String actionsToSource(final List actions, final int version, final String path, final boolean highlight) { + public static String actionsToSource(List actions, int version, String path, boolean highlight, int indent) { + HilightedTextWriter writer = new HilightedTextWriter(false, indent); + Action.actionsToSource(actions, SWF.DEFAULT_VERSION, ""/*FIXME*/, writer); + String s = Graph.removeNonRefenrencedLoopLabels(writer.toString()); + return s; + } + + /** + * Converts list of actions to ActionScript source code + * + * @param actions List of actions + * @param version SWF version + * @param path + * @return HilightedTextWriter with Source code + */ + public static HilightedTextWriter actionsToSource(final List actions, final int version, final String path, final HilightedTextWriter writer) { int timeout = Configuration.getConfig("decompilationTimeoutSingleMethod", 60); + int writerPos = writer.getLength(); try { - return Helper.timedCall(new Callable() { + Helper.timedCall(new Callable() { @Override - public String call() throws Exception { + public Void call() throws Exception { //List tree = actionsToTree(new HashMap(), actions, version); int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC; List tree = actionsToTree(new HashMap(), new HashMap(), new HashMap(), actions, version, staticOperation, path); - HilightedTextWriter writer = new HilightedTextWriter(highlight); - Graph.graphToString(tree, writer, true, new LocalData()); - String s = Graph.removeNonRefenrencedLoopLabels(writer.toString()); - return s; + Graph.graphToString(tree, writer, new LocalData()); + return null; } }, timeout, TimeUnit.SECONDS); } catch (TimeoutException ex) { Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error", ex); - return "/*\r\n * Decompilation error\r\n * Timeout (" + Helper.formatTimeToText(timeout) + ") was reached\r\n */"; + writer.setLength(writerPos); // remove already rendered code + writer.appendNoHilight("/*").newLine(); + writer.appendNoHilight(" * Decompilation error").newLine(); + writer.appendNoHilight(" * Timeout (" + Helper.formatTimeToText(timeout) + ") was reached").newLine(); + writer.appendNoHilight(" */"); } catch (Exception | OutOfMemoryError | StackOverflowError ex2) { Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error", ex2); if (ex2 instanceof OutOfMemoryError) { System.gc(); } - return "/*\r\n * Decompilation error\r\n * Code may be obfuscated\r\n * Error type: " + ex2.getClass().getSimpleName() + "\r\n */"; + writer.setLength(writerPos); // remove already rendered code + writer.appendNoHilight("/*").newLine(); + writer.appendNoHilight(" * Decompilation error").newLine(); + writer.appendNoHilight(" * Code may be obfuscated").newLine(); + writer.appendNoHilight(" * Error type: " + ex2.getClass().getSimpleName()).newLine(); + writer.appendNoHilight(" */"); } + return writer; } /** @@ -1202,7 +1227,9 @@ public class Action implements GraphSourceItem { } String s = null; try { - s = Action.actionsToString(new ArrayList(), address, ret, null, version, false, false, swfPos, path); + HilightedTextWriter writer = new HilightedTextWriter(false); + Action.actionsToString(new ArrayList(), address, ret, null, version, false, writer, swfPos, path); + s = writer.toString(); ret = ASMParser.parse(address, swfPos, true, s, SWF.DEFAULT_VERSION, false); } catch (Exception ex) { Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, "parsing error. path: " + path, ex); @@ -1230,8 +1257,9 @@ public class Action implements GraphSourceItem { } } - public String getASMSourceReplaced(List container, List knownAddreses, List constantPool, int version, boolean hex, boolean highlight) { - return getASMSource(container, knownAddreses, constantPool, version, hex); + public HilightedTextWriter getASMSourceReplaced(List container, List knownAddreses, List constantPool, int version, boolean hex, HilightedTextWriter writer) { + writer.appendNoHilight(getASMSource(container, knownAddreses, constantPool, version, hex)); + return writer; } public static double toFloatPoint(Object o) { diff --git a/trunk/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java b/trunk/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java index 5c2b97cec..afca854d0 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java @@ -99,7 +99,7 @@ public class FunctionActionItem extends ActionItem { writer.append(")").newLine(); writer.append("{").newLine(); writer.indent(); - Graph.graphToString(actions, writer, false, localData); + Graph.graphToString(actions, writer, localData); writer.unindent(); return writer.append("}"); } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/model/clauses/IfFrameLoadedActionItem.java b/trunk/src/com/jpexs/decompiler/flash/action/model/clauses/IfFrameLoadedActionItem.java index 677387bbc..697d2b4ad 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/model/clauses/IfFrameLoadedActionItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/model/clauses/IfFrameLoadedActionItem.java @@ -51,7 +51,7 @@ public class IfFrameLoadedActionItem extends ActionItem implements Block { writer.append(")").newLine(); writer.append("{").newLine(); writer.indent(); - Graph.graphToString(actions, writer, false, localData); + Graph.graphToString(actions, writer, localData); writer.unindent(); return writer.append("}"); } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java index 7dd7d3997..be134f839 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java @@ -27,7 +27,7 @@ import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; import com.jpexs.decompiler.flash.ecma.Null; import com.jpexs.decompiler.flash.ecma.Undefined; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.helpers.Helper; @@ -227,26 +227,26 @@ public class ActionPush extends Action { } @Override - public String getASMSourceReplaced(List container, List knownAddreses, List constantPool, int version, boolean hex, boolean highlight) { + public HilightedTextWriter getASMSourceReplaced(List container, List knownAddreses, List constantPool, int version, boolean hex, HilightedTextWriter writer) { if (replacement == null || replacement.size() < values.size()) { - return toString(highlight); + return toString(writer); } List oldVal = values; values = replacement; - String ts = toString(highlight); + toString(writer); values = oldVal; - return ts; + return writer; } - public String paramsToStringReplaced(List container, List knownAddreses, List constantPool, int version, boolean hex, boolean highlight) { + public HilightedTextWriter paramsToStringReplaced(List container, List knownAddreses, List constantPool, int version, boolean hex, HilightedTextWriter writer) { if (replacement == null || replacement.size() < values.size()) { - return paramsToString(highlight); + return paramsToString(writer); } List oldVal = values; values = replacement; - String ts = paramsToString(highlight); + paramsToString(writer); values = oldVal; - return ts; + return writer; } public String toStringNoQ(int i) { @@ -279,29 +279,32 @@ public class ActionPush extends Action { return ret; } - public String paramsToString(boolean highlight) { - String ret = ""; + public HilightedTextWriter paramsToString(HilightedTextWriter writer) { int pos = 0; for (int i = 0; i < values.size(); i++) { if (ignoredParts.contains(i)) { continue; } if (pos > 0) { - ret += " "; + writer.appendNoHilight(" "); } - ret += highlight ? Highlighting.hilighOffset(toString(i), getAddress() + pos + 1) : toString(i); + writer.append(toString(i), getAddress() + pos + 1); pos++; } - return ret; + return writer; } @Override public String toString() { - return "Push " + paramsToString(false); + HilightedTextWriter writer = new HilightedTextWriter(false); + toString(writer); + return writer.toString(); } - public String toString(boolean highlight) { - return "Push " + paramsToString(highlight); + public HilightedTextWriter toString(HilightedTextWriter writer) { + writer.appendNoHilight("Push "); + paramsToString(writer); + return writer; } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java b/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java index d7a5e26db..4e11faca0 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.model.FunctionActionItem; import com.jpexs.decompiler.flash.action.parser.ParseException; import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphSourceItemContainer; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -165,7 +166,7 @@ public class ActionDefineFunction extends Action implements GraphSourceItemConta } @Override - public String getASMSourceReplaced(List container, List knownAddreses, List constantPool, int version, boolean hex, boolean highlight) { + public HilightedTextWriter getASMSourceReplaced(List container, List knownAddreses, List constantPool, int version, boolean hex, HilightedTextWriter writer) { List oldParamNames = paramNames; if (replacedParamNames != null) { paramNames = replacedParamNames; @@ -177,7 +178,8 @@ public class ActionDefineFunction extends Action implements GraphSourceItemConta String ret = getASMSource(container, knownAddreses, constantPool, version, hex); paramNames = oldParamNames; functionName = oldFunctionName; - return ret; + writer.appendNoHilight(ret); + return writer; } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java b/trunk/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java index 720491cfe..38285b6a9 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.model.FunctionActionItem; import com.jpexs.decompiler.flash.action.parser.ParseException; import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphSourceItemContainer; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -232,7 +233,7 @@ public class ActionDefineFunction2 extends Action implements GraphSourceItemCont } @Override - public String getASMSourceReplaced(List container, List knownAddreses, List constantPool, int version, boolean hex, boolean highlight) { + public HilightedTextWriter getASMSourceReplaced(List container, List knownAddreses, List constantPool, int version, boolean hex, HilightedTextWriter writer) { List oldParamNames = paramNames; if (replacedParamNames != null) { paramNames = replacedParamNames; @@ -244,7 +245,8 @@ public class ActionDefineFunction2 extends Action implements GraphSourceItemCont String ret = getASMSource(container, knownAddreses, constantPool, version, hex); paramNames = oldParamNames; functionName = oldFunctionName; - return ret; + writer.appendNoHilight(ret); + return writer; } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java index fdaa64445..868165eb3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.avm2.parser.ParseException; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.gui.GraphFrame; import com.jpexs.decompiler.flash.gui.View; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.helpers.Helper; @@ -133,7 +134,9 @@ public class ASMSourceEditorPane extends LineMarkedEditorPane implements CaretLi if (bodyIndex == -1) { return; } - String textWithHexTags = abc.bodies[bodyIndex].code.toASMSource(abc.constants, trait, abc.method_info[abc.bodies[bodyIndex].method_info], abc.bodies[bodyIndex], true, true); + HilightedTextWriter writer = new HilightedTextWriter(true); + abc.bodies[bodyIndex].code.toASMSource(abc.constants, trait, abc.method_info[abc.bodies[bodyIndex].method_info], abc.bodies[bodyIndex], true, writer); + String textWithHexTags = writer.toString(); textWithHex = Helper.hexToComments(textWithHexTags); textNoHex = Helper.stripComments(textWithHexTags); setText(hex ? textWithHex : textNoHex); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index 059db05b2..4e11e3cd7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -28,8 +28,10 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import static com.jpexs.decompiler.flash.gui.AppStrings.translate; import com.jpexs.decompiler.flash.gui.View; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.graph.Graph; import com.jpexs.helpers.Cache; import java.util.ArrayList; import java.util.List; @@ -442,7 +444,6 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL public void cacheScriptPack(ScriptPack scriptLeaf, List abcList) { int maxCacheSize = 50; int scriptIndex = scriptLeaf.scriptIndex; - StringBuilder hilightedCodeBuf = new StringBuilder(); String hilightedCode = ""; ScriptInfo script = null; ABC abc = scriptLeaf.abc; @@ -450,11 +451,12 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL script = abc.script_info[scriptIndex]; } if (!cache.contains(scriptLeaf)) { + HilightedTextWriter writer = new HilightedTextWriter(true); for (int scriptTraitIndex : scriptLeaf.traitIndices) { - hilightedCodeBuf.append(script.traits.traits[scriptTraitIndex].convertPackaged(null, scriptLeaf.getPath().toString(), abcList, abc, false, false, scriptIndex, -1, true, new ArrayList(), Configuration.getConfig("parallelSpeedUp", true))); + script.traits.traits[scriptTraitIndex].convertPackaged(null, scriptLeaf.getPath().toString(), abcList, abc, false, false, scriptIndex, -1, writer, new ArrayList(), Configuration.getConfig("parallelSpeedUp", true)); } - - hilightedCode = hilightedCodeBuf.toString(); + String s = Graph.removeNonRefenrencedLoopLabels(writer.toString()); + hilightedCode = s; cache.put(scriptLeaf, new CachedDecompilation(hilightedCode)); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java index b27a4e97e..1ffa1f4cb 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java @@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.types.ValueKind; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import static com.jpexs.decompiler.flash.gui.AppStrings.translate; import com.jpexs.decompiler.flash.gui.View; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import java.awt.BorderLayout; import java.io.ByteArrayInputStream; @@ -89,8 +90,18 @@ public class SlotConstTraitDetailPanel extends JPanel implements TraitDetail { public void load(TraitSlotConst trait, ABC abc, boolean isStatic) { this.abc = abc; this.trait = trait; - boolean highlight = true; - String s = "trait " + Highlighting.hilighSpecial(highlight, abc.constants.multinameToString(trait.name_index), "traitname") + " " + Highlighting.hilighSpecial(highlight, (trait.isConst() ? "const" : "slot"), "traittype") + " slotid " + Highlighting.hilighSpecial(highlight, "" + trait.slot_id, "slotid") + " type " + Highlighting.hilighSpecial(highlight, abc.constants.multinameToString(trait.type_index), "traittypename") + " value " + Highlighting.hilighSpecial(highlight, (new ValueKind(trait.value_index, trait.value_kind).toASMString(abc.constants)), "traitvalue"); + HilightedTextWriter writer = new HilightedTextWriter(true); + writer.appendNoHilight("trait "); + writer.hilightSpecial(abc.constants.multinameToString(trait.name_index), "traitname"); + writer.appendNoHilight(" "); + writer.hilightSpecial(trait.isConst() ? "const" : "slot", "traittype"); + writer.appendNoHilight(" slotid "); + writer.hilightSpecial("" + trait.slot_id, "slotid"); + writer.appendNoHilight(" type "); + writer.hilightSpecial(abc.constants.multinameToString(trait.type_index), "traittypename"); + writer.appendNoHilight(" value "); + writer.hilightSpecial((new ValueKind(trait.value_index, trait.value_kind).toASMString(abc.constants)), "traitvalue"); + String s = writer.toString(); specialHilights = Highlighting.getSpecialHighlights(s); showWarning = trait.isConst() || isStatic; slotConstEditor.setText(Highlighting.stripHilights(s)); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java index b2170157a..3859fa0ef 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java @@ -5,6 +5,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.gui.AppStrings; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import java.util.ArrayList; import java.util.List; @@ -66,9 +67,13 @@ public class TraitsListItem { public String toString() { String s = ""; if ((type != Type.INITIALIZER) && isStatic) { - s = abc.class_info[classIndex].static_traits.traits[index].convertHeader(null, "", abcTags, abc, true, false, scriptIndex, classIndex, false, new ArrayList(), false); + HilightedTextWriter writer = new HilightedTextWriter(false); + abc.class_info[classIndex].static_traits.traits[index].convertHeader(null, "", abcTags, abc, true, false, scriptIndex, classIndex, writer, new ArrayList(), false); + s = writer.toString(); } else if ((type != Type.INITIALIZER) && (!isStatic)) { - s = abc.instance_info[classIndex].instance_traits.traits[index].convertHeader(null, "", abcTags, abc, false, false, scriptIndex, classIndex, false, new ArrayList(), false); + HilightedTextWriter writer = new HilightedTextWriter(false); + abc.instance_info[classIndex].instance_traits.traits[index].convertHeader(null, "", abcTags, abc, false, false, scriptIndex, classIndex, writer, new ArrayList(), false); + s = writer.toString(); } else if (!isStatic) { s = STR_INSTANCE_INITIALIZER; } else { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java index 57af4f5de..2cffab351 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java @@ -173,7 +173,7 @@ public class ActionPanel extends JPanel implements ActionListener { if (actions == null) { actions = src.getActions(SWF.DEFAULT_VERSION); } - String s = Action.actionsToSource(actions, SWF.DEFAULT_VERSION, src.toString()/*FIXME?*/, true); + String s = Action.actionsToSource(actions, SWF.DEFAULT_VERSION, src.toString()/*FIXME?*/, true, 0); List hilights = Highlighting.getInstrHighlights(s); String srcNoHex = Highlighting.stripHilights(s); cache.put(src, new CachedScript(srcNoHex, hilights)); @@ -309,7 +309,9 @@ public class ActionPanel extends JPanel implements ActionListener { asm.addDisassemblyListener(listener); List actions = asm.getActions(SWF.DEFAULT_VERSION); lastCode = actions; - lastDisasm = asm.getASMSource(SWF.DEFAULT_VERSION, true, true, actions); + HilightedTextWriter writer = new HilightedTextWriter(true); + asm.getASMSource(SWF.DEFAULT_VERSION, true, writer, actions); + lastDisasm = writer.toString(); asm.removeDisassemblyListener(listener); srcWithHex = Helper.hexToComments(lastDisasm); srcNoHex = Helper.stripComments(lastDisasm); diff --git a/trunk/src/com/jpexs/decompiler/flash/helpers/HilightedTextWriter.java b/trunk/src/com/jpexs/decompiler/flash/helpers/HilightedTextWriter.java index 1b1caf764..f77a45b3b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/helpers/HilightedTextWriter.java +++ b/trunk/src/com/jpexs/decompiler/flash/helpers/HilightedTextWriter.java @@ -35,15 +35,28 @@ public class HilightedTextWriter { private int indent = 0; private Stack offsets = new Stack<>(); private Stack loopStack = new Stack<>(); + private Stack stringAddedStack = new Stack<>(); + private boolean stringAdded = false; public HilightedTextWriter(boolean hilight) { this.hilight = hilight; } + public HilightedTextWriter(boolean hilight, int indent) { + this.hilight = hilight; + this.indent = indent; + } + public boolean getIsHighlighted() { return hilight; } + /** + * Highlights specified text as instruction by adding special tags + * + * @param offset Offset of instruction + * @return HilightedTextWriter + */ public HilightedTextWriter startOffset(GraphSourceItem src, int pos) { GraphSourceItemPosition itemPos = new GraphSourceItemPosition(); itemPos.graphSourceItem = src; @@ -57,20 +70,56 @@ public class HilightedTextWriter { return this; } + /** + * Highlights specified text as method by adding special tags + * + * @param index MethodInfo index + * @return HilightedTextWriter + */ public HilightedTextWriter startMethod(long index) { - if (hilight) { - appendNoHilight(Highlighting.HLOPEN); - appendNoHilight(Helper.escapeString("type=method;index=" + index)); - appendNoHilight(Highlighting.HLEND); - } - return this; + return start("type=method;index=" + index); } public HilightedTextWriter endMethod() { - if (hilight) { - appendNoHilight(Highlighting.HLCLOSE); - } - return this; + return end(); + } + + /** + * Highlights specified text as class by adding special tags + * + * @param index Class index + * @return HilightedTextWriter + */ + public HilightedTextWriter startClass(long index) { + return start("type=class;index=" + index); + } + + public HilightedTextWriter endClass() { + return end(); + } + + /** + * Highlights specified text as trait by adding special tags + * + * @param index Trait index + * @return HilightedTextWriter + */ + public HilightedTextWriter startTrait(long index) { + return start("type=trait;index=" + index); + } + + public HilightedTextWriter endTrait() { + return end(); + } + + public HilightedTextWriter hilightSpecial(String text, String type) { + return hilightSpecial(text, type, 0); + } + + public HilightedTextWriter hilightSpecial(String text, String type, int index) { + start("type=special;subtype=" + type + ";index=" + index); + appendNoHilight(text); + return end(); } public HilightedTextWriter startLoop(long loopId, int loopType) { @@ -115,23 +164,52 @@ public class HilightedTextWriter { return loop.loopId; } + public static String hilighOffset(String text, long offset) { + String data = "type=instruction;offset=" + offset; + return Highlighting.HLOPEN + Helper.escapeString(data) + Highlighting.HLEND + text + Highlighting.HLCLOSE; + } + public HilightedTextWriter append(String str) { GraphSourceItemPosition itemPos = offsets.peek(); GraphSourceItem src = itemPos.graphSourceItem; int pos = itemPos.position; if (src != null && hilight) { - appendToSb(Highlighting.hilighOffset(str, src.getOffset() + pos + 1)); + appendToSb(hilighOffset(str, src.getOffset() + pos + 1)); } else { appendToSb(str); } return this; } + public HilightedTextWriter append(String str, long offset) { + if (hilight) { + appendToSb(hilighOffset(str, offset)); + } else { + appendToSb(str); + } + return this; + } + + public HilightedTextWriter appendNoHilight(int i) { + appendNoHilight(Integer.toString(i)); + return this; + } + public HilightedTextWriter appendNoHilight(String str) { appendToSb(str); return this; } + public HilightedTextWriter appendWithoutIndent(String str) { + if (!newLine) { + newLine(); + } + newLine = false; + appendToSb(str); + newLine(); + return this; + } + public HilightedTextWriter indent() { indent++; return this; @@ -143,7 +221,7 @@ public class HilightedTextWriter { } public HilightedTextWriter newLine() { - sb.append("\r\n"); + appendToSb("\r\n"); newLine = true; return this; } @@ -155,21 +233,62 @@ public class HilightedTextWriter { } return this; } + + public HilightedTextWriter removeFromEnd(int count) { + sb.setLength(sb.length() - count); + return this; + } + public void setLength(int length) { + sb.setLength(length); + } + public int getLength() { return sb.length(); } + public int getIndent() { + return indent; + } + public String toString() { return sb.toString(); } + public void mark() { + stringAddedStack.add(stringAdded); + stringAdded = false; + } + + public boolean getMark() { + boolean result = stringAdded; + stringAdded = stringAddedStack.pop() || result; + return result; + } + + private HilightedTextWriter start(String data) { + if (hilight) { + sb.append(Highlighting.HLOPEN); + sb.append(Helper.escapeString(data)); + sb.append(Highlighting.HLEND); + } + return this; + } + + private HilightedTextWriter end() { + if (hilight) { + sb.append(Highlighting.HLCLOSE); + } + return this; + } + private void appendToSb(String str) { if (newLine) { newLine = false; appendIndent(); } sb.append(str); + stringAdded = true; } private void appendIndent() { diff --git a/trunk/src/com/jpexs/decompiler/flash/helpers/hilight/Highlighting.java b/trunk/src/com/jpexs/decompiler/flash/helpers/hilight/Highlighting.java index c4be38b92..c0f8f6698 100644 --- a/trunk/src/com/jpexs/decompiler/flash/helpers/hilight/Highlighting.java +++ b/trunk/src/com/jpexs/decompiler/flash/helpers/hilight/Highlighting.java @@ -164,10 +164,6 @@ public class Highlighting implements Serializable { public static final String HLEND = "\">"; public static final String HLCLOSE = ""; - public static String hilight(String text, String data) { - return HLOPEN + Helper.escapeString(data) + HLEND + text + HLCLOSE; - } - public static List getHilights(String text) { return getHilights(text, null); } @@ -219,63 +215,6 @@ public class Highlighting implements Serializable { return ret; } - /** - * Highlights specified text as instruction by adding special tags - * - * @param text Text to highlight - * @param offset Offset of instruction - * @return Highlighted text - */ - public static String hilighOffset(String text, long offset) { - return hilight(text, "type=instruction;offset=" + offset); - } - - public static String hilighSpecial(boolean higlight, String text, String type) { - return hilighSpecial(higlight, text, type, 0); - } - - public static String hilighSpecial(boolean higlight, String text, String type, long index) { - if (!higlight) { - return text; - } - return hilight(text, "type=special;subtype=" + type + ";index=" + index); - } - - /** - * Highlights specified text as method by adding special tags - * - * @param text Text to highlight - * @param index Methodinfo index - * @return Highlighted text - */ - public static String hilighMethod(String text, long index) { - return hilight(text, "type=method;index=" + index); - } - - /** - * Highlights specified text as trait by adding special tags - * - * @param text Text to highlight - * @param index Trait index - * @return Highlighted text - */ - public static String hilighTrait(String text, long index) { - - return hilight(text, "type=trait;index=" + index); - } - - /** - * Highlights specified text as class by adding special tags - * - * @param text Text to highlight - * @param index Class index - * @return Highlighted text - */ - public static String hilighClass(String text, long index) { - - return hilight(text, "type=class;index=" + index); - } - /** * Strips all highlights from the text * diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java index 706bb7fad..cee35d794 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java @@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.abc.CopyOutputStream; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionListReader; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.ButtonTag; @@ -136,11 +137,11 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT * @return ASM source */ @Override - public String getASMSource(int version, boolean hex, boolean highlight, List actions) { + public HilightedTextWriter getASMSource(int version, boolean hex, HilightedTextWriter writer, List actions) { if (actions == null) { actions = getActions(version); } - return Action.actionsToString(listeners, 0, actions, null, version, hex, highlight, getPos() + hdrSize, toString()/*FIXME?*/); + return Action.actionsToString(listeners, 0, actions, null, version, hex, writer, getPos() + hdrSize, toString()/*FIXME?*/); } /** diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DoActionTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DoActionTag.java index 98ccc3f98..fcd330631 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DoActionTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DoActionTag.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionListReader; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.helpers.ReReadableInputStream; import java.io.ByteArrayInputStream; @@ -74,11 +75,11 @@ public class DoActionTag extends Tag implements ASMSource { * @return ASM source */ @Override - public String getASMSource(int version, boolean hex, boolean highlight, List actions) { + public HilightedTextWriter getASMSource(int version, boolean hex, HilightedTextWriter writer, List actions) { if (actions == null) { actions = getActions(version); } - return Action.actionsToString(listeners, 0, actions, null, version, hex, highlight, getPos(), toString()/*FIXME?*/); + return Action.actionsToString(listeners, 0, actions, null, version, hex, writer, getPos(), toString()/*FIXME?*/); } /** diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DoInitActionTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DoInitActionTag.java index 30f9f00fb..1d11a97db 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DoInitActionTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DoInitActionTag.java @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionListReader; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; import com.jpexs.helpers.Helper; @@ -101,11 +102,11 @@ public class DoInitActionTag extends CharacterIdTag implements ASMSource { * @return ASM source */ @Override - public String getASMSource(int version, boolean hex, boolean highlight, List actions) { + public HilightedTextWriter getASMSource(int version, boolean hex, HilightedTextWriter writer, List actions) { if (actions == null) { actions = getActions(version); } - return Action.actionsToString(listeners, 0, actions, null, version, hex, highlight, getPos() + 2, toString()/*FIXME?*/); + return Action.actionsToString(listeners, 0, actions, null, version, hex, writer, getPos() + 2, toString()/*FIXME?*/); } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/ASMSource.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/ASMSource.java index 9a29ffdca..2c0f1f383 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/ASMSource.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/ASMSource.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.DisassemblyListener; import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import java.util.List; /** @@ -34,7 +35,7 @@ public interface ASMSource { * @param hex Add hexadecimal? * @return ASM source */ - public String getASMSource(int version, boolean hex, boolean highlight, List actions); + public HilightedTextWriter getASMSource(int version, boolean hex, HilightedTextWriter writer, List actions); /** * Whether or not this object contains ASM source diff --git a/trunk/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java b/trunk/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java index 437548cc3..7330968de 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.DisassemblyListener; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionListReader; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.flash.tags.base.ContainerItem; @@ -147,11 +148,11 @@ public class BUTTONCONDACTION implements ASMSource, Exportable, ContainerItem { * @return ASM source */ @Override - public String getASMSource(int version, boolean hex, boolean highlight, List actions) { + public HilightedTextWriter getASMSource(int version, boolean hex, HilightedTextWriter writer, List actions) { if (actions == null) { actions = getActions(version); } - return Action.actionsToString(listeners, 0, actions, null, version, hex, highlight, getPos() + 4, toString()/*FIXME?*/); + return Action.actionsToString(listeners, 0, actions, null, version, hex, writer, getPos() + 4, toString()/*FIXME?*/); } /** diff --git a/trunk/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java b/trunk/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java index 9ce791402..17bf27099 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.DisassemblyListener; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionListReader; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.flash.tags.base.ContainerItem; @@ -151,11 +152,11 @@ public class CLIPACTIONRECORD implements ASMSource, Exportable, ContainerItem { * @return ASM source */ @Override - public String getASMSource(int version, boolean hex, boolean highlight, List actions) { + public HilightedTextWriter getASMSource(int version, boolean hex, HilightedTextWriter writer, List actions) { if (actions == null) { actions = getActions(version); } - return Action.actionsToString(listeners, 0, actions, null, version, hex, highlight, getPos() + hdrPos, toString()/*FIXME?*/); + return Action.actionsToString(listeners, 0, actions, null, version, hex, writer, getPos() + hdrPos, toString()/*FIXME?*/); } /** diff --git a/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index b1211dca3..cca20bb78 100644 --- a/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -22,7 +22,6 @@ import com.jpexs.decompiler.flash.RunnableIOEx; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.tags.CSMTextSettingsTag; import com.jpexs.decompiler.flash.tags.DefineButton2Tag; import com.jpexs.decompiler.flash.tags.DefineButtonCxformTag; @@ -90,7 +89,6 @@ import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; import com.jpexs.decompiler.flash.types.sound.MP3FRAME; -import com.jpexs.helpers.Helper; import java.awt.Font; import java.awt.GraphicsEnvironment; import java.awt.Point; @@ -1112,8 +1110,8 @@ public class XFLConverter { } private static String convertActionScript(ASMSource as) { - String decompiledAS = Action.actionsToSource(as.getActions(SWF.DEFAULT_VERSION), SWF.DEFAULT_VERSION, as.toString(), false); - return as.getActionSourcePrefix() + Helper.indentRows(as.getActionSourceIndent(), decompiledAS, HilightedTextWriter.INDENT_STRING) + as.getActionSourceSuffix(); + String decompiledAS = Action.actionsToSource(as.getActions(SWF.DEFAULT_VERSION), SWF.DEFAULT_VERSION, as.toString(), false, as.getActionSourceIndent()); + return as.getActionSourcePrefix() + decompiledAS + as.getActionSourceSuffix(); } private static long getTimestamp() { diff --git a/trunk/src/com/jpexs/decompiler/graph/Graph.java b/trunk/src/com/jpexs/decompiler/graph/Graph.java index cadea32b2..e988620b8 100644 --- a/trunk/src/com/jpexs/decompiler/graph/Graph.java +++ b/trunk/src/com/jpexs/decompiler/graph/Graph.java @@ -2147,7 +2147,7 @@ public class Graph { * @param localData * @return String */ - public static HilightedTextWriter graphToString(List tree, HilightedTextWriter writer, boolean replaceIndents, LocalData localData) { + public static HilightedTextWriter graphToString(List tree, HilightedTextWriter writer, LocalData localData) { for (GraphTargetItem ti : tree) { if (!ti.isEmpty()) { ti.toStringSemicoloned(writer, localData).newLine(); diff --git a/trunk/src/com/jpexs/decompiler/graph/model/BlockItem.java b/trunk/src/com/jpexs/decompiler/graph/model/BlockItem.java index 1d98ec01a..e2af36a78 100644 --- a/trunk/src/com/jpexs/decompiler/graph/model/BlockItem.java +++ b/trunk/src/com/jpexs/decompiler/graph/model/BlockItem.java @@ -40,7 +40,7 @@ public class BlockItem extends GraphTargetItem { protected HilightedTextWriter appendTo(HilightedTextWriter writer, LocalData localData) { writer.append("{").newLine(); writer.indent(); - Graph.graphToString(commands, writer, false, localData); + Graph.graphToString(commands, writer, localData); writer.newLine(); writer.unindent(); return writer.append("}");